@arbidocs/react 0.5.111 → 0.5.113
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/account/client.js +96 -0
- package/dist/account/client.js.map +7 -0
- package/dist/account/delete.js +70 -0
- package/dist/account/delete.js.map +7 -0
- package/dist/account/didit.js +34 -0
- package/dist/account/didit.js.map +7 -0
- package/dist/account/dismissed-tips.js +33 -0
- package/dist/account/dismissed-tips.js.map +7 -0
- package/dist/account/email.js +84 -0
- package/dist/account/email.js.map +7 -0
- package/dist/account/entitlements.js +47 -0
- package/dist/account/entitlements.js.map +7 -0
- package/dist/account/identity.js +270 -0
- package/dist/account/identity.js.map +7 -0
- package/dist/account/index.js +93 -0
- package/dist/account/index.js.map +7 -0
- package/dist/account/notifications.js +59 -0
- package/dist/account/notifications.js.map +7 -0
- package/dist/account/password.js +103 -0
- package/dist/account/password.js.map +7 -0
- package/dist/account/profile.js +116 -0
- package/dist/account/profile.js.map +7 -0
- package/dist/account/recovery.js +13 -0
- package/dist/account/recovery.js.map +7 -0
- package/dist/account/relevance.js +82 -0
- package/dist/account/relevance.js.map +7 -0
- package/dist/account/sessions.js +37 -0
- package/dist/account/sessions.js.map +7 -0
- package/dist/account/settings.js +39 -0
- package/dist/account/settings.js.map +7 -0
- package/dist/account/table-views.js +16 -0
- package/dist/account/table-views.js.map +7 -0
- package/dist/ai/AiAnswer.js +83 -0
- package/dist/ai/AiAnswer.js.map +7 -0
- package/dist/ai/AiMarkdown.js +40 -0
- package/dist/ai/AiMarkdown.js.map +7 -0
- package/dist/ai/ArtifactCanvas.js +193 -0
- package/dist/ai/ArtifactCanvas.js.map +7 -0
- package/dist/ai/CitationRenderer.js +413 -0
- package/dist/ai/CitationRenderer.js.map +7 -0
- package/dist/{chunk-WL2Y2T47.js → ai/MarkdownRenderer.js} +35 -101
- package/dist/ai/MarkdownRenderer.js.map +7 -0
- package/dist/ai/MessageArtifactCard.js +75 -0
- package/dist/ai/MessageArtifactCard.js.map +7 -0
- package/dist/ai/PassageCard.js +79 -0
- package/dist/ai/PassageCard.js.map +7 -0
- package/dist/ai/engine.js +110 -0
- package/dist/ai/engine.js.map +7 -0
- package/dist/ai/index.js +63 -0
- package/dist/ai/index.js.map +7 -0
- package/dist/ai/markdown-base-components.js +37 -0
- package/dist/ai/markdown-base-components.js.map +7 -0
- package/dist/ai/markdown-streaming-context.js +6 -0
- package/dist/ai/markdown-streaming-context.js.map +7 -0
- package/dist/{chunk-VSCU7K4V.js → ai/normalize-citations.js} +12 -19
- package/dist/ai/normalize-citations.js.map +7 -0
- package/dist/ai/redline.js +41 -0
- package/dist/ai/redline.js.map +7 -0
- package/dist/ai/split-markdown-blocks.js +40 -0
- package/dist/ai/split-markdown-blocks.js.map +7 -0
- package/dist/{chunk-UW2SGTI5.js → ai/stored-markdown.js} +41 -93
- package/dist/ai/stored-markdown.js.map +7 -0
- package/dist/annotations/AnnotationPageOverlay.js +807 -0
- package/dist/annotations/AnnotationPageOverlay.js.map +7 -0
- package/dist/annotations/AnnotationToolbar.js +398 -0
- package/dist/annotations/AnnotationToolbar.js.map +7 -0
- package/dist/annotations/FreezeDialog.js +170 -0
- package/dist/annotations/FreezeDialog.js.map +7 -0
- package/dist/annotations/ProductionDialog.js +354 -0
- package/dist/annotations/ProductionDialog.js.map +7 -0
- package/dist/annotations/controller.js +49 -0
- package/dist/annotations/controller.js.map +7 -0
- package/dist/annotations/freeze/browser.js +21 -0
- package/dist/annotations/freeze/browser.js.map +7 -0
- package/dist/annotations/freeze/bundle.js +201 -0
- package/dist/annotations/freeze/bundle.js.map +7 -0
- package/dist/annotations/freeze/coords.js +37 -0
- package/dist/annotations/freeze/coords.js.map +7 -0
- package/dist/annotations/freeze/freeze.js +261 -0
- package/dist/annotations/freeze/freeze.js.map +7 -0
- package/dist/annotations/freeze/hash.js +28 -0
- package/dist/annotations/freeze/hash.js.map +7 -0
- package/dist/annotations/freeze/index-page.js +78 -0
- package/dist/annotations/freeze/index-page.js.map +7 -0
- package/dist/annotations/freeze/index.js +28 -22
- package/dist/annotations/freeze/index.js.map +7 -1
- package/dist/annotations/freeze/raster.js +208 -0
- package/dist/annotations/freeze/raster.js.map +7 -0
- package/dist/annotations/freeze/stamp.js +117 -0
- package/dist/annotations/freeze/stamp.js.map +7 -0
- package/dist/annotations/freeze/types.js +14 -0
- package/dist/annotations/freeze/types.js.map +7 -0
- package/dist/annotations/freeze/vector.js +283 -0
- package/dist/annotations/freeze/vector.js.map +7 -0
- package/dist/annotations/geometry.js +81 -0
- package/dist/annotations/geometry.js.map +7 -0
- package/dist/annotations/index.js +125 -6
- package/dist/annotations/index.js.map +7 -1
- package/dist/annotations/merge.js +53 -0
- package/dist/annotations/merge.js.map +7 -0
- package/dist/{chunk-T3USOSVN.js → annotations/model.js} +23 -16
- package/dist/annotations/model.js.map +7 -0
- package/dist/annotations/overlay-geometry.js +41 -0
- package/dist/annotations/overlay-geometry.js.map +7 -0
- package/dist/annotations/redaction-log.js +33 -0
- package/dist/annotations/redaction-log.js.map +7 -0
- package/dist/annotations/selection-marks.js +122 -0
- package/dist/annotations/selection-marks.js.map +7 -0
- package/dist/annotations/state.js +140 -0
- package/dist/annotations/state.js.map +7 -0
- package/dist/annotations/store.js +49 -0
- package/dist/annotations/store.js.map +7 -0
- package/dist/annotations/useAnnotationLayer.js +306 -0
- package/dist/annotations/useAnnotationLayer.js.map +7 -0
- package/dist/annotations/useAnnotationShortcuts.js +31 -0
- package/dist/annotations/useAnnotationShortcuts.js.map +7 -0
- package/dist/annotations/useTextSelectionMarks.js +100 -0
- package/dist/annotations/useTextSelectionMarks.js.map +7 -0
- package/dist/artifacts/artifact-kind.js +19 -0
- package/dist/artifacts/artifact-kind.js.map +7 -0
- package/dist/artifacts/index.js +89 -571
- package/dist/artifacts/index.js.map +7 -1
- package/dist/{chunk-WUTL62MC.js → artifacts/normalize-markdown.js} +12 -14
- package/dist/artifacts/normalize-markdown.js.map +7 -0
- package/dist/artifacts/redline-core.js +12 -3
- package/dist/artifacts/redline-core.js.map +7 -1
- package/dist/{chunk-74N436VK.js → artifacts/redline-diff.js} +10 -9
- package/dist/artifacts/redline-diff.js.map +7 -0
- package/dist/artifacts/redline-engine.js +14 -0
- package/dist/artifacts/redline-engine.js.map +7 -0
- package/dist/artifacts/renderArtifactMarkdown.js +9 -0
- package/dist/artifacts/renderArtifactMarkdown.js.map +7 -0
- package/dist/artifacts/useArtifactEditSession.js +183 -0
- package/dist/artifacts/useArtifactEditSession.js.map +7 -0
- package/dist/artifacts/useArtifactSession.js +173 -0
- package/dist/artifacts/useArtifactSession.js.map +7 -0
- package/dist/artifacts/useArtifactSource.js +16 -0
- package/dist/artifacts/useArtifactSource.js.map +7 -0
- package/dist/artifacts/useArtifactText.js +78 -0
- package/dist/artifacts/useArtifactText.js.map +7 -0
- package/dist/artifacts/useRedline.js +65 -0
- package/dist/artifacts/useRedline.js.map +7 -0
- package/dist/artifacts/useStreamedArtifact.js +74 -0
- package/dist/artifacts/useStreamedArtifact.js.map +7 -0
- package/dist/artifacts/versions.js +68 -0
- package/dist/artifacts/versions.js.map +7 -0
- package/dist/billing.js +200 -0
- package/dist/billing.js.map +7 -0
- package/dist/boot-timeout.js +19 -0
- package/dist/boot-timeout.js.map +7 -0
- package/dist/calendar/accounts.js +213 -0
- package/dist/calendar/accounts.js.map +7 -0
- package/dist/calendar/hooks.js +409 -0
- package/dist/calendar/hooks.js.map +7 -0
- package/dist/calendar/index.js +31 -0
- package/dist/calendar/index.js.map +7 -0
- package/dist/calendar/keys.js +5 -0
- package/dist/calendar/keys.js.map +7 -0
- package/dist/calendar/offline/outbox.js +231 -0
- package/dist/calendar/offline/outbox.js.map +7 -0
- package/dist/calendar/offline/runtime.js +109 -0
- package/dist/calendar/offline/runtime.js.map +7 -0
- package/dist/calendar/offline/support.js +41 -0
- package/dist/calendar/offline/support.js.map +7 -0
- package/dist/calendar/support.js +34 -0
- package/dist/calendar/support.js.map +7 -0
- package/dist/calls/actions.js +226 -0
- package/dist/calls/actions.js.map +7 -0
- package/dist/calls/events.js +138 -0
- package/dist/calls/events.js.map +7 -0
- package/dist/calls/gate.js +19 -0
- package/dist/calls/gate.js.map +7 -0
- package/dist/calls/hooks.js +115 -0
- package/dist/calls/hooks.js.map +7 -0
- package/dist/calls/in-call-chat.js +132 -0
- package/dist/calls/in-call-chat.js.map +7 -0
- package/dist/calls/index.js +24 -0
- package/dist/calls/index.js.map +7 -0
- package/dist/calls/keys.js +17 -0
- package/dist/calls/keys.js.map +7 -0
- package/dist/calls/livekit/index.js +6 -958
- package/dist/calls/livekit/index.js.map +7 -1
- package/dist/calls/livekit/room.js +98 -0
- package/dist/calls/livekit/room.js.map +7 -0
- package/dist/calls/livekit/useCallRecorder.js +219 -0
- package/dist/calls/livekit/useCallRecorder.js.map +7 -0
- package/dist/calls/livekit/useCallTranscriber.js +309 -0
- package/dist/calls/livekit/useCallTranscriber.js.map +7 -0
- package/dist/calls/livekit/useHostMuteNotice.js +29 -0
- package/dist/calls/livekit/useHostMuteNotice.js.map +7 -0
- package/dist/calls/livekit/useInCallChat.js +161 -0
- package/dist/calls/livekit/useInCallChat.js.map +7 -0
- package/dist/calls/livekit/useWebinar.js +239 -0
- package/dist/calls/livekit/useWebinar.js.map +7 -0
- package/dist/calls/meeting-chat.js +149 -0
- package/dist/calls/meeting-chat.js.map +7 -0
- package/dist/calls/moderation.js +50 -0
- package/dist/calls/moderation.js.map +7 -0
- package/dist/calls/open-meeting-chat.js +29 -0
- package/dist/calls/open-meeting-chat.js.map +7 -0
- package/dist/calls/read-only.js +24 -0
- package/dist/calls/read-only.js.map +7 -0
- package/dist/calls/recording-media.js +218 -0
- package/dist/calls/recording-media.js.map +7 -0
- package/dist/calls/recording-playback.js +260 -0
- package/dist/calls/recording-playback.js.map +7 -0
- package/dist/calls/recording.js +268 -0
- package/dist/calls/recording.js.map +7 -0
- package/dist/calls/save-to-thread.js +80 -0
- package/dist/calls/save-to-thread.js.map +7 -0
- package/dist/calls/session.js +134 -0
- package/dist/calls/session.js.map +7 -0
- package/dist/calls/transcript-format.js +147 -0
- package/dist/calls/transcript-format.js.map +7 -0
- package/dist/calls/transcription.js +101 -0
- package/dist/calls/transcription.js.map +7 -0
- package/dist/calls/webinar.js +71 -0
- package/dist/calls/webinar.js.map +7 -0
- package/dist/charge-watch.js +71 -0
- package/dist/charge-watch.js.map +7 -0
- package/dist/chat/ChatBubble.js +146 -0
- package/dist/chat/ChatBubble.js.map +7 -0
- package/dist/chat/ConversationScope.js +30 -0
- package/dist/chat/ConversationScope.js.map +7 -0
- package/dist/chat/active-config.js +20 -0
- package/dist/chat/active-config.js.map +7 -0
- package/dist/chat/agent-chat-owner.js +25 -0
- package/dist/chat/agent-chat-owner.js.map +7 -0
- package/dist/chat/chat-artifacts.js +64 -0
- package/dist/chat/chat-artifacts.js.map +7 -0
- package/dist/chat/citations.js +32 -0
- package/dist/chat/citations.js.map +7 -0
- package/dist/chat/config-model.js +10 -0
- package/dist/chat/config-model.js.map +7 -0
- package/dist/chat/conversation-cache.js +676 -0
- package/dist/chat/conversation-cache.js.map +7 -0
- package/dist/chat/conversation-events.js +57 -0
- package/dist/chat/conversation-events.js.map +7 -0
- package/dist/chat/conversation-mentions.js +58 -0
- package/dist/chat/conversation-mentions.js.map +7 -0
- package/dist/chat/conversation-workspace.js +58 -0
- package/dist/chat/conversation-workspace.js.map +7 -0
- package/dist/chat/mentions.js +116 -0
- package/dist/chat/mentions.js.map +7 -0
- package/dist/chat/open-document.js +106 -0
- package/dist/chat/open-document.js.map +7 -0
- package/dist/chat/orphaned.js +44 -0
- package/dist/chat/orphaned.js.map +7 -0
- package/dist/chat/pendingFirstTurn.js +30 -0
- package/dist/chat/pendingFirstTurn.js.map +7 -0
- package/dist/chat/reply-target.js +12 -0
- package/dist/chat/reply-target.js.map +7 -0
- package/dist/chat/run-finished.js +28 -0
- package/dist/chat/run-finished.js.map +7 -0
- package/dist/chat/run-state.js +91 -0
- package/dist/chat/run-state.js.map +7 -0
- package/dist/chat/stream-handlers.js +419 -0
- package/dist/chat/stream-handlers.js.map +7 -0
- package/dist/chat/thread-binding.js +76 -0
- package/dist/chat/thread-binding.js.map +7 -0
- package/dist/chat/thread-document.js +53 -0
- package/dist/chat/thread-document.js.map +7 -0
- package/dist/chat/turn-control.js +79 -0
- package/dist/chat/turn-control.js.map +7 -0
- package/dist/chat/useAgentRunControl.js +36 -0
- package/dist/chat/useAgentRunControl.js.map +7 -0
- package/dist/chat/useAnswerAgentQuestion.js +19 -0
- package/dist/chat/useAnswerAgentQuestion.js.map +7 -0
- package/dist/chat/useAskAgain.js +32 -0
- package/dist/chat/useAskAgain.js.map +7 -0
- package/dist/chat/useAutoSendDraft.js +17 -0
- package/dist/chat/useAutoSendDraft.js.map +7 -0
- package/dist/chat/useBranchNavigation.js +97 -0
- package/dist/chat/useBranchNavigation.js.map +7 -0
- package/dist/chat/useConnectRunStream.js +169 -0
- package/dist/chat/useConnectRunStream.js.map +7 -0
- package/dist/chat/useConversation.js +431 -0
- package/dist/chat/useConversation.js.map +7 -0
- package/dist/chat/useConversationActions.js +662 -0
- package/dist/chat/useConversationActions.js.map +7 -0
- package/dist/chat/useConversationData.js +143 -0
- package/dist/chat/useConversationData.js.map +7 -0
- package/dist/chat/useConversationDocuments.js +41 -0
- package/dist/chat/useConversationDocuments.js.map +7 -0
- package/dist/chat/useConversationSettings.js +78 -0
- package/dist/chat/useConversationSettings.js.map +7 -0
- package/dist/chat/useConversationTurn.js +31 -0
- package/dist/chat/useConversationTurn.js.map +7 -0
- package/dist/chat/useConversationWorkspace.js +12 -0
- package/dist/chat/useConversationWorkspace.js.map +7 -0
- package/dist/chat/useDeleteMessage.js +15 -0
- package/dist/chat/useDeleteMessage.js.map +7 -0
- package/dist/chat/useDocumentAutoAdd.js +73 -0
- package/dist/chat/useDocumentAutoAdd.js.map +7 -0
- package/dist/chat/useMessageTimer.js +39 -0
- package/dist/chat/useMessageTimer.js.map +7 -0
- package/dist/chat/useThinkingContent.js +67 -0
- package/dist/chat/useThinkingContent.js.map +7 -0
- package/dist/chat/useThreadDocument.js +61 -0
- package/dist/chat/useThreadDocument.js.map +7 -0
- package/dist/chat/workflow-run-titles.js +50 -0
- package/dist/chat/workflow-run-titles.js.map +7 -0
- package/dist/config/config-hooks.js +209 -0
- package/dist/config/config-hooks.js.map +7 -0
- package/dist/connectivity.js +72 -0
- package/dist/connectivity.js.map +7 -0
- package/dist/connectors/hooks.js +263 -0
- package/dist/connectors/hooks.js.map +7 -0
- package/dist/connectors/index.js +28 -0
- package/dist/connectors/index.js.map +7 -0
- package/dist/contacts.js +100 -0
- package/dist/contacts.js.map +7 -0
- package/dist/conversation-list.js +65 -0
- package/dist/conversation-list.js.map +7 -0
- package/dist/databases.js +195 -0
- package/dist/databases.js.map +7 -0
- package/dist/datasets/aggregate.js +281 -0
- package/dist/datasets/aggregate.js.map +7 -0
- package/dist/datasets/index.js +122 -0
- package/dist/datasets/index.js.map +7 -0
- package/dist/datasets/members.js +27 -0
- package/dist/datasets/members.js.map +7 -0
- package/dist/datasets/panel.js +44 -0
- package/dist/datasets/panel.js.map +7 -0
- package/dist/datasets/registry.js +47 -0
- package/dist/datasets/registry.js.map +7 -0
- package/dist/datasets/rows-source.js +44 -0
- package/dist/datasets/rows-source.js.map +7 -0
- package/dist/datasets/sources/activity.js +83 -0
- package/dist/datasets/sources/activity.js.map +7 -0
- package/dist/datasets/sources/conversations.js +74 -0
- package/dist/datasets/sources/conversations.js.map +7 -0
- package/dist/datasets/sources/database.js +209 -0
- package/dist/datasets/sources/database.js.map +7 -0
- package/dist/datasets/sources/documents.js +93 -0
- package/dist/datasets/sources/documents.js.map +7 -0
- package/dist/datasets/sources/facts.js +56 -0
- package/dist/datasets/sources/facts.js.map +7 -0
- package/dist/datasets/sources/projects.js +117 -0
- package/dist/datasets/sources/projects.js.map +7 -0
- package/dist/datasets/sources/tags.js +67 -0
- package/dist/datasets/sources/tags.js.map +7 -0
- package/dist/datasets/sources/usage.js +268 -0
- package/dist/datasets/sources/usage.js.map +7 -0
- package/dist/datasets/sources/workflows.js +91 -0
- package/dist/datasets/sources/workflows.js.map +7 -0
- package/dist/datasets/sources/workspaces.js +67 -0
- package/dist/datasets/sources/workspaces.js.map +7 -0
- package/dist/datasets/store.js +194 -0
- package/dist/datasets/store.js.map +7 -0
- package/dist/datasets/types.js +14 -0
- package/dist/datasets/types.js.map +7 -0
- package/dist/directmessages/ConversationList.js +148 -0
- package/dist/directmessages/ConversationList.js.map +7 -0
- package/dist/directmessages/DateSeparator.js +8 -0
- package/dist/directmessages/DateSeparator.js.map +7 -0
- package/dist/directmessages/DmAvatar.js +29 -0
- package/dist/directmessages/DmAvatar.js.map +7 -0
- package/dist/directmessages/DmComposer.js +201 -0
- package/dist/directmessages/DmComposer.js.map +7 -0
- package/dist/directmessages/arrivals.js +29 -0
- package/dist/directmessages/arrivals.js.map +7 -0
- package/dist/directmessages/chat-cache.js +192 -0
- package/dist/directmessages/chat-cache.js.map +7 -0
- package/dist/directmessages/grouping.js +26 -0
- package/dist/directmessages/grouping.js.map +7 -0
- package/dist/directmessages/index.js +81 -0
- package/dist/directmessages/index.js.map +7 -0
- package/dist/directmessages/useChats.js +266 -0
- package/dist/directmessages/useChats.js.map +7 -0
- package/dist/directmessages/utils.js +23 -0
- package/dist/directmessages/utils.js.map +7 -0
- package/dist/document-tools/can-annotate.js +7 -0
- package/dist/document-tools/can-annotate.js.map +7 -0
- package/dist/document-tools/core.js +218 -12
- package/dist/document-tools/core.js.map +7 -1
- package/dist/document-tools/document-pdf.js +76 -0
- package/dist/document-tools/document-pdf.js.map +7 -0
- package/dist/document-tools/environment.js +136 -0
- package/dist/document-tools/environment.js.map +7 -0
- package/dist/document-tools/file-shares.js +112 -0
- package/dist/document-tools/file-shares.js.map +7 -0
- package/dist/document-tools/frozen-copy.js +27 -0
- package/dist/document-tools/frozen-copy.js.map +7 -0
- package/dist/document-tools/index.js +26 -148
- package/dist/document-tools/index.js.map +7 -1
- package/dist/document-tools/markup-download.js +51 -0
- package/dist/document-tools/markup-download.js.map +7 -0
- package/dist/document-tools/markup-store.js +138 -0
- package/dist/document-tools/markup-store.js.map +7 -0
- package/dist/document-tools/markup-transfer.js +88 -0
- package/dist/document-tools/markup-transfer.js.map +7 -0
- package/dist/document-tools/production.js +147 -0
- package/dist/document-tools/production.js.map +7 -0
- package/dist/document-tools/saved-signature.js +90 -0
- package/dist/document-tools/saved-signature.js.map +7 -0
- package/dist/document-tools/signature-requests.js +310 -0
- package/dist/document-tools/signature-requests.js.map +7 -0
- package/dist/document-tools/signing.js +127 -0
- package/dist/document-tools/signing.js.map +7 -0
- package/dist/document-tools/useDocumentBytes.js +38 -0
- package/dist/document-tools/useDocumentBytes.js.map +7 -0
- package/dist/document-tools/useDocumentMarkup.js +154 -0
- package/dist/document-tools/useDocumentMarkup.js.map +7 -0
- package/dist/document-tools/useIsOnline.js +13 -0
- package/dist/document-tools/useIsOnline.js.map +7 -0
- package/dist/document-tools/verification.js +60 -0
- package/dist/document-tools/verification.js.map +7 -0
- package/dist/documents/DocumentReview.js +220 -0
- package/dist/documents/DocumentReview.js.map +7 -0
- package/dist/documents/DraftTitleControls.js +41 -0
- package/dist/documents/DraftTitleControls.js.map +7 -0
- package/dist/documents/InlineMicButton.js +90 -0
- package/dist/documents/InlineMicButton.js.map +7 -0
- package/dist/documents/MicRecordingOverlay.js +29 -0
- package/dist/documents/MicRecordingOverlay.js.map +7 -0
- package/dist/documents/MicWaveformIndicator.js +68 -0
- package/dist/documents/MicWaveformIndicator.js.map +7 -0
- package/dist/documents/PhotoCapture.js +120 -0
- package/dist/documents/PhotoCapture.js.map +7 -0
- package/dist/documents/VideoCapture.js +129 -0
- package/dist/documents/VideoCapture.js.map +7 -0
- package/dist/documents/VoiceNoteRecorder.js +166 -0
- package/dist/documents/VoiceNoteRecorder.js.map +7 -0
- package/dist/documents/audio-segmenter.js +63 -0
- package/dist/documents/audio-segmenter.js.map +7 -0
- package/dist/documents/capture-frame.js +21 -0
- package/dist/documents/capture-frame.js.map +7 -0
- package/dist/documents/chunked-recorder.js +190 -0
- package/dist/documents/chunked-recorder.js.map +7 -0
- package/dist/documents/document-download.js +53 -0
- package/dist/documents/document-download.js.map +7 -0
- package/dist/documents/document-fields.js +109 -0
- package/dist/documents/document-fields.js.map +7 -0
- package/dist/documents/documents-cache.js +110 -0
- package/dist/documents/documents-cache.js.map +7 -0
- package/dist/documents/documents-data.js +128 -0
- package/dist/documents/documents-data.js.map +7 -0
- package/dist/documents/documents-loader.js +113 -0
- package/dist/documents/documents-loader.js.map +7 -0
- package/dist/documents/documents-writes.js +448 -0
- package/dist/documents/documents-writes.js.map +7 -0
- package/dist/documents/format-elapsed.js +10 -0
- package/dist/documents/format-elapsed.js.map +7 -0
- package/dist/documents/has-video-track.js +26 -0
- package/dist/documents/has-video-track.js.map +7 -0
- package/dist/documents/index.js +266 -0
- package/dist/documents/index.js.map +7 -0
- package/dist/documents/media-error.js +18 -0
- package/dist/documents/media-error.js.map +7 -0
- package/dist/documents/offline-documents.js +160 -0
- package/dist/documents/offline-documents.js.map +7 -0
- package/dist/documents/pending-sync.js +210 -0
- package/dist/documents/pending-sync.js.map +7 -0
- package/dist/documents/processing-live.js +122 -0
- package/dist/documents/processing-live.js.map +7 -0
- package/dist/documents/processing-order.js +59 -0
- package/dist/documents/processing-order.js.map +7 -0
- package/dist/documents/processing-settle.js +21 -0
- package/dist/documents/processing-settle.js.map +7 -0
- package/dist/documents/related-documents.js +133 -0
- package/dist/documents/related-documents.js.map +7 -0
- package/dist/documents/support.js +29 -0
- package/dist/documents/support.js.map +7 -0
- package/dist/documents/upload-files.js +169 -0
- package/dist/documents/upload-files.js.map +7 -0
- package/dist/documents/useAudioRecorder.js +315 -0
- package/dist/documents/useAudioRecorder.js.map +7 -0
- package/dist/documents/useCameraStream.js +35 -0
- package/dist/documents/useCameraStream.js.map +7 -0
- package/dist/documents/useDocumentThumbnails.js +71 -0
- package/dist/documents/useDocumentThumbnails.js.map +7 -0
- package/dist/documents/useDownloadDocuments.js +90 -0
- package/dist/documents/useDownloadDocuments.js.map +7 -0
- package/dist/documents/usePassageQuotes.js +37 -0
- package/dist/documents/usePassageQuotes.js.map +7 -0
- package/dist/documents/useUploadFiles.js +165 -0
- package/dist/documents/useUploadFiles.js.map +7 -0
- package/dist/documents/useUploadFromUrls.js +63 -0
- package/dist/documents/useUploadFromUrls.js.map +7 -0
- package/dist/documents/useVideoRecorder.js +62 -0
- package/dist/documents/useVideoRecorder.js.map +7 -0
- package/dist/entities/AgentMarkers.js +61 -0
- package/dist/entities/AgentMarkers.js.map +7 -0
- package/dist/entities/DocumentEntity.js +125 -0
- package/dist/entities/DocumentEntity.js.map +7 -0
- package/dist/entities/EntityPill.js +250 -0
- package/dist/entities/EntityPill.js.map +7 -0
- package/dist/entities/ProjectEntity.js +61 -0
- package/dist/entities/ProjectEntity.js.map +7 -0
- package/dist/entities/ShieldIcon.js +49 -0
- package/dist/entities/ShieldIcon.js.map +7 -0
- package/dist/entities/TagEntity.js +79 -0
- package/dist/entities/TagEntity.js.map +7 -0
- package/dist/entities/ThreadVisibilityIcon.js +15 -0
- package/dist/entities/ThreadVisibilityIcon.js.map +7 -0
- package/dist/entities/UserEntity.js +211 -0
- package/dist/entities/UserEntity.js.map +7 -0
- package/dist/entities/VerifiedBadge.js +19 -0
- package/dist/entities/VerifiedBadge.js.map +7 -0
- package/dist/entities/agent-avatar-colors.js +26 -0
- package/dist/entities/agent-avatar-colors.js.map +7 -0
- package/dist/entities/colors.js +64 -0
- package/dist/entities/colors.js.map +7 -0
- package/dist/entities/file-type.js +151 -0
- package/dist/entities/file-type.js.map +7 -0
- package/dist/entities/index.js +100 -0
- package/dist/entities/index.js.map +7 -0
- package/dist/entities/media-type.js +61 -0
- package/dist/entities/media-type.js.map +7 -0
- package/dist/entities/registry.js +385 -0
- package/dist/entities/registry.js.map +7 -0
- package/dist/entities/status.js +43 -0
- package/dist/entities/status.js.map +7 -0
- package/dist/entities/tag-kinds.js +23 -0
- package/dist/entities/tag-kinds.js.map +7 -0
- package/dist/entities/tag-types.js +44 -0
- package/dist/entities/tag-types.js.map +7 -0
- package/dist/entities/vocabulary.js +12 -0
- package/dist/entities/vocabulary.js.map +7 -0
- package/dist/entity-extraction.js +25 -0
- package/dist/entity-extraction.js.map +7 -0
- package/dist/facts-search.js +57 -0
- package/dist/facts-search.js.map +7 -0
- package/dist/facts.js +69 -0
- package/dist/facts.js.map +7 -0
- package/dist/hooks.js +320 -0
- package/dist/hooks.js.map +7 -0
- package/dist/host/ArbiHost.js +24 -0
- package/dist/host/ArbiHost.js.map +7 -0
- package/dist/host/assistant-copy.js +54 -0
- package/dist/host/assistant-copy.js.map +7 -0
- package/dist/host/config.js +9 -0
- package/dist/host/config.js.map +7 -0
- package/dist/host/context.js +10 -0
- package/dist/host/context.js.map +7 -0
- package/dist/host/features.js +144 -0
- package/dist/host/features.js.map +7 -0
- package/dist/host/index.js +12 -0
- package/dist/host/index.js.map +7 -0
- package/dist/{chunk-DPYBZDJB.js → host/merge.js} +7 -7
- package/dist/host/merge.js.map +7 -0
- package/dist/house-template.js +40 -0
- package/dist/house-template.js.map +7 -0
- package/dist/icons/AppleIcon.js +25 -0
- package/dist/icons/AppleIcon.js.map +7 -0
- package/dist/icons/ArbiBotHeadIcon.js +46 -0
- package/dist/icons/ArbiBotHeadIcon.js.map +7 -0
- package/dist/icons/ArbiIcon.js +24 -0
- package/dist/icons/ArbiIcon.js.map +7 -0
- package/dist/icons/AudIcon.js +56 -0
- package/dist/icons/AudIcon.js.map +7 -0
- package/dist/icons/ClaudeIcon.js +28 -0
- package/dist/icons/ClaudeIcon.js.map +7 -0
- package/dist/icons/DocIcon.js +56 -0
- package/dist/icons/DocIcon.js.map +7 -0
- package/dist/icons/EmlIcon.js +57 -0
- package/dist/icons/EmlIcon.js.map +7 -0
- package/dist/icons/FireworksIcon.js +47 -0
- package/dist/icons/FireworksIcon.js.map +7 -0
- package/dist/icons/GeminiIcon.js +37 -0
- package/dist/icons/GeminiIcon.js.map +7 -0
- package/dist/icons/GitHubIcon.js +32 -0
- package/dist/icons/GitHubIcon.js.map +7 -0
- package/dist/icons/GoogleIcon.js +53 -0
- package/dist/icons/GoogleIcon.js.map +7 -0
- package/dist/icons/HtmlIcon.js +56 -0
- package/dist/icons/HtmlIcon.js.map +7 -0
- package/dist/icons/ImgIcon.js +56 -0
- package/dist/icons/ImgIcon.js.map +7 -0
- package/dist/icons/LinkedInIcon.js +25 -0
- package/dist/icons/LinkedInIcon.js.map +7 -0
- package/dist/icons/OpenAIIcon.js +28 -0
- package/dist/icons/OpenAIIcon.js.map +7 -0
- package/dist/icons/PdfIcon.js +56 -0
- package/dist/icons/PdfIcon.js.map +7 -0
- package/dist/icons/ProviderIcon.js +42 -0
- package/dist/icons/ProviderIcon.js.map +7 -0
- package/dist/icons/TxtIcon.js +56 -0
- package/dist/icons/TxtIcon.js.map +7 -0
- package/dist/icons/VidIcon.js +56 -0
- package/dist/icons/VidIcon.js.map +7 -0
- package/dist/icons/XlsIcon.js +56 -0
- package/dist/icons/XlsIcon.js.map +7 -0
- package/dist/icons/arbi-mark.js +5 -0
- package/dist/icons/arbi-mark.js.map +7 -0
- package/dist/icons/colors.js +31 -0
- package/dist/icons/colors.js.map +7 -0
- package/dist/icons/file-type.js +105 -0
- package/dist/icons/file-type.js.map +7 -0
- package/dist/icons/index.js +55 -0
- package/dist/icons/index.js.map +7 -0
- package/dist/imagecrop/ImageCropModal.js +56 -0
- package/dist/imagecrop/ImageCropModal.js.map +7 -0
- package/dist/imagecrop/ImageCropper.js +100 -0
- package/dist/imagecrop/ImageCropper.js.map +7 -0
- package/dist/imagecrop/cropImage.js +43 -0
- package/dist/imagecrop/cropImage.js.map +7 -0
- package/dist/imagecrop/index.js +13 -0
- package/dist/imagecrop/index.js.map +7 -0
- package/dist/index.js +702 -17116
- package/dist/index.js.map +7 -1
- package/dist/{chunk-SSXFVWCT.js → lazy-chunk.js} +8 -8
- package/dist/lazy-chunk.js.map +7 -0
- package/dist/lib/collision-padding.js +13 -0
- package/dist/lib/collision-padding.js.map +7 -0
- package/dist/lib/format-friendly-date.js +55 -0
- package/dist/lib/format-friendly-date.js.map +7 -0
- package/dist/lib/format-relative-time.js +52 -0
- package/dist/lib/format-relative-time.js.map +7 -0
- package/dist/lib/markdown-to-text.js +35 -0
- package/dist/lib/markdown-to-text.js.map +7 -0
- package/dist/lib/toast-interaction.js +9 -0
- package/dist/lib/toast-interaction.js.map +7 -0
- package/dist/lib/utils.js +9 -0
- package/dist/lib/utils.js.map +7 -0
- package/dist/mail/client.js +103 -0
- package/dist/mail/client.js.map +7 -0
- package/dist/mail/document-attachment.js +38 -0
- package/dist/mail/document-attachment.js.map +7 -0
- package/dist/mail/filing.js +132 -0
- package/dist/mail/filing.js.map +7 -0
- package/dist/mail/hooks.js +393 -0
- package/dist/mail/hooks.js.map +7 -0
- package/dist/mail/index.js +120 -0
- package/dist/mail/index.js.map +7 -0
- package/dist/mail/offline/changes.js +258 -0
- package/dist/mail/offline/changes.js.map +7 -0
- package/dist/mail/offline/confirm-sign-out.js +37 -0
- package/dist/mail/offline/confirm-sign-out.js.map +7 -0
- package/dist/mail/offline/crypto.js +26 -0
- package/dist/mail/offline/crypto.js.map +7 -0
- package/dist/mail/offline/drafts.js +69 -0
- package/dist/mail/offline/drafts.js.map +7 -0
- package/dist/mail/offline/hooks.js +104 -0
- package/dist/mail/offline/hooks.js.map +7 -0
- package/dist/mail/offline/index.js +48 -0
- package/dist/mail/offline/index.js.map +7 -0
- package/dist/mail/offline/live.js +233 -0
- package/dist/mail/offline/live.js.map +7 -0
- package/dist/mail/offline/mailbox.js +191 -0
- package/dist/mail/offline/mailbox.js.map +7 -0
- package/dist/mail/offline/outbox.js +167 -0
- package/dist/mail/offline/outbox.js.map +7 -0
- package/dist/mail/offline/reads.js +159 -0
- package/dist/mail/offline/reads.js.map +7 -0
- package/dist/mail/offline/runtime.js +100 -0
- package/dist/mail/offline/runtime.js.map +7 -0
- package/dist/mail/offline/settings.js +84 -0
- package/dist/mail/offline/settings.js.map +7 -0
- package/dist/mail/offline/store.js +29 -0
- package/dist/mail/offline/store.js.map +7 -0
- package/dist/mail/offline/sync.js +251 -0
- package/dist/mail/offline/sync.js.map +7 -0
- package/dist/mail/offline/wipe.js +19 -0
- package/dist/mail/offline/wipe.js.map +7 -0
- package/dist/mail/thread-keys.js +53 -0
- package/dist/mail/thread-keys.js.map +7 -0
- package/dist/mail/threads.js +71 -0
- package/dist/mail/threads.js.map +7 -0
- package/dist/mail/useMailClient.js +42 -0
- package/dist/mail/useMailClient.js.map +7 -0
- package/dist/model-connections.js +58 -0
- package/dist/model-connections.js.map +7 -0
- package/dist/notifications/ActivityFeed.js +70 -0
- package/dist/notifications/ActivityFeed.js.map +7 -0
- package/dist/notifications/NotificationBell.js +200 -0
- package/dist/notifications/NotificationBell.js.map +7 -0
- package/dist/notifications/Toaster.js +24 -0
- package/dist/notifications/Toaster.js.map +7 -0
- package/dist/notifications/activity-types.js +65 -0
- package/dist/notifications/activity-types.js.map +7 -0
- package/dist/notifications/bell.js +24 -0
- package/dist/notifications/bell.js.map +7 -0
- package/dist/notifications/calendar-notifications.js +79 -0
- package/dist/notifications/calendar-notifications.js.map +7 -0
- package/dist/notifications/index.js +108 -0
- package/dist/notifications/index.js.map +7 -0
- package/dist/notifications/live.js +28 -0
- package/dist/notifications/live.js.map +7 -0
- package/dist/notifications/notification-types.js +127 -0
- package/dist/notifications/notification-types.js.map +7 -0
- package/dist/{chunk-BF5KW5ZI.js → notifications/notify-store.js} +24 -74
- package/dist/notifications/notify-store.js.map +7 -0
- package/dist/notifications/server-notifications.js +452 -0
- package/dist/notifications/server-notifications.js.map +7 -0
- package/dist/notifications/useNotifications.js +34 -0
- package/dist/notifications/useNotifications.js.map +7 -0
- package/dist/offline-store/network.js +11 -0
- package/dist/offline-store/network.js.map +7 -0
- package/dist/offline-store/store.js +136 -0
- package/dist/offline-store/store.js.map +7 -0
- package/dist/offline-store/wipe.js +8 -0
- package/dist/offline-store/wipe.js.map +7 -0
- package/dist/offline.js +58 -0
- package/dist/offline.js.map +7 -0
- package/dist/people.js +122 -0
- package/dist/people.js.map +7 -0
- package/dist/projects.js +30 -0
- package/dist/projects.js.map +7 -0
- package/dist/query-client.js +63 -0
- package/dist/query-client.js.map +7 -0
- package/dist/{chunk-ZM6N7YZH.js → query-keys.js} +18 -31
- package/dist/query-keys.js.map +7 -0
- package/dist/query-persist.js +66 -0
- package/dist/query-persist.js.map +7 -0
- package/dist/queued-writes.js +59 -0
- package/dist/queued-writes.js.map +7 -0
- package/dist/remote-control.js +67 -0
- package/dist/remote-control.js.map +7 -0
- package/dist/search/index.js +23 -0
- package/dist/search/index.js.map +7 -0
- package/dist/search/session.js +58 -0
- package/dist/search/session.js.map +7 -0
- package/dist/search/useSemanticSearch.js +82 -0
- package/dist/search/useSemanticSearch.js.map +7 -0
- package/dist/session/chat.js +512 -0
- package/dist/session/chat.js.map +7 -0
- package/dist/session/documents.js +196 -0
- package/dist/session/documents.js.map +7 -0
- package/dist/session/drafts.js +103 -0
- package/dist/session/drafts.js.map +7 -0
- package/dist/session/index.js +123 -0
- package/dist/session/index.js.map +7 -0
- package/dist/session/layout.js +339 -0
- package/dist/session/layout.js.map +7 -0
- package/dist/session/persist.js +106 -0
- package/dist/session/persist.js.map +7 -0
- package/dist/session/session-hooks.js +53 -0
- package/dist/session/session-hooks.js.map +7 -0
- package/dist/session/signed-in.js +36 -0
- package/dist/session/signed-in.js.map +7 -0
- package/dist/session/store.js +166 -0
- package/dist/session/store.js.map +7 -0
- package/dist/session/thread-tabs.js +121 -0
- package/dist/session/thread-tabs.js.map +7 -0
- package/dist/session/ui-state-storage.js +76 -0
- package/dist/session/ui-state-storage.js.map +7 -0
- package/dist/session/workspace.js +77 -0
- package/dist/session/workspace.js.map +7 -0
- package/dist/shell/index.js +43 -10
- package/dist/shell/index.js.map +7 -1
- package/dist/skill-pack.js +111 -0
- package/dist/skill-pack.js.map +7 -0
- package/dist/storage.js +186 -0
- package/dist/storage.js.map +7 -0
- package/dist/support/index.js +35 -0
- package/dist/support/index.js.map +7 -0
- package/dist/tags.js +204 -0
- package/dist/tags.js.map +7 -0
- package/dist/ui/DebouncedInput.js +109 -0
- package/dist/ui/DebouncedInput.js.map +7 -0
- package/dist/ui/DictateContext.js +8 -0
- package/dist/ui/DictateContext.js.map +7 -0
- package/dist/ui/IconToggle.js +79 -0
- package/dist/ui/IconToggle.js.map +7 -0
- package/dist/ui/VerifiedToggle.js +38 -0
- package/dist/ui/VerifiedToggle.js.map +7 -0
- package/dist/ui/VisibilityToggle.js +103 -0
- package/dist/ui/VisibilityToggle.js.map +7 -0
- package/dist/ui/avatar.js +40 -0
- package/dist/ui/avatar.js.map +7 -0
- package/dist/ui/badge.js +28 -0
- package/dist/ui/badge.js.map +7 -0
- package/dist/ui/button.js +48 -0
- package/dist/ui/button.js.map +7 -0
- package/dist/ui/card.js +90 -0
- package/dist/ui/card.js.map +7 -0
- package/dist/ui/checkbox.js +22 -0
- package/dist/ui/checkbox.js.map +7 -0
- package/dist/ui/collapsible.js +10 -0
- package/dist/ui/collapsible.js.map +7 -0
- package/dist/ui/command.js +103 -0
- package/dist/ui/command.js.map +7 -0
- package/dist/{chunk-YNNAJJ5Z.js → ui/dialog.js} +30 -68
- package/dist/ui/dialog.js.map +7 -0
- package/dist/{chunk-47CCGUWR.js → ui/dropdown-menu.js} +40 -45
- package/dist/ui/dropdown-menu.js.map +7 -0
- package/dist/ui/hover-card.js +36 -0
- package/dist/ui/hover-card.js.map +7 -0
- package/dist/ui/index.js +290 -10
- package/dist/ui/index.js.map +7 -1
- package/dist/ui/input.js +65 -0
- package/dist/ui/input.js.map +7 -0
- package/dist/ui/label.js +16 -0
- package/dist/ui/label.js.map +7 -0
- package/dist/ui/mark-menu.js +300 -0
- package/dist/ui/mark-menu.js.map +7 -0
- package/dist/ui/popover.js +40 -0
- package/dist/ui/popover.js.map +7 -0
- package/dist/ui/portal-container.js +17 -0
- package/dist/ui/portal-container.js.map +7 -0
- package/dist/ui/progress.js +24 -0
- package/dist/ui/progress.js.map +7 -0
- package/dist/ui/radio-group.js +29 -0
- package/dist/ui/radio-group.js.map +7 -0
- package/dist/ui/scroll-area.js +39 -0
- package/dist/ui/scroll-area.js.map +7 -0
- package/dist/ui/select.js +130 -0
- package/dist/ui/select.js.map +7 -0
- package/dist/ui/separator.js +23 -0
- package/dist/ui/separator.js.map +7 -0
- package/dist/ui/slider.js +23 -0
- package/dist/ui/slider.js.map +7 -0
- package/dist/ui/switch.js +28 -0
- package/dist/ui/switch.js.map +7 -0
- package/dist/ui/table.js +75 -0
- package/dist/ui/table.js.map +7 -0
- package/dist/ui/tabs.js +48 -0
- package/dist/ui/tabs.js.map +7 -0
- package/dist/ui/textarea.js +63 -0
- package/dist/ui/textarea.js.map +7 -0
- package/dist/ui/toggle-group.js +43 -0
- package/dist/ui/toggle-group.js.map +7 -0
- package/dist/ui/toggle.js +40 -0
- package/dist/ui/toggle.js.map +7 -0
- package/dist/ui/tooltip.js +215 -0
- package/dist/ui/tooltip.js.map +7 -0
- package/dist/usage-metered.js +8 -0
- package/dist/usage-metered.js.map +7 -0
- package/dist/useArbi.js +16 -0
- package/dist/useArbi.js.map +7 -0
- package/dist/useInstallSkillPack.js +81 -0
- package/dist/useInstallSkillPack.js.map +7 -0
- package/dist/usermenu/UserMenu.js +188 -0
- package/dist/usermenu/UserMenu.js.map +7 -0
- package/dist/usermenu/index.js +5 -0
- package/dist/usermenu/index.js.map +7 -0
- package/dist/users/index.js +15 -0
- package/dist/users/index.js.map +7 -0
- package/dist/users/user-display.js +60 -0
- package/dist/users/user-display.js.map +7 -0
- package/dist/viewers/AudioViewer.js +23 -0
- package/dist/viewers/AudioViewer.js.map +7 -0
- package/dist/viewers/DocxViewer.js +81 -0
- package/dist/viewers/DocxViewer.js.map +7 -0
- package/dist/viewers/ImageViewer.js +31 -0
- package/dist/viewers/ImageViewer.js.map +7 -0
- package/dist/viewers/PdfViewer.js +19 -3
- package/dist/viewers/PdfViewer.js.map +7 -1
- package/dist/{PdfViewerImpl-TEBYF2QI.js → viewers/PdfViewerImpl.js} +25 -19
- package/dist/viewers/PdfViewerImpl.js.map +7 -0
- package/dist/viewers/VideoViewer.js +31 -0
- package/dist/viewers/VideoViewer.js.map +7 -0
- package/dist/viewers/XlsxViewer.js +102 -0
- package/dist/viewers/XlsxViewer.js.map +7 -0
- package/dist/viewers/index.js +61 -271
- package/dist/viewers/index.js.map +7 -1
- package/dist/viewers/page-scroll.js +59 -0
- package/dist/viewers/page-scroll.js.map +7 -0
- package/dist/viewers/pdf-viewer-constants.js +9 -0
- package/dist/viewers/pdf-viewer-constants.js.map +7 -0
- package/dist/{chunk-PTOP7OHG.js → viewers/pdfjs-polyfills.js} +5 -6
- package/dist/viewers/pdfjs-polyfills.js.map +7 -0
- package/dist/viewers/selection-runs.js +38 -0
- package/dist/viewers/selection-runs.js.map +7 -0
- package/dist/viewers/usePageIntersectionObserver.js +68 -0
- package/dist/viewers/usePageIntersectionObserver.js.map +7 -0
- package/dist/viewers/useProcessedChunks.js +58 -0
- package/dist/viewers/useProcessedChunks.js.map +7 -0
- package/dist/viewers/viewer-zoom.js +163 -0
- package/dist/viewers/viewer-zoom.js.map +7 -0
- package/dist/websocket/ArbiWebSocketProvider.js +207 -0
- package/dist/websocket/ArbiWebSocketProvider.js.map +7 -0
- package/dist/websocket/context.js +14 -0
- package/dist/websocket/context.js.map +7 -0
- package/dist/websocket/hooks.js +30 -0
- package/dist/websocket/hooks.js.map +7 -0
- package/dist/websocket/index.js +22 -0
- package/dist/websocket/index.js.map +7 -0
- package/dist/websocket/live-updates.js +38 -0
- package/dist/websocket/live-updates.js.map +7 -0
- package/dist/websocket/reconnect.js +13 -0
- package/dist/websocket/reconnect.js.map +7 -0
- package/dist/websocket/store.js +58 -0
- package/dist/websocket/store.js.map +7 -0
- package/dist/workforce.js +607 -0
- package/dist/workforce.js.map +7 -0
- package/dist/workspaces/access-request.js +35 -0
- package/dist/workspaces/access-request.js.map +7 -0
- package/dist/workspaces/archive.js +59 -0
- package/dist/workspaces/archive.js.map +7 -0
- package/dist/workspaces/current.js +20 -0
- package/dist/workspaces/current.js.map +7 -0
- package/dist/workspaces/delete-workspaces.js +15 -0
- package/dist/workspaces/delete-workspaces.js.map +7 -0
- package/dist/workspaces/export-archive.js +40 -0
- package/dist/workspaces/export-archive.js.map +7 -0
- package/dist/workspaces/index.js +99 -0
- package/dist/workspaces/index.js.map +7 -0
- package/dist/workspaces/settings.js +45 -0
- package/dist/workspaces/settings.js.map +7 -0
- package/dist/workspaces/shell-workspaces.js +49 -0
- package/dist/workspaces/shell-workspaces.js.map +7 -0
- package/dist/workspaces/switch.js +234 -0
- package/dist/workspaces/switch.js.map +7 -0
- package/dist/workspaces/transfer.js +170 -0
- package/dist/workspaces/transfer.js.map +7 -0
- package/dist/workspaces/useShellWorkspaces.js +86 -0
- package/dist/workspaces/useShellWorkspaces.js.map +7 -0
- package/dist/workspaces/workspace-users.js +65 -0
- package/dist/workspaces/workspace-users.js.map +7 -0
- package/package.json +4 -4
- package/dist/PdfViewerImpl-TEBYF2QI.js.map +0 -1
- package/dist/PdfViewerImpl.d-B28hLEuj.d.cts +0 -62
- package/dist/ProductionDialog.d-CpzslFn0.d.cts +0 -51
- package/dist/annotations/freeze/index.d.cts +0 -205
- package/dist/annotations/index.d.cts +0 -360
- package/dist/artifacts/index.d.cts +0 -476
- package/dist/artifacts/redline-core.d.cts +0 -39
- package/dist/bundle-YNOX7VIL.js +0 -5
- package/dist/bundle-YNOX7VIL.js.map +0 -1
- package/dist/bundle.d-BnCSbHy2.d.cts +0 -85
- package/dist/calls/livekit/index.d.cts +0 -280
- package/dist/chunk-47CCGUWR.js.map +0 -1
- package/dist/chunk-4FL3X3LA.js +0 -2057
- package/dist/chunk-4FL3X3LA.js.map +0 -1
- package/dist/chunk-6QNBSXCE.js +0 -271
- package/dist/chunk-6QNBSXCE.js.map +0 -1
- package/dist/chunk-74N436VK.js.map +0 -1
- package/dist/chunk-APZZQZ6P.js +0 -147
- package/dist/chunk-APZZQZ6P.js.map +0 -1
- package/dist/chunk-BF5KW5ZI.js.map +0 -1
- package/dist/chunk-DPYBZDJB.js.map +0 -1
- package/dist/chunk-DZKRL5H3.js +0 -2766
- package/dist/chunk-DZKRL5H3.js.map +0 -1
- package/dist/chunk-HDCRPPBW.js +0 -75
- package/dist/chunk-HDCRPPBW.js.map +0 -1
- package/dist/chunk-L2IPPTVC.js +0 -20
- package/dist/chunk-L2IPPTVC.js.map +0 -1
- package/dist/chunk-LSU4UPS5.js +0 -1011
- package/dist/chunk-LSU4UPS5.js.map +0 -1
- package/dist/chunk-NIKPG4PW.js +0 -1128
- package/dist/chunk-NIKPG4PW.js.map +0 -1
- package/dist/chunk-NNAJLY6B.js +0 -4974
- package/dist/chunk-NNAJLY6B.js.map +0 -1
- package/dist/chunk-OYPKKHXY.js +0 -559
- package/dist/chunk-OYPKKHXY.js.map +0 -1
- package/dist/chunk-PTOP7OHG.js.map +0 -1
- package/dist/chunk-QMY2JKBI.js +0 -246
- package/dist/chunk-QMY2JKBI.js.map +0 -1
- package/dist/chunk-SN5YV6FF.js +0 -11
- package/dist/chunk-SN5YV6FF.js.map +0 -1
- package/dist/chunk-SSXFVWCT.js.map +0 -1
- package/dist/chunk-T3USOSVN.js.map +0 -1
- package/dist/chunk-T4CLW3DN.js +0 -2560
- package/dist/chunk-T4CLW3DN.js.map +0 -1
- package/dist/chunk-UW2SGTI5.js.map +0 -1
- package/dist/chunk-VSCU7K4V.js.map +0 -1
- package/dist/chunk-WL2Y2T47.js.map +0 -1
- package/dist/chunk-WUTL62MC.js.map +0 -1
- package/dist/chunk-XWPLOFDN.js +0 -644
- package/dist/chunk-XWPLOFDN.js.map +0 -1
- package/dist/chunk-Y3MTRA7D.js +0 -97
- package/dist/chunk-Y3MTRA7D.js.map +0 -1
- package/dist/chunk-YNNAJJ5Z.js.map +0 -1
- package/dist/chunk-ZM6N7YZH.js.map +0 -1
- package/dist/document-tools/core.d.cts +0 -883
- package/dist/document-tools/index.d.cts +0 -90
- package/dist/index.d-LArLnpI8.d.cts +0 -2036
- package/dist/index.d-oR5FKZpJ.d.cts +0 -579
- package/dist/index.d.cts +0 -15923
- package/dist/lazy-chunk.d-B6YDLMKI.d.cts +0 -31
- package/dist/model.d-CNtRWKVK.d.cts +0 -110
- package/dist/query-keys.d-B1Am9tIF.d.cts +0 -337
- package/dist/shell/index.d.cts +0 -6
- package/dist/store.d-GADDvC7w.d.cts +0 -35
- package/dist/stored-markdown.d-Bp18vrbr.d.cts +0 -125
- package/dist/ui/index.d.cts +0 -26
- package/dist/useAudioRecorder.d-B9rlMI_E.d.cts +0 -778
- package/dist/viewers/PdfViewer.d.cts +0 -9
- package/dist/viewers/index.d.cts +0 -262
package/dist/index.js.map
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/host/index.ts","../src/workspaces/current.ts","../src/workforce.ts","../src/chat/citations.ts","../src/chat/conversation-cache.ts","../src/chat/conversation-mentions.ts","../src/config/config-hooks.ts","../src/chat/agent-chat-owner.ts","../src/chat/thread-binding.ts","../src/chat/reply-target.ts","../src/chat/conversation-workspace.ts","../src/documents/processing-settle.ts","../src/documents/processing-live.ts","../src/documents/documents-writes.ts","../src/documents/support.tsx","../src/documents/document-download.ts","../src/documents/useDownloadDocuments.ts","../src/documents/useDocumentThumbnails.ts","../src/documents/DocumentReview.tsx","../src/documents/VoiceNoteRecorder.tsx","../src/documents/DraftTitleControls.tsx","../src/documents/useCameraStream.ts","../src/documents/useVideoRecorder.ts","../src/documents/capture-frame.ts","../src/documents/PhotoCapture.tsx","../src/documents/VideoCapture.tsx","../src/documents/has-video-track.ts","../src/documents/upload-files.ts","../src/documents/useUploadFiles.ts","../src/documents/useUploadFromUrls.ts","../src/documents/related-documents.ts","../src/offline.ts","../src/documents/pending-sync.ts","../src/documents/offline-documents.ts","../src/chat/stream-handlers.ts","../src/chat/turn-control.ts","../src/chat/useConversationActions.ts","../src/chat/useConversationData.ts","../src/chat/useBranchNavigation.ts","../src/chat/useConnectRunStream.ts","../src/chat/workflow-run-titles.ts","../src/chat/useConversation.ts","../src/chat/ConversationScope.tsx","../src/chat/useConversationWorkspace.ts","../src/chat/conversation-events.ts","../src/chat/useThreadDocument.ts","../src/chat/config-model.ts","../src/chat/useDeleteMessage.ts","../src/chat/useConversationTurn.ts","../src/chat/active-config.ts","../src/chat/useConversationDocuments.ts","../src/chat/useDocumentAutoAdd.ts","../src/chat/useAutoSendDraft.ts","../src/chat/orphaned.ts","../src/chat/pendingFirstTurn.ts","../src/chat/useAnswerAgentQuestion.ts","../src/chat/useConversationSettings.ts","../src/chat/useAskAgain.ts","../src/chat/useThinkingContent.ts","../src/chat/useMessageTimer.ts","../src/chat/useAgentRunControl.ts","../src/chat/ChatBubble.tsx","../src/boot-timeout.ts","../src/useInstallSkillPack.ts","../src/skill-pack.ts","../src/connectivity.ts","../src/websocket/reconnect.ts","../src/mail/client.ts","../src/mail/threads.ts","../src/mail/offline/mailbox.ts","../src/offline-store/network.ts","../src/mail/offline/changes.ts","../src/mail/filing.ts","../src/mail/offline/drafts.ts","../src/mail/offline/outbox.ts","../src/mail/offline/sync.ts","../src/mail/offline/live.ts","../src/mail/offline/reads.ts","../src/mail/useMailClient.ts","../src/mail/hooks.ts","../src/websocket/live-updates.ts","../src/chat/run-finished.ts","../src/notifications/live.ts","../src/websocket/context.ts","../src/websocket/ArbiWebSocketProvider.tsx","../src/websocket/hooks.ts","../src/workspaces/shell-workspaces.ts","../src/workspaces/useShellWorkspaces.ts","../src/workspaces/switch.ts","../src/workspaces/settings.ts","../src/workspaces/workspace-users.ts","../src/workspaces/delete-workspaces.ts","../src/workspaces/export-archive.ts","../src/workspaces/transfer.ts","../src/workspaces/access-request.ts","../src/workspaces/archive.ts","../src/facts.ts","../src/facts-search.ts","../src/databases.ts","../src/account/table-views.ts","../src/datasets/types.ts","../src/datasets/aggregate.ts","../src/datasets/rows-source.ts","../src/datasets/panel.ts","../src/datasets/members.ts","../src/datasets/sources/workflows.ts","../src/datasets/sources/activity.ts","../src/datasets/sources/conversations.ts","../src/datasets/sources/database.ts","../src/datasets/sources/documents.ts","../src/datasets/sources/facts.ts","../src/datasets/sources/projects.ts","../src/datasets/sources/tags.ts","../src/datasets/sources/usage.ts","../src/datasets/sources/workspaces.ts","../src/datasets/registry.ts","../src/datasets/store.ts","../src/documents/usePassageQuotes.ts","../src/query-persist.ts","../src/query-client.ts","../src/projects.ts","../src/charge-watch.ts","../src/billing.ts","../src/storage.ts","../src/contacts.ts","../src/people.ts","../src/house-template.ts","../src/model-connections.ts","../src/account/email.ts","../src/account/password.ts","../src/account/dismissed-tips.ts","../src/account/notifications.ts","../src/account/relevance.ts","../src/account/sessions.ts","../src/account/delete.ts","../src/account/didit.ts","../src/account/identity.ts","../src/account/recovery.ts","../src/mail/document-attachment.ts","../src/mail/thread-keys.ts","../src/mail/offline/runtime.ts","../src/mail/offline/hooks.ts","../src/mail/offline/confirm-sign-out.ts","../src/connectors/hooks.ts","../src/calendar/support.tsx","../src/calendar/hooks.ts","../src/calendar/accounts.ts","../src/offline-store/wipe.ts","../src/calendar/offline/outbox.ts","../src/calendar/offline/support.ts","../src/calendar/offline/runtime.ts","../src/ai/engine.ts","../src/ai/redline.ts","../src/ai/AiAnswer.tsx","../src/ai/ArtifactCanvas.tsx","../src/ai/MessageArtifactCard.tsx","../src/ai/CitationRenderer.tsx","../src/search/useSemanticSearch.ts","../src/icons/AppleIcon.tsx","../src/icons/GitHubIcon.tsx","../src/icons/LinkedInIcon.tsx","../src/notifications/notification-types.ts","../src/notifications/activity-types.ts","../src/notifications/ActivityFeed.tsx","../src/notifications/useNotifications.ts","../src/notifications/server-notifications.ts","../src/notifications/calendar-notifications.ts","../src/notifications/bell.ts","../src/directmessages/utils.ts","../src/directmessages/DmAvatar.tsx","../src/directmessages/ConversationList.tsx","../src/directmessages/DmComposer.tsx","../src/directmessages/useChats.ts","../src/directmessages/arrivals.ts","../src/directmessages/DateSeparator.tsx","../src/directmessages/grouping.ts","../src/imagecrop/ImageCropper.tsx","../src/imagecrop/cropImage.ts","../src/imagecrop/ImageCropModal.tsx","../src/remote-control.ts","../src/support/index.ts"],"names":["ArbiHost","useMemo","attempt","text","useQuery","useQueryClient","useMutation","chain","useRef","ids","chatModel","useCallback","useEffect","store","documents","update","documentOps","doctagOps","useState","jsxs","jsx","Fragment","Trash2","RotateCcw","Loader2","Check","Square","mimeFromName","BATCH_SIZE","docIds","partialMatchKey","document","run","onlineManager","conversationKey","quotaFromStreamError","threads","retryTimer","day","signedInUserId","queuedMessages","branch","selectThread","queue","React","TypingIndicator","ChatBubble","set","signedIn","fetch","bucket","mailOps","tried","keyFor","write","classify","unlocked","logger","records","useSyncExternalStore","isMessageType","getUserEncryptionKeypair","EMPTY","openWorkspaceId","bucketOf","workspaceOf","inWorkspace","useQueries","isAbortError","watch","settings","settingsOps","syncing","ArbiApiError","NO_SUPPORT","sealer","seqCounter","notify","cacheKey","Sparkles","AlertTriangle","Copy","FileText","ImageIcon","measure","Activity","reason","CheckCheck","X","chats","chatOps"],"mappings":"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","file":"index.js","sourcesContent":["import { ArbiHost as GenericArbiHost, type ArbiHostProps } from './ArbiHost'\nimport type { ArbiHostConfig } from './config'\n\n/** `<ArbiHost config>` with the `@arbidocs/react` domains (see ./ArbiHost.tsx). */\nexport const ArbiHost: (props: ArbiHostProps<ArbiHostConfig>) => React.ReactElement =\n GenericArbiHost\n\nexport { type ArbiHostConnection, type ArbiHostProps } from './ArbiHost'\nexport { mergeHostConfig } from './merge'\nexport {\n useArbiHost,\n type ArbiHostConfig,\n type AccountHost,\n type CallsHost,\n type CallSlotMode,\n type MailHost,\n} from './config'\n","/**\n * The workspace the app is in: the session's selection, as the workspace list has it, and the\n * signed-in person's membership in it.\n */\n\nimport { useMemo } from 'react'\nimport type { components } from '@arbidocs/client'\nimport { useWorkspaces } from '../hooks'\nimport { useArbiSession, useArbiSessionState } from '../session'\nimport type { ArbiWorkspaceStatus } from '../session'\n\ntype Workspace = NonNullable<ReturnType<typeof useWorkspaces>['data']>[number]\ntype WorkspaceRole = components['schemas']['WorkspaceRole']\n\nexport interface CurrentWorkspace {\n /** The selected workspace (`wrk-…`), also before the list has it; null on the workspace list. */\n workspaceId: string | null\n /** Whether it is open on the server session. */\n workspaceStatus: ArbiWorkspaceStatus\n /** Its entry in the workspace list (undefined until listed, or when it is no longer there). */\n workspace: Workspace | undefined\n /** The signed-in person's role in it, null when they are not a member (a public workspace). */\n role: WorkspaceRole | null\n isMember: boolean\n /** The signed-in person (`usr-…`). */\n userId: string | null\n}\n\nexport function useCurrentWorkspace(): CurrentWorkspace {\n const workspaceId = useArbiSessionState((s) => s.workspaceId)\n const workspaceStatus = useArbiSessionState((s) => s.workspaceStatus)\n const userId = useArbiSession().user?.external_id ?? null\n const { data: workspaces } = useWorkspaces()\n const workspace = workspaceId ? workspaces?.find((w) => w.external_id === workspaceId) : undefined\n const membership = userId\n ? workspace?.users?.find((member) => member.user.external_id === userId)\n : undefined\n const role = membership?.role ?? null\n return useMemo(\n () => ({ workspaceId, workspaceStatus, workspace, role, isMember: !!membership, userId }),\n [workspaceId, workspaceStatus, workspace, role, membership, userId]\n )\n}\n","/**\n * Work, workflows, agents and skills: the mutation and read hooks behind an \"AI workforce\" screen.\n *\n * A conversation with a `status` is a task: it is listed by `useConversations` and changed through\n * `useUpdateConversation` and friends (which patch the list, see `conversation-list`). A workflow is the automation that creates them. Everything\n * sits on the SDK (`arbi.conversations`, `arbi.workflows`, `arbi.agents`, `arbi.agentConfig`,\n * `arbi.workspaces`, `arbi.assistant.listSkills`) and invalidates through {@link arbiQueryKeys}, so\n * `useConversations`, `useWorkflows`, `useAgents` and `useConfigs` refresh on their own after a\n * write. Mapping a form onto these requests (`TaskComposerValues` to a create-work or create-workflow\n * request, an agent form to a persona) is the pure part and lives next to the forms in\n * `@arbidocs/blocks/agents`.\n *\n * Requires an `ArbiHost` (with an `arbi`) and a React Query client above it.\n */\n\nimport { useEffect, useMemo, useRef } from 'react'\nimport { useMutation, useQuery, useQueryClient, type QueryClient } from '@tanstack/react-query'\nimport type {\n ActivityResponse,\n ConversationResponse,\n CreateWorkRequest,\n CreateWorkflowRequest,\n PlanWorkRequest,\n StepActionRequest,\n UpdateConversationRequest,\n UpdateWorkflowRequest,\n WorkflowResponse,\n WorkflowRunResponse,\n WorkflowRunHistoryResponse,\n} from '@arbidocs/sdk/browser'\nimport type { components } from '@arbidocs/client'\nimport { useArbi } from './useArbi'\nimport { useCurrentWorkspace } from './workspaces/current'\nimport { arbiMutationKeys, arbiQueryKeys, useConversations } from './hooks'\nimport {\n addConversationToList,\n invalidateConversationDetails,\n invalidateConversationLists,\n patchConversation,\n removeConversationFromLists,\n} from './conversation-list'\nimport { useArbiSessionState } from './session'\n\n/** An agent or deployment config: section name (`Agents`, `QueryLLM`, ...) to its parameters. */\nexport type AgentConfigSections = Record<string, Record<string, unknown>>\n\n// ── Conversations as work ───────────────────────────────────────────────────\n\n/**\n * Whether a React Query key is the cached activity of a task (of `conversationId`, or any): the\n * {@link useConversationActivity} key, `['arbi', 'conversations', id, 'activity']`.\n */\nexport function isActivityKey(queryKey: readonly unknown[], conversationId?: string): boolean {\n const [scope, resource, id, leaf] = queryKey\n if (scope !== 'arbi' || resource !== 'conversations' || leaf !== 'activity') return false\n return !conversationId || id === conversationId\n}\n\n/** Re-read the activity of one task (or every cached one): after a run or a patch. */\nexport function invalidateConversationActivity(queryClient: QueryClient, conversationId?: string) {\n void queryClient.invalidateQueries({\n predicate: (q) => isActivityKey(q.queryKey, conversationId),\n })\n}\n\n/** How often to re-read the list while an agent is generating. */\nconst GENERATING_POLL_MS = 2500\n\n/**\n * One poll for the whole page. Several components read the list, and each running its own timer\n * meant N times the requests, each cancelling the last. Holders share a single timer that runs\n * while at least one of them needs it; the returned function lets go.\n */\nlet listPollHolders = 0\nlet listPollTimer: ReturnType<typeof setInterval> | undefined\nlet listPollRefetch: (() => unknown) | undefined\n\nfunction holdListPoll(refetch: () => unknown): () => void {\n listPollRefetch = refetch\n listPollHolders += 1\n if (listPollTimer === undefined) {\n listPollTimer = setInterval(() => void listPollRefetch?.(), GENERATING_POLL_MS)\n }\n return () => {\n listPollHolders -= 1\n if (listPollHolders === 0 && listPollTimer !== undefined) {\n clearInterval(listPollTimer)\n listPollTimer = undefined\n }\n }\n}\n\n/**\n * The open workspace's conversations, and among them its tasks: the ones that have a `status` (a\n * plain chat has none). One list serves both: a task is a conversation with a status.\n *\n * The list is seeded once and patched by writes, so a run that finishes server-side is picked up by\n * re-reading it while any task is generating. A task whose status or update time changed has a\n * stale history, which is re-read.\n */\nexport function useConversationItems() {\n // Not the id alone: it lands before the workspace is open, and the list is read once.\n const workspaceId = useArbiSessionState((s) => s.workspaceId)\n const open = useArbiSessionState((s) => s.workspaceStatus === 'open')\n const query = useConversations(workspaceId ?? undefined, { enabled: open })\n const { refetch } = query\n const all = query.data\n const tasks = useMemo(() => (all ?? []).filter((c) => c.status != null), [all])\n const queryClient = useQueryClient()\n const seen = useRef(new Map<string, string>())\n useEffect(() => {\n for (const t of tasks) {\n const stamp = `${t.status}|${t.updated_at ?? ''}`\n const before = seen.current.get(t.external_id)\n if (before !== undefined && before !== stamp) {\n invalidateConversationActivity(queryClient, t.external_id)\n }\n seen.current.set(t.external_id, stamp)\n }\n }, [tasks, queryClient])\n const generating = tasks.some((t) => t.in_progress || t.status === 'generating')\n useEffect(() => (generating ? holdListPoll(refetch) : undefined), [generating, refetch])\n return { conversations: all ?? [], tasks, isLoading: query.isLoading, refetch }\n}\n\n/** Whether the open conversation is shared (a thread with people in it), from the list. */\nexport function useConversationIsShared(): boolean {\n const id = useArbiSessionState((state) => state.conversationId)\n const { conversations } = useConversationItems()\n return conversations.find((conversation) => conversation.external_id === id)?.is_shared ?? false\n}\n\n/** The open workspace's tasks only: the conversations that have a `status`. */\nexport function useWorkItems() {\n const { tasks, isLoading, refetch } = useConversationItems()\n return { tasks, isLoading, refetch }\n}\n\n/**\n * The signed-in person's role in the open workspace (`owner`, `collaborator`, `guest`), or null when\n * they are not a member: their entry in the workspace's own member list.\n */\nexport function useWorkspaceRole() {\n return useCurrentWorkspace().role\n}\n\n/**\n * Whether the viewer edits the open workspace (owner or collaborator). A task or workflow they do\n * not own is always shared with them, and editors may then change it; guests only read. Sharing and\n * deleting stay with the row's owner, which the row itself says (`is_owner`).\n */\nexport function useCanEditShared(): boolean {\n const role = useWorkspaceRole()\n return role === 'owner' || role === 'collaborator'\n}\n\n/** Whether the viewer owns the open workspace: with an item's creator, the only one who shares or deletes it. */\nexport function useIsWorkspaceOwner(): boolean {\n return useWorkspaceRole() === 'owner'\n}\n\n/**\n * The run was accepted, but the thread it creates did not show up within the lookup. The task is\n * running, so starting it again would make a second one: look for its thread again with\n * `findThread(messageId)` instead.\n */\nexport class TaskThreadPendingError extends Error {\n constructor(readonly messageId: string) {\n super(\"The task has started, but its thread isn't ready yet.\")\n this.name = 'TaskThreadPendingError'\n }\n}\n\n/** Looking up the thread a just-accepted run is creating: how many tries, how far apart. */\nconst THREAD_LOOKUP_ATTEMPTS = 20\nconst THREAD_LOOKUP_DELAY_MS = 500\n\n/** A run that makes its thread a task, as the person asking (see `ThreadQuery` in blocks). */\nexport interface StartTaskQuery {\n input: string\n workspaceId: string\n docIds: string[]\n mentions?: Parameters<ReturnType<typeof useArbi>['assistant']['submit']>[1]['mentions']\n task?: Parameters<ReturnType<typeof useArbi>['assistant']['submit']>[1]['task']\n}\n\n/**\n * Run now: a background response whose `task` options make its thread a task (generating, then\n * open again). It runs as the person asking, so there is no stream to hold open: the response\n * carries the message id, from which the thread is found and the list re-read. A bad parent is\n * refused before anything is created. Resolves with the new thread's id; the run uses the chat's\n * model choice, else the person's last config.\n */\nexport function useStartTaskQuery() {\n const arbi = useArbi()\n const queryClient = useQueryClient()\n const chatModel = useArbiSessionState((s) => s.chatModel)\n const post = useMutation({\n mutationFn: (query: StartTaskQuery) => {\n const selectedConfig =\n chatModel ||\n queryClient\n .getQueriesData<{ last_config?: string }>({ queryKey: arbiQueryKeys.userSettings() })\n .map(([, settings]) => settings?.last_config)\n .find(Boolean)\n // The run goes to the workspace the query names (opened for this session if it is not the\n // current one), never to whichever workspace the session has open when it is sent.\n return arbi.assistant.submit(query.input, {\n workspaceId: query.workspaceId,\n docIds: query.docIds,\n fullContext: false,\n ...(selectedConfig ? { model: selectedConfig } : {}),\n ...(query.mentions !== undefined ? { mentions: query.mentions } : {}),\n ...(query.task !== undefined ? { task: query.task } : {}),\n })\n },\n })\n /**\n * The thread of a run, read from the run itself (`GET /v1/responses/{id}`, which answers while the\n * run is live): undefined while the run has not created it yet. Once the run has posted its\n * question the thread exists (its `arbi.user_message` event names it); a finished run's message is\n * stored with its thread. Asking for the message of a run still setting up would be a 404.\n */\n const threadOf = async (\n messageId: string,\n known?: string | null\n ): Promise<string | undefined> => {\n const response = await arbi.assistant.getResponse(messageId)\n const events = (response.metadata?.events ?? []) as {\n type?: string\n conversation_ext_id?: string\n }[]\n const posted = events.find((e) => e.type === 'arbi.user_message')?.conversation_ext_id\n if (posted) return posted\n if (response.status === 'queued' || response.status === 'in_progress') return undefined\n return known || (await arbi.conversations.getMessage(messageId)).conversation_ext_id\n }\n /** The thread a run is creating, looked up `attempts` times; null while it is not there yet. */\n const lookUpThread = async (\n messageId: string,\n attempts: number,\n known?: string | null\n ): Promise<{ conversationId: string } | null> => {\n let conversationId: string | undefined\n for (let attempt = 0; attempt < attempts && !conversationId; attempt += 1) {\n if (attempt > 0) await new Promise((r) => setTimeout(r, THREAD_LOOKUP_DELAY_MS))\n try {\n conversationId = await threadOf(messageId, known)\n } catch (error) {\n // A 404 is a run another server instance has not marked live yet; anything else (a\n // refusal) is not worth waiting on.\n if (!(error && typeof error === 'object' && 'status' in error && error.status === 404))\n throw error\n }\n }\n if (!conversationId) return null\n // The new task is not in the cached list yet: read it again.\n await invalidateConversationLists(queryClient)\n return { conversationId }\n }\n return {\n isPending: post.isPending,\n /** Look again for the thread of a run whose start threw {@link TaskThreadPendingError}. */\n findThread: (messageId: string) => lookUpThread(messageId, 1),\n start: async (query: StartTaskQuery): Promise<{ conversationId: string }> => {\n const accepted = await post.mutateAsync(query)\n const found = await lookUpThread(\n accepted.id,\n THREAD_LOOKUP_ATTEMPTS,\n accepted.conversation_ext_id\n )\n if (!found) throw new TaskThreadPendingError(accepted.id)\n return found\n },\n }\n}\n\n/**\n * Patch a conversation: rename it, share it or make it private (`shared`, owner only), or change\n * its work fields (description, due date, parent, `status` `todo | done`, plan).\n * The one write behind title edits, the share toggle and marking a task done.\n */\nexport function useUpdateConversation() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: ({\n conversationId,\n patch,\n }: {\n conversationId: string\n patch: UpdateConversationRequest\n }): Promise<ConversationResponse> => arbi.conversations.update(conversationId, patch),\n // The list takes the server's version of the row; what hangs off it is read again.\n onSuccess: (updated, { conversationId }) => {\n patchConversation(qc, conversationId, updated)\n return invalidateConversationDetails(qc, conversationId)\n },\n })\n}\n\n/** Delete a conversation (thread or task); it leaves every cached list at once. */\nexport function useDeleteConversation() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: (conversationId: string) => arbi.conversations.delete(conversationId),\n onSuccess: (_res, conversationId) => removeConversationFromLists(qc, conversationId),\n })\n}\n\n/** The workspace a work call names: the one given, else the one open now (none: the SDK's). */\nfunction workWorkspace(arbi: ReturnType<typeof useArbi>, workspaceId?: string | null) {\n return workspaceId || (arbi.hasWorkspace ? arbi.getWorkspaceId() : undefined)\n}\n\n/**\n * Search the past conversation messages (keyword + semantic, grouped) of `workspaceId`, else of\n * the workspace open when it is sent.\n */\nexport function useConversationSearch(workspaceId?: string | null) {\n const arbi = useArbi()\n return useMutation({\n mutationFn: (body: components['schemas']['ConversationSearchRequest']) =>\n arbi.conversations.search(body, { workspaceId: workWorkspace(arbi, workspaceId) }),\n })\n}\n\n/**\n * Create a work item from a `CreateWorkRequest`: a plain to-do, or (with a prompt or skill) agent\n * work that starts at once. It is made in `options.workspaceId` (the page's), else in the workspace\n * open when it is sent; the request names it, and it joins that workspace's list. Resolves with the\n * created conversation.\n */\nexport function useCreateWork(options?: { workspaceId?: string | null }) {\n const arbi = useArbi()\n const qc = useQueryClient()\n const named = options?.workspaceId\n return useMutation({\n // The workspace is read once, when the request is sent: the request names it and the new work\n // joins that workspace's list, so one switched to while it is in flight neither receives it\n // nor lists it.\n mutationFn: async (body: CreateWorkRequest): Promise<ConversationResponse> => {\n const workspaceId = workWorkspace(arbi, named)\n const created = await arbi.conversations.createWork(body, { workspaceId })\n addConversationToList(qc, workspaceId ?? null, created)\n return created\n },\n })\n}\n\n/**\n * Run a work item now, or retry it. A run parked waiting for workspace access (a temporary\n * authorization tier) is granted a temporary, session-scoped key and run again, so the person\n * clicking Run authorizes it. Resolves with the updated conversation.\n */\nexport function useRunConversation() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: (conversationId: string): Promise<ConversationResponse> =>\n arbi.conversations.runWithAuth(conversationId),\n // The server's version replaces the listed one; everything under the conversation is re-read.\n onSuccess: (updated) => {\n if (updated?.external_id) patchConversation(qc, updated.external_id, updated)\n return qc.invalidateQueries({ queryKey: arbiQueryKeys.allConversations() })\n },\n })\n}\n\n/**\n * Complete or skip a step of a workflow run (a form, an upload, a review's approval). The run then\n * starts its next agent step; the listed conversation is replaced and its activity re-read.\n */\nexport function useActOnStep() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: ({\n conversationId,\n body,\n }: {\n conversationId: string\n body: StepActionRequest\n }): Promise<ConversationResponse> => arbi.conversations.actOnStep(conversationId, body),\n // The server's version of the conversation replaces the listed one; its history is re-read.\n onSuccess: (updated) => {\n if (!updated?.external_id) return\n patchConversation(qc, updated.external_id, updated)\n invalidateConversationActivity(qc, updated.external_id)\n },\n })\n}\n\n/**\n * Draft an editable plan (goal and acceptance checklist) from an objective, for a task in\n * `workspaceId`, else in the workspace open when it is sent.\n */\nexport function usePlanWork(workspaceId?: string | null) {\n const arbi = useArbi()\n return useMutation({\n mutationFn: (body: PlanWorkRequest) =>\n arbi.conversations.plan(body, { workspaceId: workWorkspace(arbi, workspaceId) }),\n })\n}\n\n/**\n * The agent run-session key a parked run waits for the owner to allow (public key and email,\n * non-secret). Enabled only while the run is waiting; 404 otherwise.\n */\nexport function useConversationPendingAuth(\n conversationId: string | undefined,\n options?: { enabled?: boolean }\n) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.conversationPendingAuth(conversationId ?? ''),\n queryFn: () => arbi.conversations.pendingAuth(conversationId as string),\n enabled: (options?.enabled ?? true) && !!conversationId && arbi.isLoggedIn,\n retry: false,\n })\n}\n\n/**\n * A task's history, oldest first (created, run started, handed off, sent back, done, ...). Cached\n * under the conversations prefix, so every task write that invalidates the list refreshes it too.\n * Pass `live` while a run is generating to re-read it every few seconds.\n */\nexport function useConversationActivity(\n conversationId: string | undefined,\n options?: { enabled?: boolean; live?: boolean }\n) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.conversationActivity(conversationId ?? ''),\n queryFn: (): Promise<ActivityResponse[]> =>\n arbi.conversations.activity(conversationId as string),\n enabled: (options?.enabled ?? true) && !!conversationId && arbi.isLoggedIn,\n refetchInterval: options?.live ? 2500 : false,\n })\n}\n\n// ── Workflows ───────────────────────────────────────────────────────────────\n\n/** The caller's workflows (their own, and the ones shared with the open workspace). */\nexport function useWorkflows(options?: { enabled?: boolean; live?: boolean }) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.workflows(),\n queryFn: (): Promise<WorkflowResponse[]> => arbi.workflows.list(),\n // A clock or event can fire while the list is open, without a write here.\n refetchInterval: options?.live ? 10_000 : false,\n enabled: (options?.enabled ?? true) && arbi.isLoggedIn,\n })\n}\n\n/** A workflow's runs, re-read every few seconds while shown (a run moves on by itself). */\nexport function useWorkflowRuns(workflowId: string | undefined) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.workflowRuns(workflowId ?? ''),\n queryFn: (): Promise<WorkflowRunHistoryResponse[]> => arbi.workflows.runs(workflowId as string),\n enabled: !!workflowId && arbi.isLoggedIn,\n refetchInterval: 3000,\n staleTime: 0,\n refetchOnMount: 'always',\n })\n}\n\n/** Create a workflow from a `CreateWorkflowRequest`. Resolves with the created workflow. */\nexport function useCreateWorkflow() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: (body: CreateWorkflowRequest): Promise<WorkflowResponse> =>\n arbi.workflows.create(body),\n onSuccess: () => qc.invalidateQueries({ queryKey: arbiQueryKeys.workflows() }),\n })\n}\n\n/** Patch a workflow: pause or resume it (`active`), share it, or change its trigger or action. */\nexport function useUpdateWorkflow() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: ({\n workflowId,\n patch,\n }: {\n workflowId: string\n patch: UpdateWorkflowRequest\n }): Promise<WorkflowResponse> => arbi.workflows.update(workflowId, patch),\n onSuccess: () => qc.invalidateQueries({ queryKey: arbiQueryKeys.workflows() }),\n })\n}\n\nexport function useDeleteWorkflow() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: (workflowId: string) => arbi.workflows.delete(workflowId),\n onSuccess: () => qc.invalidateQueries({ queryKey: arbiQueryKeys.workflows() }),\n })\n}\n\n/**\n * Run a workflow now. Resolves with the conversation it created\n * (`conversation_ext_id`), which joins the conversation list.\n */\nexport function useRunWorkflow() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationKey: arbiMutationKeys.runWorkflow(),\n mutationFn: (workflowId: string): Promise<WorkflowRunResponse> =>\n arbi.workflows.run(workflowId),\n onSuccess: () =>\n Promise.all([\n qc.invalidateQueries({ queryKey: arbiQueryKeys.workflows() }),\n qc.invalidateQueries({ queryKey: arbiQueryKeys.allConversations() }),\n ]),\n })\n}\n\n// ── Agents ──────────────────────────────────────────────────────────────────\n\n/** Create an agent by name. The one-time `signing_private_key` is in the result. */\nexport function useCreateAgent() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: (name: string) => arbi.agents.create(name),\n onSuccess: () => qc.invalidateQueries({ queryKey: arbiQueryKeys.agents() }),\n })\n}\n\n/**\n * Generate an avatar for an owned agent from a prompt and set it as its picture. Resolves with the\n * agent (`picture` set); the agent list refreshes.\n */\nexport function useGenerateAgentAvatar() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: ({ agentExtId, prompt }: { agentExtId: string; prompt: string }) =>\n arbi.agents.generateAvatar(agentExtId, prompt),\n onSuccess: () => qc.invalidateQueries({ queryKey: arbiQueryKeys.agents() }),\n })\n}\n\n/** The default and maximum lifetime of a temporary agent authorization (seconds). */\nexport function useAuthorizeLimits(options?: { enabled?: boolean }) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.authorizeLimits(),\n queryFn: () => arbi.agents.authorizeLimits(),\n enabled: (options?.enabled ?? true) && arbi.isLoggedIn,\n })\n}\n\n/** The MCP tools registered on the deployment, for an agent's tool picker. */\nexport function useMcpTools(options?: { enabled?: boolean }) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.mcpTools(),\n queryFn: () => arbi.health.mcpTools(),\n enabled: (options?.enabled ?? true) && arbi.isLoggedIn,\n })\n}\n\n/**\n * An agent's pinned config (persona, model, tool switches), or the library default config when\n * `agentExtId` is omitted: edit forms seed from the first, create forms from the second.\n */\nexport function useAgentConfig(agentExtId?: string, options?: { enabled?: boolean }) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.agentConfig(agentExtId),\n queryFn: async () =>\n (agentExtId\n ? await arbi.agents.getConfig(agentExtId)\n : await arbi.agentConfig.get('default')) as AgentConfigSections | null,\n enabled: (options?.enabled ?? true) && arbi.isLoggedIn,\n })\n}\n\n/** The model names an agent may be pinned to. */\nexport function useAgentModels(options?: { enabled?: boolean }) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.models(),\n queryFn: async () => (await arbi.agentConfig.getModels()).models.map((m) => m.model_name),\n enabled: (options?.enabled ?? true) && arbi.isLoggedIn,\n })\n}\n\nexport interface SaveAgentConfigVars {\n agentExtId: string\n /** Config title; defaults to `agent-<agentExtId>`. */\n title?: string\n /**\n * Parameters to set, per section, e.g. `{ Agents: { PERSONA: '...', WEB_SEARCH_ENABLED: true } }`.\n * Merged key by key over the agent's current config (or the default one for a new agent).\n */\n sections: AgentConfigSections\n}\n\n/** Pin a behaviour config to an agent: read its current config, merge `sections` over it, save. */\nexport function useSaveAgentConfig() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: async ({ agentExtId, title, sections }: SaveAgentConfigVars) => {\n const pinned = (await arbi.agents.getConfig(agentExtId)) as AgentConfigSections | null\n const base = pinned ?? ((await arbi.agentConfig.get('default')) as AgentConfigSections)\n const merged: AgentConfigSections = structuredClone(base)\n for (const [section, params] of Object.entries(sections)) {\n merged[section] = { ...(merged[section] ?? {}), ...params }\n }\n return arbi.agentConfig.save({\n ...merged,\n agent_ext_id: agentExtId,\n title: title ?? `agent-${agentExtId}`,\n } as never)\n },\n onSuccess: (_saved, { agentExtId }) =>\n Promise.all([\n qc.invalidateQueries({ queryKey: arbiQueryKeys.configs() }),\n qc.invalidateQueries({ queryKey: arbiQueryKeys.agentConfig(agentExtId) }),\n // The agent list shows the pinned persona/model, so it refreshes too.\n qc.invalidateQueries({ queryKey: arbiQueryKeys.agents() }),\n ]),\n })\n}\n\n/** The workspaces an agent can currently open (`permanent` tells standing from temporary). */\nexport function useAgentWorkspaces(\n agentExtId: string | undefined,\n options?: { enabled?: boolean }\n) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.agentWorkspaces(agentExtId ?? ''),\n queryFn: () => arbi.agents.listWorkspaces(agentExtId as string),\n enabled: (options?.enabled ?? true) && !!agentExtId && arbi.isLoggedIn,\n })\n}\n\n/** How an agent is given a workspace. */\nexport type AgentAccessMode =\n /** A standing member: the agent can open the workspace while the owner is away. */\n | { kind: 'standing' }\n /** A TTL'd, session-scoped key: gone when the run session ends. `ttlSeconds` omitted = default. */\n | { kind: 'temporary'; ttlSeconds?: number }\n\nexport interface GrantAgentAccessVars {\n agentExtId: string\n workspaceId: string\n /** Default `{ kind: 'standing' }`. */\n mode?: AgentAccessMode\n}\n\n/**\n * Give an agent access to a workspace you own. Standing access adds the agent as a member without\n * switching the open workspace; temporary access mints the agent's run session and deposits a\n * session-scoped key on it (the `session_pubkey_b64` path).\n */\nexport function useGrantAgentAccess() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: async ({\n agentExtId,\n workspaceId,\n mode = { kind: 'standing' },\n }: GrantAgentAccessVars) => {\n if (mode.kind === 'temporary') {\n return arbi.agents.grantTemporaryAccess(agentExtId, workspaceId, mode.ttlSeconds)\n }\n const agent = (await arbi.agents.list()).find((a) => a.external_id === agentExtId)\n if (!agent?.email) throw new Error(\"The agent's address is unknown.\")\n return arbi.workspaces.grantAccess({ workspaceId, emails: [agent.email] })\n },\n onSuccess: (_res, { agentExtId, mode }) => {\n void qc.invalidateQueries({ queryKey: arbiQueryKeys.agentWorkspaces(agentExtId) })\n // Temporary access is a new run session: the session list shows it.\n if (mode?.kind === 'temporary')\n void qc.invalidateQueries({ queryKey: arbiQueryKeys.sessions() })\n },\n })\n}\n\n/**\n * Take an agent out of a workspace (owner only). The workspace is named on the request (opened for\n * the session, not switched to), so the app's current workspace never changes.\n */\nexport function useRevokeAgentAccess() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: ({ agentExtId, workspaceId }: { agentExtId: string; workspaceId: string }) =>\n arbi.workspaces.removeUsers([agentExtId], { workspaceId }),\n onSuccess: (_res, { agentExtId }) =>\n qc.invalidateQueries({ queryKey: arbiQueryKeys.agentWorkspaces(agentExtId) }),\n })\n}\n\n// ── Skills ──────────────────────────────────────────────────────────────────\n\n/**\n * The skills the user can run (own plus the shared marketplace), metadata only. Without a\n * deployment marketplace the server lists a workspace's skills, so the list is kept per workspace\n * and the request names the open one: a switch while it runs cannot answer for another.\n */\nexport function useSkills(options?: {\n enabled?: boolean\n includeHidden?: boolean\n live?: boolean\n}) {\n const arbi = useArbi()\n const workspaceId = arbi.hasWorkspace ? arbi.getWorkspaceId() : ''\n return useQuery({\n queryKey: arbiQueryKeys.skillList(workspaceId, options?.includeHidden ?? false),\n queryFn: () =>\n arbi.assistant.listSkills({\n includeHidden: options?.includeHidden,\n workspaceId: workspaceId || undefined,\n }),\n refetchInterval: options?.live ? 5000 : false,\n enabled: (options?.enabled ?? true) && arbi.isLoggedIn,\n staleTime: 30_000,\n })\n}\n\n/**\n * Upload skill files through the same document path as the main application. A skill is the\n * uploader's own (`mine`) unless an entry says `shared` (everyone's, as \"Share with everyone\" makes\n * it): saving a private skill again never publishes it.\n */\nexport function useUploadSkillFiles() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: async (\n entries: {\n folder: string\n fileName: string\n content: Blob\n shared?: boolean\n /** Explicit target, already open/primed on this session. Uses session-gated upload. */\n workspaceId?: string\n }[]\n ): Promise<{ doc_ext_ids?: string[] }[]> => {\n if (!entries.length) throw new Error('Choose at least one skill file.')\n for (const entry of entries) assertSkillFolder(entry.folder)\n const results = []\n for (const entry of entries) {\n const options = {\n folder: entry.folder,\n wpType: 'skill' as const,\n shared: entry.shared ?? false,\n }\n const result = entry.workspaceId\n ? await arbi.documents.upload(\n [new File([entry.content], entry.fileName, { type: entry.content.type })],\n { ...options, workspaceExtId: entry.workspaceId }\n )\n : await arbi.documents.uploadFile(entry.content, entry.fileName, options)\n throwOnSkipped(result)\n results.push(result)\n }\n return results\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: arbiQueryKeys.skills() }),\n })\n}\n\n/** A skill's files live under `skills/<slug>/`, never outside it. */\nfunction assertSkillFolder(folder: string) {\n if (\n !/^skills\\/[a-z0-9][a-z0-9_-]*(?:\\/[^/]+)*$/.test(folder) ||\n folder.split('/').some((segment) => segment === '..' || segment === '.')\n )\n throw new Error('Skill files need a folder under skills/<name>.')\n}\n\n/** Fail on files the server skipped (a name clash, a rejected type), naming each with its reason. */\nfunction throwOnSkipped(result: { skipped?: { file_name: string; reason: string }[] | null }) {\n if (result.skipped?.length)\n throw new Error(result.skipped.map((file) => `${file.file_name}: ${file.reason}`).join('; '))\n}\n\n/**\n * Save a SKILL.md as the user's own skill `slug` (`arbi.assistant.uploadSkill`): private unless\n * `shared`. Pass `shared: isSharedSkill(skill)` from `@arbidocs/sdk` when changing an existing\n * skill, so a shared one stays shared and nothing else is ever published by saving.\n */\nexport function useSaveSkill() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: async ({\n slug,\n markdown,\n shared,\n }: {\n slug: string\n markdown: string\n shared?: boolean\n }): Promise<{ doc_ext_ids?: string[] }> => {\n assertSkillFolder(`skills/${slug}`)\n const result = await arbi.assistant.uploadSkill(slug, markdown, { shared })\n throwOnSkipped(result)\n return result\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: arbiQueryKeys.skills() }),\n })\n}\n\n/**\n * A skill's main file (SKILL.md) as text, read on demand (a skill's detail or its editor), never\n * for the whole list.\n */\nexport function useSkillSource(docExtId: string | undefined, options?: { enabled?: boolean }) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.skillSource(docExtId ?? ''),\n queryFn: async () => {\n const response = await arbi.documents.download(docExtId as string)\n if (!response.ok) throw new Error(`Could not read the skill (${response.status})`)\n return response.text()\n },\n enabled: (options?.enabled ?? true) && !!docExtId && arbi.isLoggedIn,\n staleTime: 5 * 60_000,\n })\n}\n\n/** Delete a skill: its main file (only its owner may). The skill list refreshes. */\nexport function useDeleteSkill() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: (docExtId: string) => arbi.documents.delete([docExtId]),\n onSuccess: () => qc.invalidateQueries({ queryKey: arbiQueryKeys.skills() }),\n })\n}\n\n/**\n * Share a skill with everyone (`global`) or make it the owner's again (`mine`): its main file's\n * `shared` flag, which the server carries to the skill's other files. A shared name must be unique\n * (409 when someone has shared one already).\n */\nexport function useSetSkillVisibility() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: ({ docExtId, visibility }: { docExtId: string; visibility: 'mine' | 'global' }) =>\n arbi.documents.update([{ external_id: docExtId, shared: visibility === 'global' }]),\n onSuccess: () => qc.invalidateQueries({ queryKey: arbiQueryKeys.skills() }),\n })\n}\n\n/** Independent agent login status, polled while its controls are visible. */\nexport function useAgentSession(agentId: string | undefined, options?: { enabled?: boolean }) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.agentSession(agentId ?? ''),\n queryFn: () => arbi.agents.getSession(agentId!),\n enabled: !!agentId && arbi.isLoggedIn && (options?.enabled ?? true),\n refetchInterval: 5000,\n })\n}\nexport function useAgentChats(agentId: string | undefined) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.agentChats(agentId ?? ''),\n queryFn: () => arbi.agents.listChats(agentId!),\n enabled: !!agentId && arbi.isLoggedIn,\n refetchInterval: 5000,\n })\n}\n/** Starting or closing an agent's login changes its session, workspaces and chats, and the user's sessions. */\nfunction refreshAgentSession(qc: ReturnType<typeof useQueryClient>, agentId: string) {\n return Promise.all(\n [\n arbiQueryKeys.agentSession(agentId),\n arbiQueryKeys.agentWorkspaces(agentId),\n arbiQueryKeys.agentChats(agentId),\n arbiQueryKeys.sessions(),\n ].map((queryKey) => qc.invalidateQueries({ queryKey }))\n )\n}\n\n/** Log an owned agent in on its own (optionally into a workspace). */\nexport function useStartAgentSession() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: ({ agentId, workspaceId }: { agentId: string; workspaceId?: string }) =>\n arbi.agents.startSession(agentId, workspaceId),\n onSuccess: (_session, { agentId }) => refreshAgentSession(qc, agentId),\n })\n}\n\n/** Log an owned agent out. */\nexport function useCloseAgentSession() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: (agentId: string) => arbi.agents.closeSession(agentId),\n onSuccess: (_result, agentId) => refreshAgentSession(qc, agentId),\n })\n}\n","/**\n * Citation data for a chat answer: the SDK's `resolveCitations` / `summarizeCitations` joined into\n * one plain, serialisable shape per citation number, so a surface can show the source document,\n * page and passage for `[statement](#cite-N)` without touching SDK types.\n */\nimport {\n resolveCitations,\n summarizeCitations,\n type MessageMetadataPayload,\n} from '@arbidocs/sdk/browser'\n\nexport interface ArbiChatPassage {\n id: string\n /** The source document's id, when the backend reports it (what \"open document\" needs). */\n documentId: string | null\n documentTitle: string\n page: number | null\n text: string\n}\n\nexport interface ArbiChatCitation {\n /** The number in `(#cite-N)`. */\n num: string\n /** The statement the model cited. */\n statement: string\n /** Title of the first source document. */\n documentTitle: string\n /** Page of the first passage. */\n page: number | null\n passages: ArbiChatPassage[]\n}\n\n/** A passage as one readable line: whitespace folded, leading markdown list/heading marks dropped. */\nfunction previewText(content: string): string {\n return content\n .replace(/\\s+/g, ' ')\n .trim()\n .replace(/^(?:(?:[-*•>]|#{1,6})\\s+)+/, '')\n}\n\n/** The citations of a message's `tools` (stored history) or of streamed metadata. */\nexport function toChatCitations(\n source: { tools?: object | null } | null | undefined\n): ArbiChatCitation[] {\n if (!source?.tools) return []\n // Stored messages and streamed metadata carry the same `tools` map.\n const resolved = resolveCitations(source as MessageMetadataPayload)\n const summaries = summarizeCitations(resolved)\n return resolved.map((r, i) => {\n const summary = summaries[i]\n return {\n num: r.citationNum,\n statement: summary.statement,\n documentTitle: summary.docTitle,\n page: summary.pageNumber,\n passages: r.chunks.map((chunk) => ({\n id: chunk.metadata.chunk_ext_id,\n documentId: chunk.metadata.doc_ext_id ?? null,\n documentTitle: chunk.metadata.doc_title ?? summary.docTitle,\n page: chunk.metadata.page_number ?? null,\n text: previewText(chunk.content),\n })),\n }\n })\n}\n","/**\n * A conversation's threads in the query cache (`arbiQueryKeys.conversationThreads(id)`), and the\n * writers every chat engine and event uses on them: a turn's user and assistant messages, streamed\n * text (buffered per animation frame), settled output items, the resolving commit (held behind\n * the narration dwell), failure, loading state and pending questions.\n */\n\nimport type { QueryClient } from '@tanstack/react-query'\nimport type { components } from '@arbidocs/client'\nimport {\n reduceOutputItem,\n createIndexAssigner,\n type ChatMessage as Message,\n type OutputItemDone,\n type Thread,\n type ThreadsResponse,\n type UserInputRequestEvent,\n} from '@arbidocs/sdk/browser'\nimport { arbiQueryKeys } from '../hooks'\n\ntype MessageResponse = components['schemas']['MessageResponse']\n\n/** The query key of a conversation's threads. */\nexport function getThreadsQueryKey(conversationId: string) {\n return arbiQueryKeys.conversationThreads(conversationId)\n}\n\n/** Every conversation's cached threads (a filter for `invalidateQueries`, `getQueriesData`, …). */\nexport const allConversationThreads = {\n predicate: ({ queryKey }: { queryKey: readonly unknown[] }) =>\n queryKey[0] === 'arbi' && queryKey[1] === 'conversations' && queryKey[3] === 'threads',\n}\n\n/**\n * Whether the cached thread says a message is still being generated on the server\n */\nexport function isMessageRunning(\n queryClient: QueryClient,\n conversationId: string,\n messageId: string\n): boolean {\n const data = queryClient.getQueryData<ThreadsResponse>(getThreadsQueryKey(conversationId))\n return (data?.threads ?? []).some((t: Thread) =>\n t.history.some(\n (m: Message) =>\n m.external_id === messageId && (m.status === 'in_progress' || m.status === 'queued')\n )\n )\n}\n\n/**\n * Add a user message to the conversation cache\n */\nexport function addUserMessageToCache(\n queryClient: QueryClient,\n conversationId: string,\n userMessage: Message,\n options: {\n parentId?: string | null\n parentMessageId?: string | null\n currentParentMessageId?: string | null\n }\n): void {\n const { parentId, parentMessageId, currentParentMessageId } = options\n\n queryClient.setQueryData(\n getThreadsQueryKey(conversationId),\n (oldData: ThreadsResponse | undefined) => {\n if (!oldData) {\n return {\n conversation_ext_id: conversationId,\n threads: [\n {\n history: [userMessage],\n leaf_message_ext_id: userMessage.external_id,\n },\n ],\n }\n }\n\n const threads = [...(oldData.threads || [])]\n\n // The server's parent is authoritative. A follow-up sent while a turn generates names\n // that turn, but the server queues each one behind the follow-ups already waiting, so\n // it may answer it after a later turn. Placing it under the client's guess made ordered\n // follow-ups siblings (\"Branch 1 of 2\") instead of one line.\n const serverParentId = userMessage.parent_message_ext_id\n // A server parent that already has a reply is a real branch point.\n const serverParentKnown =\n !!serverParentId &&\n threads.some((t) => t.history.some((msg) => msg.external_id === serverParentId))\n // A follow-up queued behind another one is chained after that one's answer, which has not\n // streamed in yet. Until it does, the follow-up continues the thread ending at the queued\n // message. The client's guess (the running turn) would wrongly branch it off that turn.\n const queuedLeafIndex = threads.findIndex((t) =>\n t.history.some(\n (msg) => msg.external_id === t.leaf_message_ext_id && msg.status === 'queued'\n )\n )\n const continueIndex =\n serverParentId && !serverParentKnown\n ? queuedLeafIndex\n : threads.findIndex((t) => t.leaf_message_ext_id === serverParentId)\n if (serverParentId && continueIndex !== -1) {\n threads[continueIndex] = {\n ...threads[continueIndex],\n history: [...threads[continueIndex].history, userMessage],\n leaf_message_ext_id: userMessage.external_id,\n }\n return { ...oldData, threads }\n }\n\n const branchFrom = serverParentKnown ? serverParentId : parentId\n const isBranching = serverParentKnown || (parentId && parentId !== currentParentMessageId)\n\n if (isBranching) {\n // Branching: create new thread with shared history up to parent\n let sharedHistory: Message[] = []\n const parentThread = threads.find((thread) =>\n thread.history.some((msg) => msg.external_id === branchFrom)\n )\n if (parentThread) {\n const parentIndex = parentThread.history.findIndex(\n (msg) => msg.external_id === branchFrom\n )\n if (parentIndex !== -1) {\n sharedHistory = parentThread.history.slice(0, parentIndex + 1)\n }\n }\n threads.push({\n history: [...sharedHistory, userMessage],\n leaf_message_ext_id: userMessage.external_id,\n })\n } else if (parentMessageId) {\n // Appending to selected thread\n const threadIndex = threads.findIndex((t) => t.leaf_message_ext_id === parentMessageId)\n if (threadIndex !== -1) {\n threads[threadIndex] = {\n ...threads[threadIndex],\n history: [...threads[threadIndex].history, userMessage],\n leaf_message_ext_id: userMessage.external_id,\n }\n } else {\n threads.push({\n history: [userMessage],\n leaf_message_ext_id: userMessage.external_id,\n })\n }\n } else {\n // New conversation or appending to current thread\n if (threads.length > 0) {\n threads[threads.length - 1] = {\n ...threads[threads.length - 1],\n history: [...threads[threads.length - 1].history, userMessage],\n leaf_message_ext_id: userMessage.external_id,\n }\n } else {\n threads.push({\n history: [userMessage],\n leaf_message_ext_id: userMessage.external_id,\n })\n }\n }\n\n return { ...oldData, threads }\n }\n )\n}\n\n/**\n * Update an existing user message in the cache (e.g., status change from queued to completed).\n * Returns true if the message was found and updated, false otherwise.\n */\nexport function updateUserMessageInCache(\n queryClient: QueryClient,\n conversationId: string,\n userMessage: Message\n): boolean {\n let found = false\n queryClient.setQueryData(\n getThreadsQueryKey(conversationId),\n (oldData: ThreadsResponse | undefined) => {\n if (!oldData) return oldData\n\n const updated = {\n ...oldData,\n threads: oldData.threads.map((thread: Thread) => ({\n ...thread,\n history: thread.history.map((msg: Message) => {\n if (msg.external_id === userMessage.external_id) {\n found = true\n return { ...msg, ...userMessage }\n }\n return msg\n }),\n })),\n }\n return updated\n }\n )\n return found\n}\n\n/** Update only the transient state of a cached user message. */\nexport function updateUserMessageStateInCache(\n queryClient: QueryClient,\n conversationId: string,\n messageId: string,\n status: Message['status'],\n isLoading: boolean\n): void {\n queryClient.setQueryData(\n getThreadsQueryKey(conversationId),\n (oldData: ThreadsResponse | undefined) => {\n if (!oldData) return oldData\n\n return {\n ...oldData,\n threads: oldData.threads.map((thread: Thread) => ({\n ...thread,\n history: thread.history.map((message: Message) =>\n message.external_id === messageId ? { ...message, status, isLoading } : message\n ),\n })),\n }\n }\n )\n}\n\n/** Settle the oldest queued prompt matching an interjection step's content. */\nexport function completeQueuedUserMessageByContent(\n queryClient: QueryClient,\n conversationId: string,\n content: string\n): boolean {\n let completed = false\n queryClient.setQueryData(\n getThreadsQueryKey(conversationId),\n (oldData: ThreadsResponse | undefined) => {\n if (!oldData) return oldData\n\n return {\n ...oldData,\n threads: oldData.threads.map((thread: Thread) => ({\n ...thread,\n history: thread.history.map((message: Message) => {\n if (\n !completed &&\n message.role === 'user' &&\n message.status === 'queued' &&\n message.content === content\n ) {\n completed = true\n return { ...message, status: 'completed', isLoading: false }\n }\n return message\n }),\n })),\n }\n }\n )\n return completed\n}\n\n/**\n * The text of a steering interjection that a run picked up, or null for any other item.\n *\n * The backend reports a queued prompt it steered into the run as a reasoning item of\n * kind `interjection` (`arbi.step`); the \"Your message\" label is the fallback for a\n * backend that predates that field.\n */\nexport function getInterjectionText(item: unknown): string | null {\n const candidate = item as {\n type?: string\n arbi?: { label?: string; step?: string }\n summary?: unknown\n } | null\n if (\n candidate?.type !== 'reasoning' ||\n (candidate.arbi?.step !== 'interjection' && candidate.arbi?.label !== 'Your message')\n ) {\n return null\n }\n const text = Array.isArray(candidate.summary)\n ? (candidate.summary as Array<{ text?: string }>).map((c) => c.text ?? '').join('')\n : ''\n return text || null\n}\n\n/**\n * Whether the thread that ends at `leafId` contains `messageId`, i.e. `leafId` is\n * `messageId` itself or a later turn in the same line.\n */\nexport function threadEndingAtContains(\n queryClient: QueryClient,\n conversationId: string,\n leafId: string,\n messageId: string\n): boolean {\n const data = queryClient.getQueryData<ThreadsResponse>(getThreadsQueryKey(conversationId))\n const thread = data?.threads?.find((t: Thread) => t.leaf_message_ext_id === leafId)\n return !!thread?.history.some((m: Message) => m.external_id === messageId)\n}\n\n/**\n * When the run's assistant message is already in the cache, the moment it was created (ms),\n * so a reattached live timer keeps counting from the run's real start instead of from the\n * attach. Undefined when the row isn't loaded yet or has no usable timestamp.\n */\nexport function getRunStartedAt(\n queryClient: QueryClient,\n conversationId: string,\n messageId: string\n): number | undefined {\n const data = queryClient.getQueryData<ThreadsResponse>(getThreadsQueryKey(conversationId))\n const message = data?.threads\n .flatMap((thread: Thread) => thread.history)\n .find((m: Message) => m.external_id === messageId)\n const startedAt = message?.created_at ? Date.parse(message.created_at) : NaN\n // Never in the future: a server clock ahead of this one would show a negative timer.\n return Number.isFinite(startedAt) ? Math.min(startedAt, Date.now()) : undefined\n}\n\n/**\n * Ensure an assistant message row exists in the cache for a run we're ATTACHING to\n * (foregrounding a background run in the conversation view). Unlike\n * `addAssistantMessageToCache`, this is idempotent: if the run's assistant message\n * is already present (loaded from history), it just flips `isLoading` on; otherwise\n * it appends a loading placeholder to the last thread so the live steps/answer have\n * a row to accumulate under. No-op when the threads cache hasn't loaded yet.\n */\nexport function ensureAssistantMessageLoading(\n queryClient: QueryClient,\n conversationId: string,\n messageId: string\n): void {\n queryClient.setQueryData(\n getThreadsQueryKey(conversationId),\n (oldData: ThreadsResponse | undefined) => {\n if (!oldData) return oldData\n\n const exists = oldData.threads.some((t: Thread) =>\n t.history.some((m: Message) => m.external_id === messageId)\n )\n if (exists) {\n return {\n ...oldData,\n threads: oldData.threads.map((thread: Thread) => ({\n ...thread,\n history: thread.history.map((msg: Message) =>\n msg.external_id === messageId ? { ...msg, isLoading: true } : msg\n ),\n })),\n }\n }\n\n const placeholder: Message = {\n role: 'assistant',\n content: '',\n external_id: messageId,\n created_at: new Date().toISOString(),\n config_ext_id: null,\n created_by_ext_id: '',\n conversation_ext_id: conversationId,\n tokens: 0,\n status: 'in_progress',\n isLoading: true,\n }\n return {\n ...oldData,\n threads: oldData.threads.map((thread: Thread, index: number) =>\n index === oldData.threads.length - 1\n ? {\n ...thread,\n history: [...thread.history, placeholder],\n leaf_message_ext_id: placeholder.external_id,\n }\n : thread\n ),\n }\n }\n )\n}\n\n/**\n * Replace an assistant message's content outright. Used when attaching to a\n * background run (`response.output_text.done` carries the whole answer, not\n * deltas), and at the one moment a live stream's body legitimately loses text:\n * the answer item settles and replaces the interim narration lines accumulated\n * during the turn (see handleOutputItemDone).\n */\nexport function setMessageContent(\n queryClient: QueryClient,\n conversationId: string,\n messageId: string,\n content: string\n): void {\n discardStreamingTokensForMessage(conversationId, messageId)\n queryClient.setQueryData(\n getThreadsQueryKey(conversationId),\n (oldData: ThreadsResponse | undefined) => {\n if (!oldData) return oldData\n return {\n ...oldData,\n threads: oldData.threads.map((thread: Thread) => ({\n ...thread,\n history: thread.history.map((msg: Message) =>\n msg.external_id === messageId ? { ...msg, content } : msg\n ),\n })),\n }\n }\n )\n}\n\n/**\n * Record that a narration item just settled: everything streamed so far is now\n * superseded prose, and whatever arrives next is the live segment.\n *\n * Buffered tokens are flushed first — the boundary is a character offset into\n * `content`, so it is only correct once every delta for the settled item has\n * actually landed in the cache.\n *\n * Also guarantees the block separator. Items are concatenated into one string,\n * so a paragraph break between two of them depended entirely on the model\n * ending its prose with newlines. When it did not, the next item ran on\n * mid-line (\"…in parallel.Step 2: Read the relevant document\") — the boundary\n * has to supply the break itself.\n */\nexport function markNarrationSettled(\n queryClient: QueryClient,\n conversationId: string,\n messageId: string\n): void {\n flushStreamingTokens(queryClient)\n queryClient.setQueryData(\n getThreadsQueryKey(conversationId),\n (oldData: ThreadsResponse | undefined) => {\n if (!oldData) return oldData\n return {\n ...oldData,\n threads: oldData.threads.map((thread: Thread) => ({\n ...thread,\n history: thread.history.map((msg: Message) => {\n if (msg.external_id !== messageId) return msg\n const settled = (msg.content ?? '').replace(/\\s+$/, '')\n if (!settled) return msg\n const content = `${settled}\\n\\n`\n return { ...msg, content, settledNarrationLength: content.length }\n }),\n })),\n }\n }\n )\n}\n\n/**\n * Take a settled narration item's text out of a streaming answer's body. The item's deltas were\n * appended verbatim, so its text is in the body as streamed, normally at the end (the server\n * settles a narration item before anything else streams). The text stays in the steps trace.\n */\nexport function removeSettledNarration(\n queryClient: QueryClient,\n conversationId: string,\n messageId: string,\n /** The settled item's `content` parts. */\n itemContent: unknown\n): void {\n const text = Array.isArray(itemContent)\n ? (itemContent as Array<{ text?: string }>).map((c) => c.text ?? '').join('')\n : ''\n if (!text.trim()) return\n flushStreamingTokens(queryClient)\n queryClient.setQueryData(\n getThreadsQueryKey(conversationId),\n (oldData: ThreadsResponse | undefined) => {\n if (!oldData) return oldData\n return {\n ...oldData,\n threads: oldData.threads.map((thread: Thread) => ({\n ...thread,\n history: thread.history.map((msg: Message) => {\n if (msg.external_id !== messageId) return msg\n const body = msg.content ?? ''\n const at = body.lastIndexOf(text)\n if (at === -1) return msg\n const rest = body.slice(0, at) + body.slice(at + text.length)\n const content = rest.trim() ? rest : ''\n // The dimmed prefix cannot reach past the text that is left.\n const settled = Math.min(msg.settledNarrationLength ?? 0, content.length)\n return { ...msg, content, settledNarrationLength: settled || undefined }\n }),\n })),\n }\n }\n )\n}\n\n/**\n * Add an assistant message placeholder to the cache (for streaming), placed right after the\n * user message it answers.\n *\n * Follow-ups sent while a turn runs are saved at once, each with its own answer row (status\n * `queued`), so when a queued turn starts its user message may no longer be the thread's leaf:\n * later follow-ups already sit below it. The answer then goes right after its user message, not\n * at the end, and a stored queued row (loaded by a refetch) is started in place, not duplicated.\n *\n * @returns false when the user message was named but is not in the cache, so the answer could\n * only be appended to the last thread; the caller re-reads the thread to correct it.\n */\nexport function addAssistantMessageToCache(\n queryClient: QueryClient,\n conversationId: string,\n assistantMessage: Message,\n /** The user message this answers. Its thread gets the answer; else the last thread. */\n userMessageId?: string | null\n): boolean {\n let placed = true\n queryClient.setQueryData(\n getThreadsQueryKey(conversationId),\n (oldData: ThreadsResponse | undefined) => {\n if (!oldData) return oldData\n const answerId = assistantMessage.external_id\n\n // The server stored this answer row already (queued): start it where it is.\n const stored = oldData.threads.some((t: Thread) =>\n t.history.some((m: Message) => m.external_id === answerId)\n )\n if (stored) {\n return {\n ...oldData,\n threads: oldData.threads.map((thread: Thread) => ({\n ...thread,\n history: thread.history.map((m: Message) =>\n m.external_id === answerId\n ? { ...m, status: assistantMessage.status, isLoading: assistantMessage.isLoading }\n : m\n ),\n })),\n }\n }\n\n // The user message ends a thread: the answer becomes that thread's new leaf.\n const leafIndex = userMessageId\n ? oldData.threads.findIndex((t: Thread) => t.leaf_message_ext_id === userMessageId)\n : -1\n // Follow-ups are queued after the user message: insert the answer right after it.\n let holderIndex = -1\n if (userMessageId && leafIndex === -1) {\n oldData.threads.forEach((t: Thread, index: number) => {\n if (t.history.some((m: Message) => m.external_id === userMessageId)) holderIndex = index\n })\n }\n if (userMessageId && leafIndex === -1 && holderIndex === -1) placed = false\n const appendIndex = leafIndex !== -1 ? leafIndex : oldData.threads.length - 1\n\n return {\n ...oldData,\n threads: oldData.threads.map((thread: Thread, index: number) => {\n if (holderIndex !== -1) {\n if (index !== holderIndex) return thread\n const at = thread.history.findIndex((m: Message) => m.external_id === userMessageId)\n const history = [...thread.history]\n history.splice(at + 1, 0, assistantMessage)\n return { ...thread, history }\n }\n if (index === appendIndex) {\n return {\n ...thread,\n history: [...thread.history, assistantMessage],\n leaf_message_ext_id: answerId,\n }\n }\n return thread\n }),\n }\n }\n )\n return placed\n}\n\n/**\n * Internal helper that synchronously writes a chunk of text onto an assistant\n * message's content. Called by the rAF flusher below and by tests that want\n * deterministic behavior.\n */\nfunction applyTokenChunkToCache(\n queryClient: QueryClient,\n conversationId: string,\n messageId: string,\n chunk: string\n): void {\n queryClient.setQueryData(\n getThreadsQueryKey(conversationId),\n (oldData: ThreadsResponse | undefined) => {\n if (!oldData) return oldData\n\n return {\n ...oldData,\n threads: oldData.threads.map((thread: Thread) => ({\n ...thread,\n history: thread.history.map((msg: Message) => {\n if (msg.external_id === messageId) {\n return { ...msg, content: msg.content + chunk }\n }\n return msg\n }),\n })),\n }\n }\n )\n}\n\n/**\n * Per-stream pending token buffer. We coalesce every token that arrives in the\n * same frame into a single string, then commit it to React Query once on the\n * next animation frame. This turns a 20–30 Hz stream of full-tree clones into\n * ~60 Hz at most, and ensures <Message> only re-renders once per frame even\n * when the model emits many deltas in quick succession.\n */\ninterface PendingTokenEntry {\n conversationId: string\n messageId: string\n buffer: string\n}\n\nconst pendingTokens = new Map<string, PendingTokenEntry>()\nlet rafHandle: number | null = null\nlet rafSchedule: ((cb: () => void) => number) | null = null\nlet rafCancel: ((handle: number) => void) | null = null\n\nfunction getRafSchedule(): (cb: () => void) => number {\n if (rafSchedule) return rafSchedule\n if (typeof globalThis.requestAnimationFrame === 'function') {\n rafSchedule = (cb) => globalThis.requestAnimationFrame(cb)\n rafCancel = (h) => globalThis.cancelAnimationFrame(h)\n } else {\n // SSR / test fallback — use a microtask-ish timeout.\n rafSchedule = (cb) => {\n const id = setTimeout(cb, 16) as unknown as number\n return id\n }\n rafCancel = (h) => clearTimeout(h as unknown as ReturnType<typeof setTimeout>)\n }\n return rafSchedule\n}\n\nfunction flushPendingTokens(queryClient: QueryClient): void {\n rafHandle = null\n if (pendingTokens.size === 0) return\n // Snapshot and clear before writing, so tokens that arrive while we flush\n // are scheduled for the next frame rather than dropped.\n const entries = Array.from(pendingTokens.values())\n pendingTokens.clear()\n for (const entry of entries) {\n if (entry.buffer.length === 0) continue\n applyTokenChunkToCache(queryClient, entry.conversationId, entry.messageId, entry.buffer)\n }\n}\n\n/**\n * Append streaming token content to an assistant message.\n *\n * Tokens are buffered and flushed once per animation frame. Within a single\n * frame all deltas targeting the same message coalesce into one cache write,\n * so the React tree is diffed at most ~60 times/sec regardless of the model's\n * emit rate. A terminal event should call `flushStreamingTokens()` before\n * committing final metadata so no buffered text is lost.\n */\nexport function appendTokenToMessage(\n queryClient: QueryClient,\n conversationId: string,\n messageId: string,\n tokenContent: string\n): void {\n if (!tokenContent) return\n const key = `${conversationId}::${messageId}`\n const existing = pendingTokens.get(key)\n if (existing) {\n existing.buffer += tokenContent\n } else {\n pendingTokens.set(key, { conversationId, messageId, buffer: tokenContent })\n }\n if (rafHandle === null) {\n const schedule = getRafSchedule()\n rafHandle = schedule(() => flushPendingTokens(queryClient))\n }\n}\n\n/**\n * Force any buffered tokens to be committed to the cache immediately.\n * Call this from terminal handlers (metadata arrival, error, abort) so that\n * the final message reflects every token the server sent before the commit.\n */\nexport function flushStreamingTokens(queryClient: QueryClient): void {\n if (rafHandle !== null && rafCancel) {\n rafCancel(rafHandle)\n rafHandle = null\n }\n flushPendingTokens(queryClient)\n}\n\n/**\n * Drop any buffered tokens for a specific message without writing them.\n * Used when a stream resets content (agent-step transitions) so stale\n * deltas from the previous phase don't clobber the fresh buffer.\n */\nexport function discardStreamingTokensForMessage(conversationId: string, messageId: string): void {\n pendingTokens.delete(`${conversationId}::${messageId}`)\n}\n\n/**\n * Test-only hook: clear all pending buffers and cancel the scheduled flush.\n * @internal\n */\nexport function __resetStreamingTokenBufferForTests(): void {\n if (rafHandle !== null && rafCancel) {\n rafCancel(rafHandle)\n }\n rafHandle = null\n pendingTokens.clear()\n}\n\n/**\n * Assistant messages whose body swap is waiting out the narration dwell,\n * keyed `conversationId::messageId` → timer handle.\n *\n * Two things read this, and both are the point:\n * - `commitFinalMessage` itself, so a second `response.completed` for the same\n * message replaces the pending swap instead of racing it;\n * - `clearLoadingState`, which runs when the stream socket closes and would\n * otherwise un-fade the body a beat before the swap lands — splitting the\n * single resolving reflow back into two.\n */\nconst pendingFinalCommits = new Map<string, ReturnType<typeof setTimeout>>()\n\nconst finalCommitKey = (conversationId: string, messageId: string) =>\n `${conversationId}::${messageId}`\n\n/** Is this message's resolving commit still queued behind the dwell? */\nexport function hasPendingFinalCommit(conversationId: string, messageId: string): boolean {\n return pendingFinalCommits.has(finalCommitKey(conversationId, messageId))\n}\n\nfunction cancelPendingFinalCommit(conversationId: string, messageId: string): void {\n const key = finalCommitKey(conversationId, messageId)\n const handle = pendingFinalCommits.get(key)\n if (handle !== undefined) {\n clearTimeout(handle)\n pendingFinalCommits.delete(key)\n }\n}\n\n/**\n * Resolve a streamed assistant message: the server's answer replaces everything\n * the model said, the citations computed against that exact string arrive with\n * it, and `isLoading` clears — all in ONE write, so the window moves once.\n * Committing the content swap and the un-fading separately is what made it\n * jitter.\n *\n * `notBefore` (epoch ms, 0 = now) is the narration dwell: freshly-settled prose\n * is guaranteed its reading window before the swap is allowed to remove it.\n *\n * What waits is only the DISPLAY. Everything the rest of the app reasons about —\n * `status` above all — lands immediately, because the leaf assistant message's\n * status is how the app knows whether a run is still in flight: hold it at\n * `in_progress` after the stream has closed and the conversation attaches a run\n * stream to its own finished turn (Conversation.tsx `attachResponseId`), which\n * spins into an infinite update loop. The early write is invisible: the body is\n * unchanged, the footer is still hidden behind `isLoading`, and the citation\n * markers the payload brings do not appear in the streamed text, so nothing\n * renders differently until the swap.\n */\nexport function commitFinalMessage(\n queryClient: QueryClient,\n conversationId: string,\n messageId: string,\n metadata: MessageResponse,\n notBefore = 0\n): void {\n cancelPendingFinalCommit(conversationId, messageId)\n cancelPendingFinalCommit(conversationId, metadata.external_id)\n const delay = Math.max(0, notBefore - Date.now())\n if (delay === 0) {\n updateMessageWithMetadata(queryClient, conversationId, messageId, metadata)\n return\n }\n // Buffered deltas are flushed rather than dropped, so the body the user is\n // reading is the complete one and does not twitch while it waits.\n flushStreamingTokens(queryClient)\n // Keyed by the SERVER's id: the early write rebuilds the message from the\n // payload, so that is the id it carries while the swap is pending — and the id\n // clearLoadingState will look up.\n const key = finalCommitKey(conversationId, metadata.external_id)\n applyMetadata(queryClient, conversationId, messageId, metadata, { holdBody: true })\n pendingFinalCommits.set(\n key,\n setTimeout(() => {\n pendingFinalCommits.delete(key)\n // The message now carries the server's id; the swap targets that.\n swapInFinalBody(queryClient, conversationId, metadata.external_id, metadata.content ?? '')\n }, delay)\n )\n}\n\n/** The one visible move: the answer takes the window and stops being provisional. */\nfunction swapInFinalBody(\n queryClient: QueryClient,\n conversationId: string,\n messageId: string,\n content: string\n): void {\n queryClient.setQueryData(\n getThreadsQueryKey(conversationId),\n (oldData: ThreadsResponse | undefined) => {\n if (!oldData) return oldData\n return {\n ...oldData,\n threads: oldData.threads.map((thread: Thread) => ({\n ...thread,\n history: thread.history.map((msg: Message) =>\n msg.external_id === messageId ? { ...msg, content, isLoading: false } : msg\n ),\n })),\n }\n }\n )\n}\n\n/**\n * Test-only hook: drop every deferred commit without running it.\n * @internal\n */\nexport function __resetPendingFinalCommitsForTests(): void {\n for (const handle of pendingFinalCommits.values()) clearTimeout(handle)\n pendingFinalCommits.clear()\n}\n\n/**\n * Update an assistant message with final metadata from server\n */\nexport function updateMessageWithMetadata(\n queryClient: QueryClient,\n conversationId: string,\n streamingMessageId: string,\n metadata: MessageResponse\n): void {\n applyMetadata(queryClient, conversationId, streamingMessageId, metadata, { holdBody: false })\n}\n\n/**\n * Rebuild a streaming assistant message from the server's final payload.\n *\n * `holdBody` keeps the body exactly as the reader currently sees it (and keeps it\n * provisional) while letting every other fact land — see commitFinalMessage for\n * why the facts must not wait.\n */\nfunction applyMetadata(\n queryClient: QueryClient,\n conversationId: string,\n streamingMessageId: string,\n metadata: MessageResponse,\n { holdBody }: { holdBody: boolean }\n): void {\n // Final content comes from server metadata — drop any buffered tokens so\n // we don't re-append what's about to be overwritten.\n if (!holdBody) discardStreamingTokensForMessage(conversationId, streamingMessageId)\n queryClient.setQueryData(\n getThreadsQueryKey(conversationId),\n (oldData: ThreadsResponse | undefined) => {\n if (!oldData) return oldData\n\n const serverAssistantId = metadata.external_id\n\n return {\n ...oldData,\n threads: oldData.threads.map((thread: Thread) => ({\n ...thread,\n history: thread.history.map((msg: Message) => {\n if (msg.external_id === streamingMessageId) {\n // Always use server metadata content — it includes citation markers\n // with offset_start/offset_end calculated against this exact string.\n // This REBUILDS the message from the server payload, so every\n // client-side field has to be carried over explicitly or it is\n // destroyed here at the end of the turn.\n return {\n ...metadata,\n isLoading: holdBody ? true : false,\n content: holdBody ? msg.content : metadata.content,\n agentSteps: msg.agentSteps,\n pendingUserInput: msg.pendingUserInput,\n // While the body is held for the narration dwell, the dimmed\n // prose must stay dimmed: dropping the boundary here would\n // un-fade it a beat before the swap, splitting the one resolving\n // reflow in two.\n settledNarrationLength: msg.settledNarrationLength,\n }\n }\n return msg\n }),\n leaf_message_ext_id:\n thread.leaf_message_ext_id === streamingMessageId\n ? serverAssistantId\n : thread.leaf_message_ext_id,\n })),\n }\n }\n )\n}\n\n/**\n * Mark a specific assistant message as failed in the conversation cache.\n * Called when WebSocket response_complete arrives with status='failed'.\n */\nexport function markMessageAsFailed(\n queryClient: QueryClient,\n conversationId: string,\n messageId: string\n): void {\n // Flush any buffered tokens first so the failed message still reflects\n // whatever the model produced before the failure.\n flushStreamingTokens(queryClient)\n // A failure supersedes a queued resolving commit — letting it fire afterwards\n // would quietly un-fail the message.\n cancelPendingFinalCommit(conversationId, messageId)\n queryClient.setQueryData(\n getThreadsQueryKey(conversationId),\n (oldData: ThreadsResponse | undefined) => {\n if (!oldData) return oldData\n\n return {\n ...oldData,\n threads: oldData.threads.map((thread: Thread) => ({\n ...thread,\n history: thread.history.map((msg: Message) =>\n msg.external_id === messageId\n ? { ...msg, status: 'failed' as const, isLoading: false }\n : msg\n ),\n })),\n }\n }\n )\n}\n\n/**\n * Clear loading state on all messages in a conversation.\n *\n * A message whose resolving commit is still queued behind the narration dwell is\n * left alone: clearing `isLoading` early would un-fade a body that still holds\n * the narration, and the real commit would then reflow it a second time — the\n * two-step ending this design exists to remove. The pending commit clears\n * `isLoading` itself when it lands.\n */\nexport function clearLoadingState(queryClient: QueryClient, conversationId: string): void {\n queryClient.setQueryData(\n getThreadsQueryKey(conversationId),\n (oldData: ThreadsResponse | undefined) => {\n if (!oldData) return oldData\n\n return {\n ...oldData,\n threads: oldData.threads.map((thread: Thread) => ({\n ...thread,\n history: thread.history.map((msg: Message) =>\n msg.isLoading && !hasPendingFinalCommit(conversationId, msg.external_id ?? '')\n ? { ...msg, isLoading: false }\n : msg\n ),\n })),\n }\n }\n )\n}\n\n/**\n * Append an agent step event to a message's agentSteps array\n */\nexport function applyOutputItemToMessage(\n queryClient: QueryClient,\n conversationId: string,\n messageId: string,\n ev: OutputItemDone\n): void {\n queryClient.setQueryData(\n getThreadsQueryKey(conversationId),\n (oldData: ThreadsResponse | undefined) => {\n if (!oldData) return oldData\n return {\n ...oldData,\n threads: oldData.threads.map((thread: Thread) => ({\n ...thread,\n history: thread.history.map((msg: Message) => {\n if (msg.external_id !== messageId) return msg\n const existing = msg.agentSteps || []\n // The id->index map is rebuilt from the current steps each call: the\n // cache is immutable, so there is nowhere to keep it, and it is O(n)\n // over a handful of steps. The reducer is the one home for protocol\n // logic — this function just persists its result.\n const { assign, resolve } = createIndexAssigner(existing)\n const updated = reduceOutputItem(existing, ev, assign, resolve)\n return updated === existing ? msg : { ...msg, agentSteps: updated }\n }),\n })),\n }\n }\n )\n\n // A sub-agent that just settled has persisted its own branch server-side\n // (task message + reply) — a whole new thread this conversation's cached\n // `threads` list has never seen. The map above only patches steps on\n // EXISTING messages, so without this the branch stays invisible (no open-\n // thread affordance, no branch badge) until something else happens to\n // refetch. `staleTime` on useConversationThreads is long specifically because\n // WebSocket/SSE traffic is expected to keep it fresh — this is that update.\n const arbi = ev.item?.arbi\n if (\n (arbi?.subagent_status === 'done' || arbi?.subagent_status === 'failed') &&\n arbi.task_message_ext_id\n ) {\n queryClient.invalidateQueries({ queryKey: getThreadsQueryKey(conversationId) })\n }\n}\n\n/**\n * Persist the turn's final token/£ budget snapshot (from\n * response.completed) onto the assistant message. Distinct from\n * applyOutputItemToMessage's agentSteps: steps only ever cover\n * function_call/reasoning items, so they never carry the true final total —\n * see the finalContextUsage doc comment on Message in types/ui.ts.\n */\nexport function applyFinalContextToMessage(\n queryClient: QueryClient,\n conversationId: string,\n messageId: string,\n context: Message['finalContextUsage']\n): void {\n queryClient.setQueryData(\n getThreadsQueryKey(conversationId),\n (oldData: ThreadsResponse | undefined) => {\n if (!oldData) return oldData\n return {\n ...oldData,\n threads: oldData.threads.map((thread: Thread) => ({\n ...thread,\n history: thread.history.map((msg: Message) =>\n msg.external_id === messageId ? { ...msg, finalContextUsage: context } : msg\n ),\n })),\n }\n }\n )\n}\n\nexport function setUserInputRequest(\n queryClient: QueryClient,\n conversationId: string,\n messageId: string,\n request: UserInputRequestEvent\n): void {\n queryClient.setQueryData(\n getThreadsQueryKey(conversationId),\n (oldData: ThreadsResponse | undefined) => {\n if (!oldData) return oldData\n\n return {\n ...oldData,\n threads: oldData.threads.map((thread: Thread) => ({\n ...thread,\n history: thread.history.map((msg: Message) => {\n if (msg.external_id === messageId) {\n return { ...msg, pendingUserInput: request }\n }\n return msg\n }),\n })),\n }\n }\n )\n}\n\n/**\n * Reset the content of a message (clear the body).\n */\nexport function resetMessageContent(\n queryClient: QueryClient,\n conversationId: string,\n messageId: string\n): void {\n setMessageContent(queryClient, conversationId, messageId, '')\n}\n\n/**\n * Clear the pending user input request on a message\n */\nexport function clearUserInputRequest(\n queryClient: QueryClient,\n conversationId: string,\n messageId: string\n): void {\n queryClient.setQueryData(\n getThreadsQueryKey(conversationId),\n (oldData: ThreadsResponse | undefined) => {\n if (!oldData) return oldData\n\n return {\n ...oldData,\n threads: oldData.threads.map((thread: Thread) => ({\n ...thread,\n history: thread.history.map((msg: Message) => {\n if (msg.external_id === messageId) {\n return { ...msg, pendingUserInput: null }\n }\n return msg\n }),\n })),\n }\n }\n )\n}\n","/**\n * Who can be @mentioned in a conversation, which mode it is in, and how a message is routed: to\n * ARBI (a turn) or to the people in the thread (a comment). The send path reads the caches here, so\n * it routes exactly as the composer shows.\n */\n\nimport { useCallback } from 'react'\nimport type { QueryClient } from '@tanstack/react-query'\nimport type { components } from '@arbidocs/client'\nimport { getUserDisplayName } from '../users/user-display'\nimport { arbiQueryKeys } from '../hooks'\nimport { useAssistantName } from '../host/assistant-copy'\nimport { findConversation, isConversationShared } from '../conversation-list'\nimport { allConversationThreads } from './conversation-cache'\nimport {\n extractMentions,\n linkMentions,\n type MentionCandidate,\n type MessageMentionRef,\n} from './mentions'\n\ntype WorkspaceUser = components['schemas']['WorkspaceUserResponse']\ntype ThreadsResponse = components['schemas']['ThreadsResponse']\n\n/** When the assistant answers in a conversation: every message, or only when @mentioned. */\nexport type AssistantMode = components['schemas']['AssistantMode']\n\n/**\n * What the assistant is called in the composer when the host names it nothing else\n * (`ArbiHostConfig.assistantName`). The server stores this label with every assistant mention.\n */\nexport const ASSISTANT_MENTION_LABEL = 'ARBI'\n\n/**\n * Every name the assistant answers to: the host's, and \"ARBI\" (the server's stored label, and what\n * people may still type out of habit under a host's own name).\n */\nexport function assistantLabels(assistantName: string = ASSISTANT_MENTION_LABEL): string[] {\n return assistantName.toLowerCase() === ASSISTANT_MENTION_LABEL.toLowerCase()\n ? [assistantName]\n : [assistantName, ASSISTANT_MENTION_LABEL]\n}\n\n/**\n * `linkMentions` on this site: a mention of the assistant typed with the host's name for it is a\n * chip as well as one under the server's stored label (earlier `@ARBI` mentions).\n */\nexport function useLinkMentions(): (\n content: string,\n mentions: ReadonlyArray<MessageMentionRef> | null | undefined\n) => string {\n const assistantName = useAssistantName()\n return useCallback(\n (content, mentions) => linkMentions(content, mentions, [assistantName]),\n [assistantName]\n )\n}\n\n/**\n * The mention candidates for a workspace: the assistant first (as `assistantName`), then every\n * human member except the current user (agents are not mentionable). People's labels use the\n * server's display-name rule so the inserted `@<label>` matches what the server stores.\n */\nexport function buildMentionCandidates(\n users: ReadonlyArray<WorkspaceUser>,\n currentUserId: string | null | undefined,\n assistantName: string = ASSISTANT_MENTION_LABEL\n): MentionCandidate[] {\n const people = users\n .filter((wu) => !wu.agent_ext_id && wu.user.external_id !== currentUserId)\n .map<MentionCandidate>((wu) => ({\n id: wu.user.external_id,\n kind: 'user',\n label: getUserDisplayName(wu.user),\n description: wu.user.email,\n }))\n .sort((a, b) => a.label.localeCompare(b.label))\n return [{ id: 'assistant', kind: 'assistant', label: assistantName }, ...people]\n}\n\n/**\n * A workspace's mention candidates for routing a send, from the cached member list: the menu's,\n * plus the assistant under \"ARBI\" when the host names it otherwise, so a typed `@ARBI` still\n * reaches it (the menu offers only the host's name).\n */\nexport function cachedMentionCandidates(\n queryClient: QueryClient,\n workspaceId: string | null | undefined,\n currentUserId: string | null | undefined,\n assistantName: string = ASSISTANT_MENTION_LABEL\n): MentionCandidate[] {\n const users =\n (workspaceId &&\n queryClient.getQueryData<WorkspaceUser[]>(arbiQueryKeys.workspaceUsers(workspaceId))) ||\n []\n const aliases = assistantLabels(assistantName)\n .slice(1)\n .map<MentionCandidate>((label) => ({ id: 'assistant', kind: 'assistant', label }))\n return [...buildMentionCandidates(users, currentUserId, assistantName), ...aliases]\n}\n\n/**\n * The assistant mode of a conversation from whatever is cached: its threads response (always\n * present once it is open, even when it is not in the cached list, e.g. a thread someone just\n * shared by mentioning you), else its list row. A conversation not created yet uses `newMode`, the\n * mode chosen in the composer.\n */\nexport function cachedAssistantMode(\n queryClient: QueryClient,\n conversationId: string | null | undefined,\n newMode: AssistantMode\n): AssistantMode {\n if (!conversationId) return newMode\n const threads = queryClient\n .getQueriesData<ThreadsResponse>(allConversationThreads)\n .map(([, data]) => data)\n .find((data) => data?.conversation_ext_id === conversationId)\n if (threads?.assistant_mode) return threads.assistant_mode\n return findConversation(queryClient, conversationId)?.assistant_mode ?? 'always'\n}\n\n/**\n * Whether a message is a comment to people rather than a prompt for ARBI. The one rule for\n * routing a message: an @mention of ARBI always addresses ARBI. Otherwise it's a comment in a\n * shared thread, when it @mentions a person, or in a `mentioned`-mode thread (ARBI only on\n * @mention), solo or not: the mode the composer's toggle shows is the one the send follows, and a\n * group chat never calls ARBI unasked because this user's cached list doesn't show it shared yet.\n */\nexport function isCommentToPeople(\n queryClient: QueryClient,\n conversationId: string | null | undefined,\n content: string,\n candidates: ReadonlyArray<MentionCandidate>\n): boolean {\n const mentioned = extractMentions(content, candidates)\n if (mentioned.some((c) => c.kind === 'assistant')) return false\n if (isConversationShared(queryClient, conversationId)) return true\n if (mentioned.some((c) => c.kind === 'user')) return true\n return (\n !!conversationId && cachedAssistantMode(queryClient, conversationId, 'always') === 'mentioned'\n )\n}\n","/**\n * Saved assistant configurations (configs): the schema their forms are drawn from, saving one,\n * deleting one, and saving a change on top of the person's active config (only what differs\n * from the defaults is sent). The chat's model choice (`useApplyChatModel`) goes through here.\n */\n\nimport { useCallback, useRef } from 'react'\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'\nimport type { components } from '@arbidocs/client'\nimport { useArbi } from '../useArbi'\nimport { arbiQueryKeys } from '../query-keys'\nimport { useAvailableModels, useConfig } from '../hooks'\nimport { useUserSettings } from '../account/settings'\nimport { useArbiSessionState, useArbiSessionStore } from '../session'\nimport { notify } from '../notifications/notify-store'\n\ntype AllConfigs = components['schemas']['AllConfigs']\ntype NonDeveloperConfig = components['schemas']['NonDeveloperConfig']\n/** A config to save: only the fields that differ from the defaults, and a title. */\nexport type ConfigUpdate = components['schemas']['ConfigUpdateData']\n\n/**\n * Whether a config is the full one (a developer's): a non-developer's exposes only its Agents\n * and ArtifactLLM sections.\n */\nexport function isFullConfig(\n config: AllConfigs | NonDeveloperConfig | undefined | null\n): config is AllConfigs {\n return config != null && 'QueryLLM' in config\n}\n\n/** A refused save, in words: each invalid field and why (FastAPI's 422), else the message. */\nexport function formatConfigValidationError(error: unknown): string {\n const apiError = (error as { apiError?: { detail?: unknown } } | null)?.apiError\n const detail = apiError?.detail ?? (error as { detail?: unknown } | null)?.detail\n if (Array.isArray(detail)) {\n const parts = detail\n .map((item) => {\n if (!item || typeof item !== 'object') return null\n const e = item as { loc?: unknown[]; msg?: string }\n const field =\n Array.isArray(e.loc) && e.loc.length > 0\n ? e.loc.filter((p) => p !== 'body').join('.')\n : ''\n return field ? `${field}: ${e.msg ?? 'invalid value'}` : (e.msg ?? null)\n })\n .filter(Boolean)\n if (parts.length > 0) return parts.join('; ')\n }\n if (typeof detail === 'string') return detail\n if (error instanceof Error) return error.message\n return 'Invalid configuration value (out of range)'\n}\n\n/** The JSON schema of every config section (what the config forms draw). */\nexport function useConfigSchema() {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.configSchema(),\n queryFn: () => arbi.agentConfig.getSchema(),\n enabled: arbi.isLoggedIn,\n })\n}\n\n/**\n * Save a config (the server makes it the person's active one). A refused save says which values\n * were wrong.\n */\nexport function useSaveConfig() {\n const arbi = useArbi()\n const queryClient = useQueryClient()\n return useMutation({\n mutationFn: (body: ConfigUpdate) => arbi.agentConfig.save(body),\n onSuccess: () => {\n // Every config read refreshes, and the settings name the new active config.\n void queryClient.invalidateQueries({ queryKey: arbiQueryKeys.configs() })\n void queryClient.invalidateQueries({ queryKey: arbiQueryKeys.userSettings() })\n },\n onError: (error) => {\n notify.error(formatConfigValidationError(error), {\n description: 'Configuration not saved — fix the highlighted values and try again.',\n })\n },\n })\n}\n\n/** Delete one of the person's saved configs. */\nexport function useDeleteConfig() {\n const arbi = useArbi()\n const queryClient = useQueryClient()\n return useMutation({\n mutationFn: (configId: string) => arbi.agentConfig.delete(configId),\n onSuccess: () => queryClient.invalidateQueries({ queryKey: arbiQueryKeys.configs() }),\n })\n}\n\n/** The instrument-level fields of `active` that differ from `defaults`. */\nfunction configDelta(\n active: Record<string, unknown>,\n defaults: Record<string, unknown>\n): Record<string, unknown> {\n const delta: Record<string, unknown> = {}\n for (const [instrument, value] of Object.entries(active)) {\n if (typeof value !== 'object' || value === null) continue\n const defaultInstrument = defaults[instrument]\n if (typeof defaultInstrument !== 'object' || defaultInstrument === null) continue\n const fieldDelta: Record<string, unknown> = {}\n for (const [field, fieldValue] of Object.entries(value as Record<string, unknown>)) {\n if (\n JSON.stringify(fieldValue) !==\n JSON.stringify((defaultInstrument as Record<string, unknown>)[field])\n ) {\n fieldDelta[field] = fieldValue\n }\n }\n if (Object.keys(fieldDelta).length > 0) delta[instrument] = fieldDelta\n }\n return delta\n}\n\n/** `changes` on top of `active`'s overrides, without any field back at its default. */\nfunction deltaOnto(\n changes: Record<string, Record<string, unknown>>,\n active: Record<string, unknown>,\n defaults: Record<string, unknown>\n): Record<string, unknown> {\n const delta = configDelta(active, defaults)\n for (const [instrument, fields] of Object.entries(changes)) {\n delta[instrument] = { ...((delta[instrument] as Record<string, unknown>) ?? {}), ...fields }\n // A field back at its default is not an override.\n const defaultInstrument = defaults[instrument] as Record<string, unknown> | undefined\n if (defaultInstrument) {\n const instrumentDelta = delta[instrument] as Record<string, unknown>\n for (const [field, value] of Object.entries(fields)) {\n if (JSON.stringify(value) === JSON.stringify(defaultInstrument[field])) {\n delete instrumentDelta[field]\n }\n }\n if (Object.keys(instrumentDelta).length === 0) delete delta[instrument]\n }\n }\n return delta\n}\n\n/**\n * Save changes on top of the active config (the chat's choice, else the person's last, else the\n * defaults), keeping its other overrides and sending only what differs from the defaults.\n *\n * save(instrument, field, value, title?) one field (a switch)\n * saveDelta(changes, title?) several at once: { Agents: { ENABLED: true, … } }\n *\n * `baseConfigId`: the config a host shows (it can differ from the chat's), which saves build on\n * instead. Each save reads it first, so one made while it loads keeps its overrides, and builds on\n * the config the previous save made, so quick edits keep each other, also once the host shows a\n * config one of them made. The config a save makes becomes the chat's (`session.chatModel`), so\n * the host shows and uses it. A base that cannot be read is reported like a refused save.\n */\nexport function useSaveConfigField(baseConfigId?: string | null) {\n const arbi = useArbi()\n const queryClient = useQueryClient()\n const saveConfig = useSaveConfig()\n const { data: defaultConfig } = useConfig('default')\n const chatModel = useArbiSessionState((state) => state.chatModel)\n const { data: userSettings } = useUserSettings()\n const activeConfigId = baseConfigId || chatModel || userSettings?.last_config || 'default'\n const { data: activeConfigData } = useConfig(activeConfigId)\n const session = useArbiSessionStore()\n // The saves on the shown config, one after another: every config id they started from or made\n // (the host shows the one a save made once the settings refetch), and the config the latest one\n // leaves (its own on success, the one it started from if refused), which never rejects.\n const chain = useRef<{ ids: Set<string>; latest: Promise<string> } | null>(null)\n\n const buildDelta = (changes: Record<string, Record<string, unknown>>) =>\n deltaOnto(\n changes,\n (activeConfigData ?? {}) as Record<string, unknown>,\n (defaultConfig ?? {}) as Record<string, unknown>\n )\n\n const readConfig = (configId: string) =>\n queryClient.fetchQuery({\n queryKey: arbiQueryKeys.config(configId),\n queryFn: () => arbi.agentConfig.get(configId),\n staleTime: 10 * 60 * 1000,\n }) as Promise<Record<string, unknown>>\n\n const saveOnBase = (\n base: string,\n changes: Record<string, Record<string, unknown>>,\n title: string\n ) => {\n // The shown config is one this chain made or started from: build on whatever it leaves.\n // Anything else is a config the host moved to: start a new chain there.\n const current = chain.current?.ids.has(base) ? chain.current : null\n const ids = current?.ids ?? new Set([base])\n const from = current?.latest ?? Promise.resolve(base)\n const saved = from.then(async (configId) => {\n const [defaults, active] = await Promise.all([\n readConfig('default'),\n readConfig(configId),\n ]).catch((error: unknown) => {\n notify.error(formatConfigValidationError(error), {\n description: 'Configuration not saved — the settings it builds on could not be read.',\n })\n throw error\n })\n const response = await saveConfig.mutateAsync({\n ...deltaOnto(changes, active ?? {}, defaults ?? {}),\n title,\n } as ConfigUpdate)\n if (response?.external_id) {\n ids.add(response.external_id)\n // The host shows the config this save made: the settings refetch does that for the\n // person's last config; one the chat (or a reply) runs on follows it here, as a model\n // pick does. A chain the host has since left does not pull it back.\n const { chatModel } = session.getState()\n const followsSettings = !chatModel && base === userSettings?.last_config\n if (chain.current?.ids === ids && !followsSettings) {\n session.setChatModel(response.external_id)\n }\n }\n return { response, configId: response?.external_id ?? configId }\n })\n chain.current = {\n ids,\n latest: Promise.all([from, saved]).then(\n ([, done]) => done.configId,\n () => from\n ),\n }\n return saved.then(({ response }) => response)\n }\n\n return {\n save: (instrument: string, field: string, value: unknown, title?: string) => {\n const changes = { [instrument]: { [field]: value } }\n const name = title ?? `prefs-${Date.now()}`\n // A refused save, or a base that could not be read, is already reported.\n if (baseConfigId) return void saveOnBase(baseConfigId, changes, name).catch(() => {})\n saveConfig.mutate({ ...buildDelta(changes), title: name } as ConfigUpdate)\n },\n saveDelta: (changes: Record<string, Record<string, unknown>>, title?: string) => {\n const name = title ?? `prefs-${Date.now()}`\n if (baseConfigId) return saveOnBase(baseConfigId, changes, name)\n return saveConfig.mutateAsync({ ...buildDelta(changes), title: name } as ConfigUpdate)\n },\n isPending: saveConfig.isPending,\n }\n}\n\n/** The model a chat runs on when no one picked one: the server chooses per turn. */\nexport const AUTO_CHAT_MODEL = 'auto'\n\n/** Each session's latest model save (a pick the next turn must run on), while it is in flight. */\nconst chatModelSaves = new WeakMap<object, Promise<unknown>>()\n\n/**\n * The chat's model save still in flight, if any: a send waits for it, so the turn runs on the model\n * the picker shows rather than on the config before the pick.\n */\nexport function pendingChatModelSave(session: object): Promise<unknown> | undefined {\n return chatModelSaves.get(session)\n}\n\n/**\n * Run the chat on a model (`auto` for the server's choice): the picker shows it at once, and it is\n * saved as a config delta (the Agents model, under `label`) that the next turn runs on. A send made\n * before the save lands waits for it; of two quick picks, the later one wins.\n */\nexport function useApplyChatModel(): (model: string, label: string) => Promise<void> {\n const session = useArbiSessionStore()\n const { data: availableModels } = useAvailableModels()\n const configField = useSaveConfigField()\n return useCallback(\n async (model, label) => {\n session.setChatModelName(model)\n const agents =\n model === AUTO_CHAT_MODEL\n ? { AGENT_MODEL_NAME: AUTO_CHAT_MODEL, ENABLED: true }\n : {\n AGENT_MODEL_NAME: model,\n AGENT_API_TYPE:\n availableModels?.models?.find((m) => m.model_name === model)?.api_type || 'remote',\n ENABLED: true,\n }\n const save = configField.saveDelta({ Agents: agents }, label).then((response) => {\n if (chatModelSaves.get(session) === save && response?.external_id)\n session.setChatModel(response.external_id)\n })\n chatModelSaves.set(session, save)\n try {\n await save\n } finally {\n if (chatModelSaves.get(session) === save) chatModelSaves.delete(session)\n }\n },\n [availableModels, configField, session]\n )\n}\n","/**\n * The owned agent an existing conversation runs through, when the session has not recorded it\n * (`ArbiChatState.agentChatOwners`: a new sign-in, another device, a chat started in the agent's own\n * panel). An agent chat runs under the agent's own session, so the conversation's creator is the\n * agent (`agt-…`); it is an agent chat of this person when that agent is one of their own.\n */\n\nimport type { QueryClient } from '@tanstack/react-query'\nimport { arbiQueryKeys } from '../hooks'\n\n/** How long the person's agents are taken as current before they are listed again. */\nconst AGENTS_FRESH_MS = 60_000\n\n/** Who created `conversationId`, as the cached conversation lists have it. */\nexport function creatorOf(queryClient: QueryClient, conversationId: string): string | null {\n for (const [, data] of queryClient.getQueriesData<\n Array<{ external_id?: string; created_by_ext_id?: string }>\n >({ queryKey: arbiQueryKeys.allConversations() })) {\n if (!Array.isArray(data)) continue\n const row = data.find((entry) => entry?.external_id === conversationId)\n if (row?.created_by_ext_id) return row.created_by_ext_id\n }\n return null\n}\n\n/**\n * The person's own agent that created `conversationId`, or undefined (not an agent chat, not one of\n * theirs, or not known). `listAgents` lists the person's agents (`arbi.agents.list`).\n */\nexport async function agentChatOwnerOf(\n queryClient: QueryClient,\n listAgents: () => Promise<ReadonlyArray<{ external_id: string }>>,\n conversationId: string\n): Promise<string | undefined> {\n const creator = creatorOf(queryClient, conversationId)\n if (!creator?.startsWith('agt-')) return undefined\n const agents = await queryClient\n .fetchQuery({\n queryKey: arbiQueryKeys.agents(),\n queryFn: listAgents,\n staleTime: AGENTS_FRESH_MS,\n })\n .catch(() => undefined)\n return agents?.some((agent) => agent.external_id === creator) ? creator : undefined\n}\n","/**\n * A conversation's bound document in the query cache, and the writes that change it on the server.\n *\n * The server holds the binding (`./thread-document`); the cache is its mirror: the conversation's\n * row in the workspace's list (`bound_document_ext_id`, `bound_document_unavailable`), else its\n * threads response (a thread opened from a link, not listed yet). An attach or unbind shows at once\n * and is written with `PATCH /v1/conversation/{id}`; a failure puts the cache back. Another\n * member's or device's change arrives as `conversation.document_binding_changed`\n * (`./conversation-events`), which re-reads the conversation under this reader's access.\n */\n\nimport type { QueryClient } from '@tanstack/react-query'\nimport type { Arbi, ConversationResponse, ThreadsResponse } from '@arbidocs/sdk/browser'\nimport { findConversation, patchConversation } from '../conversation-list'\nimport { getThreadsQueryKey } from './conversation-cache'\nimport {\n UNBOUND,\n bindingOfRow,\n forgetLegacyThreadDocuments,\n readLegacyThreadDocuments,\n type ThreadBinding,\n} from './thread-document'\n\n/** What this module needs of the session store (structural, like the rest of the chat engine). */\ninterface NewChatSession {\n getState(): { conversationId: string | null; newChatDocumentId: string | null }\n setNewChatDocumentId(documentId: string | null): void\n}\n\n/** A saved conversation's binding, from the cache (its list row, else its threads). */\nexport function threadBinding(\n queryClient: QueryClient,\n conversationId: string | null | undefined\n): ThreadBinding {\n if (!conversationId) return UNBOUND\n const row = findConversation(queryClient, conversationId)\n if (row) return bindingOfRow(row)\n const threads = queryClient.getQueryData<ThreadsResponse>(getThreadsQueryKey(conversationId))\n return bindingOfRow(threads ? { external_id: conversationId, ...threads } : null)\n}\n\n/** The document the open conversation is bound to: its saved binding, or the new chat's. */\nexport function boundDocumentOf(\n queryClient: QueryClient,\n state: ReturnType<NewChatSession['getState']>\n): string | null {\n return state.conversationId\n ? threadBinding(queryClient, state.conversationId).documentId\n : state.newChatDocumentId\n}\n\n/** Put a binding in the cache (the list rows and the threads response that hold the conversation). */\nexport function cacheThreadBinding(\n queryClient: QueryClient,\n conversationId: string,\n binding: ThreadBinding\n): void {\n const fields = {\n bound_document_ext_id: binding.documentId,\n bound_document_unavailable: binding.unavailable,\n }\n patchConversation(queryClient, conversationId, fields)\n queryClient.setQueryData<ThreadsResponse>(getThreadsQueryKey(conversationId), (old) =>\n old ? { ...old, ...fields } : old\n )\n}\n\n/**\n * Bind a saved conversation to a document, or (null) unbind it: shown at once, written to the\n * server. Rejects (with the cache put back) when the server refuses: a document of another\n * workspace, or one the caller cannot read.\n */\nexport async function bindThreadDocument(\n arbi: Pick<Arbi, 'conversations'>,\n queryClient: QueryClient,\n conversationId: string,\n documentId: string | null\n): Promise<void> {\n const before = threadBinding(queryClient, conversationId)\n if (before.documentId === documentId && !before.unavailable) return\n cacheThreadBinding(queryClient, conversationId, { documentId, unavailable: false })\n try {\n const saved: ConversationResponse = await arbi.conversations.update(conversationId, {\n bound_document_ext_id: documentId,\n })\n patchConversation(queryClient, conversationId, saved)\n cacheThreadBinding(queryClient, conversationId, bindingOfRow(saved))\n } catch (error) {\n cacheThreadBinding(queryClient, conversationId, before)\n throw error\n }\n}\n\n/**\n * A new chat got its server id: the document its first turn was sent with is now the\n * conversation's (the server bound it with that turn). Call it once the conversation's row is in\n * the list; `documentId` defaults to the session's new-chat binding.\n */\nexport function adoptNewChatDocument(\n session: NewChatSession,\n queryClient: QueryClient,\n conversationId: string,\n documentId: string | null = session.getState().newChatDocumentId\n): void {\n if (!documentId) return\n cacheThreadBinding(queryClient, conversationId, { documentId, unavailable: false })\n if (session.getState().newChatDocumentId === documentId) session.setNewChatDocumentId(null)\n}\n\n/**\n * Move the bindings this browser kept locally (before the server held them) to the server, for\n * the conversations of a workspace's list, then forget them here. A conversation the server\n * already binds keeps its server binding. Runs once per list it is given; the key is removed when\n * the last kept binding is moved.\n */\nexport async function migrateLegacyThreadDocuments(\n arbi: Pick<Arbi, 'conversations'>,\n queryClient: QueryClient,\n conversations: readonly ConversationResponse[]\n): Promise<void> {\n const legacy = readLegacyThreadDocuments()\n // Only rows from a server that holds bindings (they carry the field): never lose a kept one.\n const listed = conversations.filter(\n (c) => c.external_id in legacy && 'bound_document_unavailable' in c\n )\n if (listed.length === 0) return\n await Promise.all(\n listed.map(async (row) => {\n const server = bindingOfRow(row)\n if (server.documentId || server.unavailable) return\n try {\n await bindThreadDocument(arbi, queryClient, row.external_id, legacy[row.external_id])\n } catch {\n // The document is gone or not readable any more: nothing to keep.\n }\n })\n )\n forgetLegacyThreadDocuments(listed.map((c) => c.external_id))\n}\n","/**\n * The message a new turn replies to, read from the conversation's cached threads (the rule itself\n * is `findReplyTarget` in `@arbidocs/sdk`).\n */\n\nimport type { QueryClient } from '@tanstack/react-query'\nimport { findReplyTarget, type ThreadsResponse } from '@arbidocs/sdk/browser'\nimport { getThreadsQueryKey } from './conversation-cache'\n\n/**\n * {@link findReplyTarget} over the conversation's cached threads. Leaves `parentId` as it is when\n * the threads are not loaded: there is nothing to check it against.\n */\nexport function resolveReplyTarget(\n queryClient: QueryClient,\n conversationId: string,\n parentId: string | null\n): string | null {\n if (!parentId) return null\n const data = queryClient.getQueryData<ThreadsResponse>(getThreadsQueryKey(conversationId))\n if (!data?.threads?.length) return parentId\n return findReplyTarget(data.threads, parentId)\n}\n","/**\n * The workspace each conversation is in, so a turn names its conversation's workspace rather than\n * whichever one the surface (or the server session) is on when it is sent. A docked or scoped chat\n * keeps its open conversation across a workspace switch, and a deferred follow-up is sent after a\n * long turn: both must keep writing in the conversation's own workspace.\n *\n * Kept per query client (a sign-out clears it with the cache), from, in order of trust:\n * 1. the server: the workspace a turn of the conversation was accepted in;\n * 2. the cached conversation lists, each of which is one workspace's;\n * 3. the workspace its session was in when the conversation was opened there.\n * The server stores a follow-up in its thread's workspace whatever is named, refusing a different\n * one with 409 `workspace_mismatch` (the SDK then sends it once more there), so a stale guess can\n * cost a round trip but can never write under another workspace's key.\n */\n\nimport type { QueryClient } from '@tanstack/react-query'\nimport { arbiQueryKeys } from '../query-keys'\n\ninterface Bindings {\n confirmed: Map<string, string>\n observed: Map<string, string>\n}\n\nconst byClient = new WeakMap<QueryClient, Bindings>()\n\nfunction bindingsOf(queryClient: QueryClient): Bindings {\n let bindings = byClient.get(queryClient)\n if (!bindings) {\n bindings = { confirmed: new Map(), observed: new Map() }\n byClient.set(queryClient, bindings)\n }\n return bindings\n}\n\n/** The server accepted a turn of `conversationId` in `workspaceId`. */\nexport function confirmConversationWorkspace(\n queryClient: QueryClient,\n conversationId: string,\n workspaceId: string\n): void {\n if (conversationId === 'new') return\n bindingsOf(queryClient).confirmed.set(conversationId, workspaceId)\n}\n\n/** `conversationId` was opened while its session was in `workspaceId` (kept only if unknown). */\nexport function observeConversationWorkspace(\n queryClient: QueryClient,\n conversationId: string,\n workspaceId: string\n): void {\n const { observed } = bindingsOf(queryClient)\n if (conversationId !== 'new' && !observed.has(conversationId))\n observed.set(conversationId, workspaceId)\n}\n\n/** The workspace whose cached conversation list holds `conversationId`, if one does. */\nfunction listedWorkspaceOf(queryClient: QueryClient, conversationId: string): string | null {\n for (const [key, data] of queryClient.getQueriesData<Array<{ external_id?: string }>>({\n queryKey: arbiQueryKeys.allConversations(),\n })) {\n const workspaceId = key[2]\n if (key.length !== 3 || typeof workspaceId !== 'string' || !Array.isArray(data)) continue\n if (data.some((row) => row?.external_id === conversationId)) return workspaceId\n }\n return null\n}\n\n/** The workspace `conversationId` is in, as far as this client knows (null: unknown). */\nexport function conversationWorkspaceOf(\n queryClient: QueryClient,\n conversationId: string | null | undefined\n): string | null {\n if (!conversationId || conversationId === 'new') return null\n const { confirmed, observed } = bindingsOf(queryClient)\n return (\n confirmed.get(conversationId) ??\n listedWorkspaceOf(queryClient, conversationId) ??\n observed.get(conversationId) ??\n null\n )\n}\n\ninterface ObservableSession {\n getState(): { conversationId: string | null; workspaceId: string | null }\n subscribe(listener: () => void): () => void\n}\n\nconst watchedSessions = new WeakMap<ObservableSession, WeakSet<QueryClient>>()\n\n/**\n * Record, once per session store, the workspace each conversation is opened in: the session's\n * workspace at that moment. A later switch of the session's workspace does not move it.\n */\nexport function watchConversationWorkspaces(\n queryClient: QueryClient,\n session: ObservableSession\n): void {\n const clients = watchedSessions.get(session) ?? new WeakSet<QueryClient>()\n if (clients.has(queryClient)) return\n clients.add(queryClient)\n watchedSessions.set(session, clients)\n let last: string | null = null\n const record = () => {\n const { conversationId, workspaceId } = session.getState()\n if (conversationId === last) return\n last = conversationId\n if (conversationId && workspaceId)\n observeConversationWorkspace(queryClient, conversationId, workspaceId)\n }\n record()\n session.subscribe(record)\n}\n","/**\n * Every read of documents that lands in the caches (a workspace's list, one document: a viewer\n * re-reading it while it processes, a refresh after an event), as rows, so live processing can be\n * settled from whichever read comes first (`settledByRows`): a document whose final event was lost\n * stops showing as in progress as soon as any read of it says it finished after that.\n */\n\nimport type { QueryClient, QueryKey } from '@tanstack/react-query'\nimport { arbiQueryKeys } from '../hooks'\nimport type { WorkspaceDocument } from './documents-cache'\n\nfunction startsWith(key: QueryKey, prefix: QueryKey): boolean {\n return prefix.every((part, i) => key[i] === part)\n}\n\n/** Call `onRows` with the documents each successful read or write of a documents cache holds. */\nexport function subscribeDocumentReads(\n qc: QueryClient,\n onRows: (rows: WorkspaceDocument[]) => void\n): () => void {\n const lists = arbiQueryKeys.allDocuments()\n const one = arbiQueryKeys.document('').slice(0, -1)\n return qc.getQueryCache().subscribe((event) => {\n if (event.type !== 'updated' || event.action.type !== 'success') return\n const key = event.query.queryKey\n const data: unknown = event.query.state.data\n if (key.length !== lists.length + 1) return\n if (startsWith(key, lists) && Array.isArray(data)) onRows(data as WorkspaceDocument[])\n else if (startsWith(key, one) && data && typeof data === 'object' && !Array.isArray(data))\n onRows([data as WorkspaceDocument])\n })\n}\n","/**\n * A workspace's documents in processing, live: what every site's file views show while uploads\n * and re-processing run.\n *\n * - `applyTaskEvent` (the provider runs it on each taken `task_update`): an upload appears as a\n * row the moment it is queued (a light placeholder, so the table and the gallery show it with\n * its live progress), and a finished document replaces its row with the one read afresh.\n * - `useWorkspaceProcessing(workspaceId)`: the workspace's processing rows and their counts\n * (a snapshot every half second, so a batch upload does not re-render on every event), kept\n * honest: stale or orphaned rows are dropped when the workspace opens, rows a document read says\n * finished are settled, and the in-flight ones are re-checked when the connection comes back.\n */\n\nimport { useEffect, useMemo, useState } from 'react'\nimport { useQueryClient, type QueryClient } from '@tanstack/react-query'\nimport type { Arbi } from '@arbidocs/sdk/browser'\nimport type { WsTaskUpdateMessage } from '@arbidocs/client'\nimport { useArbi } from '../useArbi'\nimport { useArbiWsStore, type LiveTask } from '../websocket/store'\nimport { getCachedDocuments, patchDocuments } from './documents-cache'\nimport { refreshDocuments } from './documents-data'\nimport { subscribeDocumentReads } from './processing-settle'\nimport { FINISHED_DOCUMENT_STATUSES, IN_FLIGHT_DOCUMENT_STATUSES } from './processing-order'\nimport type { WorkspaceDocument } from './documents-cache'\n\n/** A row in flight longer than this is a zombie (its completion was lost): no real run takes it. */\nconst STALE_TASK_MS = 6 * 60 * 60 * 1000\n/** A row whose document is missing from a read list is an orphan only after this long. */\nconst ORPHAN_TASK_MS = 15 * 60 * 1000\n/** How often the workspace's rows are re-read into views while processing runs. */\nconst SNAPSHOT_MS = 500\n\n/** Apply one taken `task_update` to the documents list (`me`: who uploads, i.e. this user). */\nexport function applyTaskEvent(\n queryClient: QueryClient,\n arbi: Arbi,\n message: WsTaskUpdateMessage & { folder?: string | null },\n me: string | null | undefined\n): void {\n const workspaceId = message.workspace_ext_id\n if (!workspaceId) return\n if (FINISHED_DOCUMENT_STATUSES.has(message.status)) {\n // The finished document replaces its placeholder row and its own entry.\n void refreshDocuments(queryClient, arbi, [message.doc_ext_id])\n return\n }\n // Only once the list has been read: a placeholder must not stand in for the first read.\n const cached = getCachedDocuments(queryClient, workspaceId)\n if (!cached || cached.some((d) => d.external_id === message.doc_ext_id)) return\n const now = new Date().toISOString()\n // The fields the read document will carry, so the row passes the list's filters meanwhile.\n const placeholder = {\n external_id: message.doc_ext_id,\n workspace_ext_id: workspaceId,\n file_name: message.file_name ?? 'Uploading…',\n status: message.status,\n folder: message.folder ?? null,\n wp_type: 'source',\n shared: false,\n created_by_ext_id: me ?? undefined,\n doc_metadata: {},\n doctags: [],\n created_at: now,\n updated_at: now,\n } as unknown as WorkspaceDocument\n patchDocuments(\n queryClient,\n (old) => (old.some((d) => d.external_id === message.doc_ext_id) ? old : [...old, placeholder]),\n workspaceId\n )\n}\n\n/** The workspace's processing rows (in the order of their document ids) and their counts. */\nexport interface WorkspaceProcessing {\n tasks: Record<string, LiveTask>\n allTasks: LiveTask[]\n processingCount: number\n completedCount: number\n failedCount: number\n skippedCount: number\n clearTask: (docId: string) => void\n clearFinishedTasks: () => void\n}\n\nexport function useWorkspaceProcessing(workspaceId: string | undefined): WorkspaceProcessing {\n const queryClient = useQueryClient()\n const arbi = useArbi()\n const [snapshot, setSnapshot] = useState(() => useArbiWsStore.getState().tasks)\n\n useEffect(() => {\n let timer: ReturnType<typeof setTimeout> | null = null\n const unsubscribe = useArbiWsStore.subscribe((state, previous) => {\n if (state.tasks === previous.tasks || timer) return\n timer = setTimeout(() => {\n timer = null\n setSnapshot(useArbiWsStore.getState().tasks)\n }, SNAPSHOT_MS)\n })\n return () => {\n unsubscribe()\n if (timer) clearTimeout(timer)\n }\n }, [])\n\n // When the workspace opens: settle what its list says finished, and drop zombie rows (in flight\n // for hours) and orphans (their document is gone from the read list).\n useEffect(() => {\n if (!workspaceId) return\n const store = useArbiWsStore.getState()\n const documents = getCachedDocuments(queryClient, workspaceId) ?? []\n store.settleTasks(documents)\n const listed = new Set(documents.map((d) => d.external_id))\n const now = Date.now()\n for (const task of Object.values(useArbiWsStore.getState().tasks)) {\n if (task.workspace_ext_id !== workspaceId || !IN_FLIGHT_DOCUMENT_STATUSES.has(task.status))\n continue\n const since = task.startTime ?? task.endTime\n const age = since == null ? null : now - since\n const stale = age != null && age > STALE_TASK_MS\n const orphan =\n documents.length > 0 && !listed.has(task.doc_ext_id) && age != null && age > ORPHAN_TASK_MS\n if (stale || orphan) store.clearTask(task.doc_ext_id)\n }\n }, [workspaceId, queryClient])\n\n // Afterwards: every documents read settles the rows it shows finished, and a connection that\n // comes back re-checks the in-flight ones (the events it missed are gone for good).\n useEffect(() => {\n if (!workspaceId) return\n const unsubscribeReads = subscribeDocumentReads(queryClient, (rows) =>\n useArbiWsStore.getState().settleTasks(rows)\n )\n const recheck = async () => {\n const ids = Object.values(useArbiWsStore.getState().tasks)\n .filter(\n (t) => t.workspace_ext_id === workspaceId && IN_FLIGHT_DOCUMENT_STATUSES.has(t.status)\n )\n .map((t) => t.doc_ext_id)\n if (ids.length) await refreshDocuments(queryClient, arbi, ids)\n }\n let wasConnected = useArbiWsStore.getState().status === 'connected'\n const unsubscribeStatus = useArbiWsStore.subscribe((state) => {\n const connected = state.status === 'connected'\n if (connected && !wasConnected) void recheck()\n wasConnected = connected\n })\n return () => {\n unsubscribeReads()\n unsubscribeStatus()\n }\n }, [workspaceId, queryClient, arbi])\n\n return useMemo(() => {\n const allTasks = workspaceId\n ? Object.values(snapshot)\n .filter((t) => t.workspace_ext_id === workspaceId)\n .sort((a, b) => a.doc_ext_id.localeCompare(b.doc_ext_id))\n : []\n const count = (statuses: ReadonlySet<string> | string[]) =>\n allTasks.filter((t) =>\n Array.isArray(statuses) ? statuses.includes(t.status) : statuses.has(t.status)\n ).length\n const { clearTask, clearFinishedTasks } = useArbiWsStore.getState()\n return {\n tasks: Object.fromEntries(allTasks.map((t) => [t.doc_ext_id, t])),\n allTasks,\n processingCount: count(IN_FLIGHT_DOCUMENT_STATUSES),\n completedCount: count(['completed', 'low-content']),\n failedCount: count(['failed']),\n skippedCount: count(['skipped']),\n clearTask,\n clearFinishedTasks,\n }\n }, [workspaceId, snapshot])\n}\n","/**\n * Writing documents: field edits, deletion, uploads (files and URLs), and their tags (applying,\n * removing, re-noting, filling them with AI). Every write patches the caches that show its\n * documents in place (the workspace list, each document's own entry, the tag counts) instead of\n * re-reading a list that can be 100k documents long.\n *\n * Offline: field edits and tag applications / removals / notes pause and are sent on reconnect.\n * While queued, a field edit already shows (it is applied to the cache, and undone if the send\n * fails or the change is cancelled: {@link rollbackOptimisticDocumentEdit}), and awaiting one\n * resolves at once rather than when the connection is back. A host that persists its query cache\n * keeps them across a reload by registering `registerArbiMutationDefaults` (`offline.ts`).\n */\n\nimport { useCallback } from 'react'\nimport { onlineManager, useMutation, useQueryClient, type QueryClient } from '@tanstack/react-query'\nimport type { ArbiClient, components } from '@arbidocs/client'\nimport {\n documents as documentOps,\n doctags as doctagOps,\n type Arbi,\n type UploadDocumentsOptions,\n type UploadResult,\n} from '@arbidocs/sdk/browser'\nimport { useArbi } from '../useArbi'\nimport { arbiMutationKeys, arbiQueryKeys } from '../hooks'\nimport {\n forgetDocuments,\n getCachedDocuments,\n patchCachedDocument,\n patchDocuments,\n setCachedDocument,\n type WorkspaceDocument,\n} from './documents-cache'\nimport { adjustTagCounts, refreshDocuments } from './documents-data'\nimport { useArbiWsStore, type LiveTask } from '../websocket/store'\nimport {\n QUEUED_WRITE_RETRY,\n inWorkspace,\n isWorkspaceUnavailable,\n primeOnArbi,\n primeOnClient,\n useCapturingWorkspace,\n type QueuedWriteWorkspace,\n} from '../queued-writes'\n\ntype DocUpdate = components['schemas']['DocUpdateRequest']\ntype DocTag = components['schemas']['DocTagResponse']\ntype CitationSources = components['schemas']['CitationSources']\n\n/** A field edit: the documents' ids with the fields that change (folder, sharing, metadata, …). */\nexport interface UpdateDocumentsInput extends QueuedWriteWorkspace {\n documents: DocUpdate[]\n}\n\n/** Applying a tag to documents (with a note, e.g. a field's value, and the passages it cites). */\nexport interface AssignDocTagsInput extends QueuedWriteWorkspace {\n tagId: string\n docIds: string[]\n note?: string | null\n citations?: CitationSources | null\n}\n\n/** Removing a tag from documents. */\nexport interface RemoveDocTagsInput extends QueuedWriteWorkspace {\n tagId: string\n docIds: string[]\n}\n\n/** Changing the note (or its cited passages) of a tag on one document. */\nexport interface UpdateDocTagInput extends QueuedWriteWorkspace {\n tagId: string\n docId: string\n note?: string | null\n citations?: CitationSources | null\n}\n\n/**\n * Snapshot taken when a queued field edit was applied to the cache; restoring it undoes the edit.\n * It is the mutation's context, so a host's list of pending changes can undo one.\n */\nexport interface OptimisticDocumentEdit {\n optimistic: true\n previous: WorkspaceDocument[]\n previousOwn: Array<[string, WorkspaceDocument | null | undefined]>\n}\n\n/**\n * Show a queued field edit in the caches at once (offline only: online, the server's answer is the\n * one source). A second edit of the same document layers on the first, so undoing the later one\n * restores the earlier one.\n */\nexport function applyOptimisticDocumentEdit(\n qc: QueryClient,\n updates: DocUpdate[]\n): OptimisticDocumentEdit {\n const byId = new Map(updates.map((update) => [update.external_id, update]))\n const previous: WorkspaceDocument[] = []\n patchDocuments(qc, (old) => {\n let changed = false\n const next = old.map((doc) => {\n const update = byId.get(doc.external_id)\n if (!update) return doc\n changed = true\n previous.push(doc)\n return { ...doc, ...update } as WorkspaceDocument\n })\n return changed ? next : old\n })\n const previousOwn = updates.map((update): [string, WorkspaceDocument | null | undefined] => {\n const own = qc.getQueryData<WorkspaceDocument | null>(\n arbiQueryKeys.document(update.external_id)\n )\n if (own) setCachedDocument(qc, { ...own, ...update } as WorkspaceDocument)\n return [update.external_id, own]\n })\n return { optimistic: true, previous, previousOwn }\n}\n\n/** Undo {@link applyOptimisticDocumentEdit} from its snapshot (anything else: nothing to undo). */\nexport function rollbackOptimisticDocumentEdit(qc: QueryClient, context: unknown): void {\n const edit = context as OptimisticDocumentEdit | undefined\n if (!edit?.optimistic) return\n if (edit.previous.length) {\n const restore = new Map(edit.previous.map((doc) => [doc.external_id, doc]))\n patchDocuments(qc, (old) =>\n old.some((doc) => restore.has(doc.external_id))\n ? old.map((doc) => restore.get(doc.external_id) ?? doc)\n : old\n )\n }\n for (const [id, own] of edit.previousOwn) qc.setQueryData(arbiQueryKeys.document(id), own)\n}\n\n/** The server's documents after an edit replace the cached ones. */\nfunction settleUpdatedDocuments(qc: QueryClient, updated: WorkspaceDocument[]): void {\n if (!updated.length) return\n const byId = new Map(updated.map((doc) => [doc.external_id, doc]))\n patchDocuments(qc, (old) =>\n old.some((doc) => byId.has(doc.external_id))\n ? old.map((doc) => byId.get(doc.external_id) ?? doc)\n : old\n )\n for (const doc of updated) setCachedDocument(qc, doc)\n}\n\n/** Apply `reducer` to the given documents wherever they are cached (lists and own entries). */\nfunction patchEachDocument(\n qc: QueryClient,\n docIds: Iterable<string>,\n reducer: (doc: WorkspaceDocument) => WorkspaceDocument\n): void {\n const ids = new Set(docIds)\n patchDocuments(qc, (old) =>\n old.some((doc) => ids.has(doc.external_id))\n ? old.map((doc) => (ids.has(doc.external_id) ? reducer(doc) : doc))\n : old\n )\n for (const id of ids) patchCachedDocument(qc, id, reducer)\n}\n\n/** The workspace a cached document belongs to. */\nfunction workspaceOf(qc: QueryClient, docId: string): string | undefined {\n for (const [, docs] of qc.getQueriesData<WorkspaceDocument[]>({\n queryKey: arbiQueryKeys.allDocuments(),\n })) {\n const doc = Array.isArray(docs) ? docs.find((d) => d.external_id === docId) : undefined\n if (doc) return doc.workspace_ext_id\n }\n return qc.getQueryData<WorkspaceDocument | null>(arbiQueryKeys.document(docId))?.workspace_ext_id\n}\n\n/** Tags applied: each document gains them, each tag's document count rises. */\nfunction settleAssignedDocTags(qc: QueryClient, created: DocTag[]): void {\n const byDoc = new Map<string, DocTag[]>()\n for (const doctag of created)\n byDoc.set(doctag.doc_ext_id, [...(byDoc.get(doctag.doc_ext_id) ?? []), doctag])\n const workspaces = new Map<string, Map<string, number>>()\n for (const doctag of created) {\n const workspaceId = workspaceOf(qc, doctag.doc_ext_id)\n if (!workspaceId) continue\n const delta = workspaces.get(workspaceId) ?? new Map<string, number>()\n delta.set(doctag.tag_ext_id, (delta.get(doctag.tag_ext_id) ?? 0) + 1)\n workspaces.set(workspaceId, delta)\n }\n patchEachDocument(qc, byDoc.keys(), (doc) => ({\n ...doc,\n doctags: [...(doc.doctags ?? []), ...(byDoc.get(doc.external_id) ?? [])],\n }))\n for (const [workspaceId, delta] of workspaces) adjustTagCounts(qc, workspaceId, delta)\n}\n\n/** A tag removed: the documents lose it, its count drops by the documents that had it. */\nfunction settleRemovedDocTags(qc: QueryClient, { tagId, docIds }: RemoveDocTagsInput): void {\n const ids = new Set(docIds)\n const removedByWorkspace = new Map<string, number>()\n for (const [, docs] of qc.getQueriesData<WorkspaceDocument[]>({\n queryKey: arbiQueryKeys.allDocuments(),\n })) {\n for (const doc of Array.isArray(docs) ? docs : []) {\n if (!ids.has(doc.external_id)) continue\n if (!doc.doctags?.some((dt) => dt.tag_ext_id === tagId)) continue\n removedByWorkspace.set(\n doc.workspace_ext_id,\n (removedByWorkspace.get(doc.workspace_ext_id) ?? 0) + 1\n )\n }\n }\n patchEachDocument(qc, ids, (doc) => ({\n ...doc,\n doctags: (doc.doctags ?? []).filter((dt) => dt.tag_ext_id !== tagId),\n }))\n for (const [workspaceId, removed] of removedByWorkspace)\n adjustTagCounts(qc, workspaceId, new Map([[tagId, -removed]]))\n}\n\n/** A tag's note changed on a document: the document's copy of it is replaced. */\nfunction settleUpdatedDocTag(qc: QueryClient, updated: DocTag): void {\n patchEachDocument(qc, [updated.doc_ext_id], (doc) => ({\n ...doc,\n doctags: (doc.doctags ?? []).map((dt) => (dt.tag_ext_id === updated.tag_ext_id ? updated : dt)),\n }))\n}\n\n/**\n * Each document write's request on a bare client (a replay after a reload), in the workspace it was\n * made in. The server keys a document or doctag write by the resource's own workspace, so once that\n * workspace is opened for the session the write cannot land in the one open now.\n */\nconst sendUpdateDocuments = (client: ArbiClient, input: UpdateDocumentsInput) =>\n inWorkspace(primeOnClient(client), input.workspaceId, () =>\n documentOps.updateDocuments(client, input.documents)\n ) as Promise<WorkspaceDocument[]>\nconst sendAssignDocTags = (client: ArbiClient, input: AssignDocTagsInput) =>\n inWorkspace(primeOnClient(client), input.workspaceId, () =>\n doctagOps.assignDocTags(client, input.tagId, input.docIds, input.note, input.citations)\n )\nconst sendRemoveDocTags = (client: ArbiClient, input: RemoveDocTagsInput) =>\n inWorkspace(primeOnClient(client), input.workspaceId, () =>\n doctagOps.removeDocTags(client, input.tagId, input.docIds)\n )\nconst sendUpdateDocTag = (client: ArbiClient, input: UpdateDocTagInput) =>\n inWorkspace(primeOnClient(client), input.workspaceId, () =>\n doctagOps.updateDocTag(client, input.tagId, input.docId, {\n note: input.note,\n citations: input.citations,\n })\n )\n\n/**\n * The document writes a host may queue offline and replay after a reload (`offline.ts`): each\n * key's request on a bare client (in the workspace the write was made in), and what its success\n * does to the cache.\n */\nexport const replayableDocumentMutations = [\n {\n mutationKey: arbiMutationKeys.updateDocuments(),\n run: sendUpdateDocuments,\n settle: (qc: QueryClient, updated: WorkspaceDocument[]) => settleUpdatedDocuments(qc, updated),\n },\n {\n mutationKey: arbiMutationKeys.assignDocTags(),\n run: sendAssignDocTags,\n settle: (qc: QueryClient, created: DocTag[]) => settleAssignedDocTags(qc, created),\n },\n {\n mutationKey: arbiMutationKeys.removeDocTags(),\n run: sendRemoveDocTags,\n settle: (qc: QueryClient, _data: unknown, input: RemoveDocTagsInput) =>\n settleRemovedDocTags(qc, input),\n },\n {\n mutationKey: arbiMutationKeys.updateDocTag(),\n run: sendUpdateDocTag,\n settle: (qc: QueryClient, updated: DocTag) => settleUpdatedDocTag(qc, updated),\n },\n] as const\n\n/**\n * The workspace a document write is made in, when its caller named none: the edited documents'\n * own (from the cache: a document can be edited from a view of another workspace), else the\n * current one. Read when the write is made, before it can be queued.\n */\nfunction useDocumentWriteWorkspace<V extends QueuedWriteWorkspace>(\n docIdOf: (variables: V) => string | undefined\n): (variables: V) => V {\n const arbi = useArbi()\n const qc = useQueryClient()\n return (variables: V) => {\n if (variables.workspaceId) return variables\n const docId = docIdOf(variables)\n const workspaceId =\n (docId ? workspaceOf(qc, docId) : undefined) ??\n (arbi.hasWorkspace ? arbi.getWorkspaceId() : undefined)\n return workspaceId ? { ...variables, workspaceId } : variables\n }\n}\n\n/**\n * `mutateAsync` that, while offline, queues the write and resolves at once (with `undefined`), so\n * a caller awaiting it to close a dialog never waits for the connection. For writes whose callers\n * do not need the server's answer.\n */\nfunction resolvingOffline<\n T extends { mutate: (...args: never[]) => unknown; mutateAsync: unknown },\n>(mutation: T): T {\n const mutateAsync = ((variables: never, options: never) => {\n if (!onlineManager.isOnline()) {\n ;(mutation.mutate as (v: never, o: never) => void)(variables, options)\n return Promise.resolve(undefined)\n }\n return (mutation.mutateAsync as (v: never, o: never) => Promise<unknown>)(variables, options)\n }) as T['mutateAsync']\n return { ...mutation, mutateAsync }\n}\n\n/** Reflect a confirmed resource share in every files view, and refresh its document detail. */\nexport function useMarkDocumentShared(): (documentExtId: string) => void {\n const qc = useQueryClient()\n return useCallback(\n (documentExtId: string) => {\n patchDocuments(qc, (old) =>\n old.map((doc) => (doc.external_id === documentExtId ? { ...doc, shared: true } : doc))\n )\n void qc.invalidateQueries({ queryKey: arbiQueryKeys.document(documentExtId) })\n },\n [qc]\n )\n}\n\n/**\n * Edit documents' fields (folder, sharing, title and other metadata, status). The answer replaces\n * the cached documents; offline the edit shows at once and is sent on reconnect.\n */\nexport function useUpdateDocuments() {\n const arbi = useArbi()\n const qc = useQueryClient()\n const capture = useDocumentWriteWorkspace<UpdateDocumentsInput>(\n (input) => input.documents[0]?.external_id\n )\n return resolvingOffline(\n useCapturingWorkspace(\n useMutation({\n mutationKey: arbiMutationKeys.updateDocuments(),\n mutationFn: (input: UpdateDocumentsInput): Promise<WorkspaceDocument[]> =>\n inWorkspace(primeOnArbi(arbi), input.workspaceId, () =>\n arbi.documents.update(input.documents)\n ),\n onMutate: ({ documents }) =>\n onlineManager.isOnline() || !documents.length\n ? undefined\n : applyOptimisticDocumentEdit(qc, documents),\n // Not sent because its workspace can't be opened: the edit stays, listed as not sent.\n onError: (error, _input, context) => {\n if (!isWorkspaceUnavailable(error)) rollbackOptimisticDocumentEdit(qc, context)\n },\n onSuccess: (updated) => settleUpdatedDocuments(qc, updated),\n ...QUEUED_WRITE_RETRY,\n }),\n capture\n )\n )\n}\n\n/** A folder path's segments: the `folder` string split on \"/\", trimmed, empty ones dropped. */\nfunction folderSegments(folder: string | null | undefined): string[] {\n return (folder ?? '')\n .split('/')\n .map((segment) => segment.trim())\n .filter(Boolean)\n}\n\n/**\n * Rename or move a folder: each of `documents` beneath `from` moves under `to`, keeping the\n * structure below it. The batch write does not return an email's attachments, so every cached row\n * beneath `from` moves too. Resolves to how many documents were written.\n */\nexport function useRenameFolder() {\n const qc = useQueryClient()\n const { mutateAsync } = useUpdateDocuments()\n return useCallback(\n async (documents: WorkspaceDocument[], from: string[], to: string[]): Promise<number> => {\n const moved = (folder: string | null | undefined): string | null | undefined => {\n const segments = folderSegments(folder)\n if (from.length === 0 || segments.length < from.length) return undefined\n if (!from.every((segment, i) => segments[i] === segment)) return undefined\n const next = [...to, ...segments.slice(from.length)]\n return next.length > 0 ? next.join('/') : null\n }\n const updates = documents.flatMap((doc) => {\n const folder = moved(doc.folder)\n return folder === undefined ? [] : [{ external_id: doc.external_id, folder }]\n })\n if (updates.length > 0) await mutateAsync({ documents: updates })\n patchDocuments(qc, (rows) => {\n let changed = false\n const next = rows.map((doc) => {\n const folder = moved(doc.folder)\n if (folder === undefined || folder === doc.folder) return doc\n changed = true\n return { ...doc, folder }\n })\n return changed ? next : rows\n })\n return updates.length\n },\n [qc, mutateAsync]\n )\n}\n\n/**\n * Delete documents (each with all its versions; an email with its attachments). They leave every\n * list, what was cached about them is forgotten, and the workspaces' file counts re-read.\n */\nexport function useDeleteDocuments() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationKey: arbiMutationKeys.deleteDocuments(),\n mutationFn: (docIds: string[]) => arbi.documents.delete(docIds),\n onSuccess: (_data, docIds) => {\n const gone = new Set(docIds)\n patchDocuments(qc, (old) =>\n old.some((doc) => gone.has(doc.external_id))\n ? old.filter((doc) => !gone.has(doc.external_id))\n : old\n )\n forgetDocuments(qc, docIds)\n // A deleted document (a failed upload especially) leaves the processing rows too.\n const { clearTask } = useArbiWsStore.getState()\n for (const id of docIds) clearTask(id)\n return qc.invalidateQueries({ queryKey: arbiQueryKeys.workspaces() })\n },\n })\n}\n\n/** Re-read the documents an upload made and the workspaces' file counts. */\nasync function settleUpload(\n qc: QueryClient,\n arbi: Arbi,\n docIds: string[] | undefined\n): Promise<void> {\n if (docIds?.length) await refreshDocuments(qc, arbi, docIds)\n await qc.invalidateQueries({ queryKey: arbiQueryKeys.workspaces() })\n}\n\n/** Files to upload and where they go. */\nexport interface UploadDocumentsInput {\n files: Array<Blob | File>\n options?: UploadDocumentsOptions\n}\n\n/**\n * Upload files (to the open workspace, or `options.workspaceExtId`): resolves with the new\n * documents' ids (and the files the server skipped). The new documents join their list.\n */\nexport function useUploadDocuments() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationKey: arbiMutationKeys.uploadDocuments(),\n mutationFn: ({ files, options }: UploadDocumentsInput): Promise<UploadResult> =>\n arbi.documents.upload(files, options),\n onSuccess: (result) => settleUpload(qc, arbi, result.doc_ext_ids),\n })\n}\n\n/** Web pages or files to fetch into a workspace (default: the open one). */\nexport interface UploadUrlsInput {\n urls: string[]\n shared?: boolean\n configExtId?: string | null\n /** The workspace the documents are made in; named on the request. Default: the open one. */\n workspaceId?: string | null\n}\n\n/** Add documents from URLs to a workspace (default: the open one); they join its list. */\nexport function useUploadUrls() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationKey: arbiMutationKeys.uploadUrls(),\n mutationFn: ({ urls, shared, configExtId, workspaceId }: UploadUrlsInput) =>\n arbi.documents.uploadUrl(urls, {\n workspaceId: workspaceId ?? arbi.getWorkspaceId() ?? undefined,\n shared,\n configExtId,\n }),\n onSuccess: (result) =>\n settleUpload(qc, arbi, (result as { doc_ext_ids?: string[] }).doc_ext_ids),\n })\n}\n\n/** Apply a tag to documents: they show it at once, its count rises. Queued offline. */\nexport function useAssignDocTags() {\n const arbi = useArbi()\n const qc = useQueryClient()\n const capture = useDocumentWriteWorkspace<AssignDocTagsInput>((input) => input.docIds[0])\n return resolvingOffline(\n useCapturingWorkspace(\n useMutation({\n mutationKey: arbiMutationKeys.assignDocTags(),\n mutationFn: ({ workspaceId, tagId, docIds, note, citations }: AssignDocTagsInput) =>\n inWorkspace(primeOnArbi(arbi), workspaceId, () =>\n arbi.doctags.assign(tagId, docIds, note, citations)\n ) as Promise<DocTag[]>,\n onSuccess: (created) => settleAssignedDocTags(qc, created),\n ...QUEUED_WRITE_RETRY,\n }),\n capture\n )\n )\n}\n\n/** Remove a tag from documents: they lose it, its count drops. Queued offline. */\nexport function useRemoveDocTags() {\n const arbi = useArbi()\n const qc = useQueryClient()\n const capture = useDocumentWriteWorkspace<RemoveDocTagsInput>((input) => input.docIds[0])\n return resolvingOffline(\n useCapturingWorkspace(\n useMutation({\n mutationKey: arbiMutationKeys.removeDocTags(),\n mutationFn: ({ workspaceId, tagId, docIds }: RemoveDocTagsInput) =>\n inWorkspace(primeOnArbi(arbi), workspaceId, () => arbi.doctags.remove(tagId, docIds)),\n onSuccess: (_data, input) => settleRemovedDocTags(qc, input),\n ...QUEUED_WRITE_RETRY,\n }),\n capture\n )\n )\n}\n\n/** Change a tag's note (or its cited passages) on a document. Queued offline. */\nexport function useUpdateDocTag() {\n const arbi = useArbi()\n const qc = useQueryClient()\n const capture = useDocumentWriteWorkspace<UpdateDocTagInput>((input) => input.docId)\n return resolvingOffline(\n useCapturingWorkspace(\n useMutation({\n mutationKey: arbiMutationKeys.updateDocTag(),\n mutationFn: ({ workspaceId, tagId, docId, note, citations }: UpdateDocTagInput) =>\n inWorkspace(primeOnArbi(arbi), workspaceId, () =>\n arbi.doctags.update(tagId, docId, { note, citations })\n ) as Promise<DocTag>,\n onSuccess: (updated) => settleUpdatedDocTag(qc, updated),\n ...QUEUED_WRITE_RETRY,\n }),\n capture\n )\n )\n}\n\n/** Tags whose values AI fills on documents. */\nexport interface GenerateDocTagsInput {\n tagIds: string[]\n docIds: string[]\n /** Also where a document already has a value (default: only where it has none). */\n overwrite?: boolean\n}\n\n/**\n * Show documents sent back into processing (AI fields being filled) as queued, as an upload shows,\n * until their real task updates take over. Returns the undo (the write was refused).\n */\nfunction queueProcessing(\n documents: Array<{ docId: string; workspaceId: string; fileName: string; version: number }>\n): () => void {\n const store = useArbiWsStore.getState()\n const previous = documents.map(({ docId }) => [docId, store.tasks[docId]] as const)\n const now = Date.now()\n for (const doc of documents)\n store.putTask({\n doc_ext_id: doc.docId,\n workspace_ext_id: doc.workspaceId,\n file_name: doc.fileName,\n version: doc.version,\n status: 'queued',\n progress: 0,\n startTime: now,\n } as LiveTask)\n return () =>\n useArbiWsStore.setState((state) => {\n const tasks = { ...state.tasks }\n for (const [docId, task] of previous) {\n if (task) tasks[docId] = task\n else delete tasks[docId]\n }\n return { tasks }\n })\n}\n\n/**\n * Fill tags' values on documents with AI. Accepted at once; the work runs in the background and a\n * `batch_complete` (`doctag_generate`) event names the documents when it is done\n * (`refreshDocuments` then brings their values). Meanwhile the documents show as queued for\n * processing (as queued), undone if the request is refused.\n */\nexport function useGenerateDocTags() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationKey: arbiMutationKeys.generateDocTags(),\n mutationFn: ({ tagIds, docIds, overwrite }: GenerateDocTagsInput) =>\n arbi.doctags.generate(tagIds, docIds, { overwrite }),\n onMutate: ({ docIds }) => {\n if (!docIds.length) return undefined\n const workspaceId = arbi.hasWorkspace ? arbi.getWorkspaceId() : ''\n const listed = new Map(\n (getCachedDocuments(qc, workspaceId) ?? []).map((doc) => [doc.external_id, doc])\n )\n // Reprocessing works on each document's current version.\n return {\n undo: queueProcessing(\n docIds.map((docId) => ({\n docId,\n workspaceId,\n fileName: listed.get(docId)?.file_name ?? '',\n version: listed.get(docId)?.current_version ?? 1,\n }))\n ),\n }\n },\n onError: (_error, _input, context) => context?.undo(),\n })\n}\n\n/**\n * Finalise a translation: its current version is saved as a new PDF document, labelled\n * \"Translation\" and linked to the original. Resolves with the new document's id; the new document\n * joins the list with its links, so the original's translations show it at once.\n */\nexport function useFinaliseTranslation() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: (docId: string) => arbi.documents.finaliseTranslation(docId),\n onSuccess: (result) => void refreshDocuments(qc, arbi, [result.document_ext_id]),\n })\n}\n","/**\n * What a host adds to the document hooks and the document kits, opt in (the host configuration's\n * `documents`): the live processing state it keeps (from its own live connection), what happens on\n * its side when documents are deleted or queued for processing, how it uploads (workspace key, zip\n * archives), and what it does with documents beyond the package (its workflows, chat, mail, offline\n * copies, viewer). Without it the hooks work on their own, and the kits offer less, never something\n * that does nothing.\n */\n\nimport type { components } from '@arbidocs/client'\nimport type { ZipExtractor } from './upload-files'\nimport type { WorkspaceDocument } from './documents-cache'\nimport type { ReactNode } from 'react'\nimport { useArbiWsStore } from '../websocket/store'\nimport { useArbiHost } from '../host/config'\n\n/** Something the host can start on documents or a folder (a workflow, a skill). */\nexport interface DocumentStartItem {\n id: string\n title: string\n run: () => void\n}\n\n/** What the host does with documents beyond the package. Each absent one is not offered. */\nexport interface DocumentHostActions {\n /** What can be started on one file. */\n startItemsForFile?: (document: WorkspaceDocument) => DocumentStartItem[]\n /** What can be started on everything in a folder. */\n startItemsForFolder?: (folderPath: string) => DocumentStartItem[]\n /** Start a chat about one document. */\n openDocumentChat?: (docId: string) => void\n /** Start a chat about several documents. */\n openDocumentsChat?: (docIds: string[]) => void\n /**\n * Hand a document to the host's mail composer as an attachment (offered while mail is on): its\n * current version, or an earlier one (`version`, 1-based).\n */\n emailDocument?: (\n document: WorkspaceDocument,\n options?: { version?: number | null }\n ) => Promise<void>\n /** Show how to raise the plan's limits (an upload was refused for them). */\n openUpgrade?: () => void\n /** Show the AI budget a document's processing ran into, and what can be done. */\n openQuota?: (quota: { spend: number; budget: number; projectExtId: string | null }) => void\n /** Open a person (yourself: your settings; someone else: a direct message). */\n openUser?: (userId: string) => void\n /** Open a document beside another, to compare them. */\n compareDocuments?: (docId: string, otherDocId: string) => void\n /** Open the fields manager (labels or AI fields), on its form for a new one with `create`. */\n openFieldsManager?: (kind?: 'label' | 'annotation', options?: { create?: boolean }) => void\n}\n\n/** A person as the document kits show them (who made a document, a field, a value). */\nexport type DocumentPerson = components['schemas']['UserResponse']\n\n/** A document's live processing, as the host follows it (a `task_update` and what it adds). */\nexport interface ProcessingTask {\n doc_ext_id: string\n status: string\n progress?: number | null\n workspace_ext_id?: string | null\n file_name?: string | null\n failed_stage?: string | null\n /** The event's order (`task_update.seq`; see `processing-order`). None on one set here. */\n seq?: number | null\n}\n\nexport interface DocumentsSupport {\n /**\n * The workspace's raw key, for the direct upload (encrypted here, sent straight to storage) that\n * the user's settings can turn on. Throws when the key is not held here (a public workspace, a\n * temporary grant): the upload then goes through the server. Absent: always through the server.\n */\n resolveWorkspaceKey?: (workspaceId: string) => Promise<Uint8Array>\n /** Opens a zip archive into its files (e.g. off the main thread). Default: on the main thread. */\n extractZip?: ZipExtractor\n /** The host's actions on documents, as a hook (a kit reads it once per view). */\n useHostActions?: () => DocumentHostActions\n /**\n * Called once documents are kept on this device (`useKeepDocumentsOffline`), while still online:\n * e.g. to load the viewer's code so a pinned document opens offline too.\n */\n onKeptOffline?: () => void | Promise<void>\n /** The document open in the host's viewer while it is open (null when closed), as a hook. */\n useOpenViewerDocumentId?: () => string | null\n /**\n * How the host shows a person (its presence, its card): by a document, a field, a thread's\n * entry or a message. `tooltip`: whether hovering shows their card; `variant`: their face alone\n * (`icon`, small, the default) or their face and name (`pill`). Absent: the kits' own avatar.\n */\n renderUser?: (\n user: DocumentPerson,\n options: { tooltip: boolean; variant?: 'icon' | 'pill' }\n ) => ReactNode\n}\n\nconst NO_SUPPORT: DocumentsSupport = {}\n\n/** The host's document support (the host configuration's `documents`; empty without one). */\nexport function useDocumentsSupport(): DocumentsSupport {\n return useArbiHost().documents ?? NO_SUPPORT\n}\n\n/** Every document's live processing (the shared WebSocket store's). */\nexport function useProcessingTasks(): Readonly<Record<string, ProcessingTask>> {\n return useArbiWsStore((state) => state.tasks)\n}\n\n/** One document's live processing: re-renders only when that document's changes. */\nexport function useProcessingTask(docId: string): ProcessingTask | undefined {\n return useArbiWsStore((state) => state.tasks[docId])\n}\n\nconst NO_ACTIONS: DocumentHostActions = {}\n\n/** The host's actions on documents (none without host support). */\nexport function useDocumentHostActions(): DocumentHostActions {\n const { useHostActions } = useDocumentsSupport()\n return useHostActions?.() ?? NO_ACTIONS\n}\n\n/** The document open in the host's viewer, while it is open (none without host support). */\nexport function useOpenViewerDocumentId(): string | null {\n const { useOpenViewerDocumentId: useHostViewing } = useDocumentsSupport()\n return useHostViewing?.() ?? null\n}\n","/**\n * Document download building blocks shared by the documents ZIP (`useDownloadDocuments`) and a\n * workspace export archive: name a file and the archive, and build the metadata rows of\n * `index.csv`. Fetching and saving are the document tools' `fetchDocumentFile` and `downloadBlob`.\n */\n\nimport type { WorkspaceDocument as Doc } from './documents-cache'\nimport { getDocumentDate } from './document-fields'\nimport { getDocumentTitle } from '../entities/DocumentEntity'\n\n/** The ZIP entry name for a document when the server did not name it. */\nexport function fallbackFileName(doc: Doc): string {\n if (doc.file_name) return doc.file_name\n const title = getDocumentTitle(doc, `document-${doc.external_id}`)\n const extension = doc.file_type || 'pdf'\n const ext = extension.startsWith('.') ? extension : `.${extension}`\n return title.toLowerCase().endsWith(ext.toLowerCase()) ? title : `${title}${ext}`\n}\n\nconst COLUMN_MAPPING: Record<string, { header: string; getValue: (d: Doc) => string | number }> = {\n file_name: {\n header: 'File Name',\n getValue: (d) => d.file_name || getDocumentTitle(d, `document-${d.external_id}.pdf`),\n },\n title: { header: 'Title', getValue: (d) => getDocumentTitle(d) },\n n_pages: { header: 'Pages', getValue: (d) => d.n_pages || '' },\n doc_date: { header: 'Document Date', getValue: (d) => getDocumentDate(d) || '' },\n doc_id: { header: 'Document ID', getValue: (d) => d.external_id },\n status: { header: 'Status', getValue: (d) => d.status || '' },\n uploaded: { header: 'Upload Date', getValue: (d) => d.created_at || '' },\n updated_at: { header: 'Last Modified', getValue: (d) => d.updated_at || '' },\n file_type: { header: 'File Type', getValue: (d) => d.file_type || '' },\n file_size: { header: 'File Size', getValue: (d) => d.file_size || '' },\n shared: { header: 'Shared', getValue: (d) => (d.shared ? 'Yes' : 'No') },\n}\n\n/**\n * One `index.csv` row per document for the chosen columns (`undefined` = every\n * standard column). A `tag-…` column holds that tag's value, or \"Yes\" for a\n * label without one.\n */\nexport function buildDocumentMetadataRows(\n documents: Doc[],\n selectedColumns?: string[]\n): Record<string, string | number>[] {\n const columns = selectedColumns || Object.keys(COLUMN_MAPPING)\n return documents.map((doc) => {\n const row: Record<string, string | number> = {}\n for (const colId of columns) {\n const standard = COLUMN_MAPPING[colId]\n if (standard) {\n row[standard.header] = standard.getValue(doc)\n } else if (colId.startsWith('tag-')) {\n // Column ids are tag ext ids; older callers passed them without the prefix.\n const bare = colId.replace(/^tag-/, '')\n const doctag = doc.doctags?.find((dt) => dt.tag_ext_id === colId || dt.tag_ext_id === bare)\n if (doctag) row[colId] = doctag.note || 'Yes'\n }\n }\n return row\n })\n}\n\n/** `2026-10-15_My_Workspace_<suffix>.zip` */\nexport function archiveName(workspaceName: string | undefined, suffix: string): string {\n const date = new Date().toISOString().split('T')[0]\n const sanitizedName = (workspaceName || 'workspace').replace(/[^a-z0-9-_]/gi, '_')\n return `${date}_${sanitizedName}_${suffix}.zip`\n}\n","/**\n * Downloading documents: one file as stored, or several as a ZIP (the files, plus an `index.csv`\n * of their metadata unless asked for files only). Used by the explorer (a file, a folder) and the\n * documents table. Progress and outcome are told through `notify`.\n */\n\nimport { useCallback, useState } from 'react'\nimport { useArbi } from '../useArbi'\nimport { notify } from '../notifications/notify-store'\nimport { downloadBlob } from '../document-tools/environment'\nimport { fetchDocumentFile } from '../document-tools/document-pdf'\nimport { getDocumentTitle } from '../entities/DocumentEntity'\nimport type { WorkspaceDocument } from './documents-cache'\nimport { archiveName, buildDocumentMetadataRows, fallbackFileName } from './document-download'\n\nexport interface UseDownloadDocumentsOptions {\n /** Names the ZIP. */\n workspaceName?: string\n}\n\nexport function useDownloadDocuments({ workspaceName }: UseDownloadDocumentsOptions = {}) {\n const arbi = useArbi()\n const [isDownloading, setIsDownloading] = useState(false)\n\n /** The stored file of a document and the name to save it under (the server's, else ours). */\n const fetchNamedFile = useCallback(\n async (doc: WorkspaceDocument): Promise<{ blob: Blob; name: string }> => {\n const blob = await fetchDocumentFile(arbi.getClient().fetch, doc.external_id)\n return { blob, name: blob instanceof File && blob.name ? blob.name : fallbackFileName(doc) }\n },\n [arbi]\n )\n\n // Stable, so a caller can depend on it (the table's columns) without rebuilding every render.\n const downloadDocuments = useCallback(\n // selectedColumns: undefined = all default columns; [] = files only (no index.csv)\n async (documents: WorkspaceDocument[], selectedColumns?: string[]) => {\n const includeMetadataCsv = selectedColumns === undefined || selectedColumns.length > 0\n if (documents.length === 0) {\n notify.error('No documents to download')\n return\n }\n setIsDownloading(true)\n try {\n const JSZip = (await import('jszip')).default\n const zip = new JSZip()\n const downloaded: WorkspaceDocument[] = []\n const failedDocs: string[] = []\n for (const doc of documents) {\n try {\n const file = await fetchNamedFile(doc)\n zip.file(file.name, file.blob)\n downloaded.push(doc)\n } catch (error) {\n console.error(`Failed to download document ${doc.external_id}:`, error)\n failedDocs.push(getDocumentTitle(doc, doc.external_id))\n }\n }\n const successCount = downloaded.length\n if (successCount === 0) {\n notify.error('Failed to download documents')\n return\n }\n if (includeMetadataCsv) {\n const Papa = (await import('papaparse')).default\n zip.file(\n 'index.csv',\n Papa.unparse(buildDocumentMetadataRows(downloaded, selectedColumns))\n )\n }\n const zipFileName = archiveName(workspaceName, `${successCount}_documents`)\n downloadBlob(await zip.generateAsync({ type: 'blob' }), zipFileName)\n // Name the ZIP and, when written, the metadata CSV so the user knows where to find them.\n const documentsLabel = `${successCount} document${successCount !== 1 ? 's' : ''}`\n const contents = includeMetadataCsv\n ? `${documentsLabel} and index.csv in ${zipFileName}`\n : `${documentsLabel} in ${zipFileName}`\n if (failedDocs.length === 0) notify.success(`Successfully downloaded ${contents}`)\n else notify.warning(`Downloaded ${contents}, ${failedDocs.length} failed`)\n } catch (error) {\n console.error('Failed to create zip file:', error)\n notify.error('Failed to download documents. Please try again.')\n } finally {\n setIsDownloading(false)\n }\n },\n [workspaceName, fetchNamedFile]\n )\n\n // A single file (a card's or a row's Download) is saved as-is, not wrapped in a ZIP.\n const downloadDocument = useCallback(\n async (doc: WorkspaceDocument) => {\n setIsDownloading(true)\n try {\n const file = await fetchNamedFile(doc)\n downloadBlob(file.blob, file.name)\n notify.success(`Successfully downloaded ${file.name}`)\n } catch (error) {\n console.error('Failed to download document', error)\n notify.error('Failed to download document. Please try again.')\n } finally {\n setIsDownloading(false)\n }\n },\n [fetchNamedFile]\n )\n\n return { downloadDocuments, downloadDocument, isDownloading }\n}\n","/**\n * Windowed thumbnail loader for a gallery of documents.\n *\n * - The caller passes only the **visible** document ids (a virtualised window plus overscan), not\n * the whole folder. They are fetched in batches — never one request per document.\n * - Results accumulate in a map that survives scrolling, so an id is fetched at most once;\n * scrolling fetches only the newly revealed ids.\n * - A freshly uploaded document's thumbnail exists once its processing finishes. Nothing polls:\n * a visible document reaching a finished status (its live processing, `useProcessingTasks`) is\n * fetched once at that moment. One that finishes with no thumbnail (video, audio, a failed\n * render) is not asked for again — until it is processed again, which is how a missing\n * thumbnail gets generated: going back into processing forgets what was known about it.\n * - Thumbnails come as `data:image/webp` URIs, used directly as `<img src>`.\n */\n\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport { useArbi } from '../useArbi'\nimport { FINISHED_DOCUMENT_STATUSES } from './documents-data'\nimport { useProcessingTasks } from './support'\n\nconst BATCH_SIZE = 200\n\n/** Statuses of a document being (re)processed: what is known about its thumbnail is stale. */\nconst IN_PROGRESS = new Set(['queued', 'parsing', 'encrypting', 'indexing', 'analysing'])\n\n/** A `Map<docId, dataUri>` of thumbnails for the visible documents, growing as they scroll. */\nexport function useDocumentThumbnails(visibleIds: string[]): Map<string, string> {\n const arbi = useArbi()\n const workspaceId = arbi.hasWorkspace ? arbi.getWorkspaceId() : null\n const tasks = useProcessingTasks()\n const tasksRef = useRef(tasks)\n tasksRef.current = tasks\n\n const [thumbnails, setThumbnails] = useState<Map<string, string>>(new Map())\n // Ids already resolved (a thumbnail, or a final \"none\"): never fetched again.\n const resolvedRef = useRef<Set<string>>(new Set())\n // Ids with a request in flight: no duplicate concurrent fetches.\n const inflightRef = useRef<Set<string>>(new Set())\n const idsKey = visibleIds.join(',')\n\n // Another workspace: another set of documents.\n useEffect(() => {\n resolvedRef.current = new Set()\n inflightRef.current = new Set()\n setThumbnails(new Map())\n }, [workspaceId])\n\n const fetchMissing = useCallback(\n async (ids: string[]) => {\n if (!workspaceId) return\n const need = ids.filter((id) => !resolvedRef.current.has(id) && !inflightRef.current.has(id))\n if (need.length === 0) return\n need.forEach((id) => inflightRef.current.add(id))\n try {\n const batches: string[][] = []\n for (let i = 0; i < need.length; i += BATCH_SIZE)\n batches.push(need.slice(i, i + BATCH_SIZE))\n const results = await Promise.all(\n batches.map((batch) => arbi.documents.getThumbnails(batch).catch(() => ({})))\n )\n const map: Record<string, string | null> = Object.assign({}, ...results)\n setThumbnails((prev) => {\n const next = new Map(prev)\n for (const id of need) {\n const uri = map[id]\n if (uri) {\n next.set(id, uri)\n resolvedRef.current.add(id)\n continue\n }\n // Still mid-pipeline: its thumbnail may not exist yet; the finish will ask again.\n if (!IN_PROGRESS.has(tasksRef.current[id]?.status ?? '')) resolvedRef.current.add(id)\n }\n return next\n })\n } finally {\n need.forEach((id) => inflightRef.current.delete(id))\n }\n },\n [arbi, workspaceId]\n )\n\n // The newly revealed window.\n useEffect(() => {\n if (visibleIds.length > 0) void fetchMissing(visibleIds)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [idsKey, fetchMissing])\n\n // A visible document going back into processing forgets its thumbnail; one finishing is fetched.\n useEffect(() => {\n for (const id of visibleIds)\n if (IN_PROGRESS.has(tasks[id]?.status ?? '')) resolvedRef.current.delete(id)\n const ready = visibleIds.filter(\n (id) =>\n !resolvedRef.current.has(id) && FINISHED_DOCUMENT_STATUSES.has(tasks[id]?.status ?? '')\n )\n if (ready.length > 0) void fetchMissing(ready)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [tasks, idsKey, fetchMissing])\n\n return thumbnails\n}\n","/**\n * DocumentReview — a reusable, decoupled \"review mode\" viewer for a single\n * document. It renders the parsed content (chunks grouped by page, as markdown)\n * and overlays the document's AI findings: each tag citation highlights the\n * chunks it references and is listed in a findings rail that jumps to the\n * passage on click.\n *\n * REUSE-FIRST: reads purely from SDK data — `useParsedDocument` for the body,\n * the passed-in `doc.doctags[].citations` for findings, `useTags` for label\n * names, and `MarkdownRenderer` for rendering. No app store / react-pdf / Zustand\n * coupling; citation-jump is plain `scrollIntoView` on `data-chunk-id`.\n */\n\nimport React from 'react'\nimport { X } from 'lucide-react'\nimport type { components } from '@arbidocs/client'\n\nimport { useParsedDocument, useTags } from '../hooks'\nimport { useDocument } from './documents-data'\nimport { FINISHED_DOCUMENT_STATUSES } from './processing-order'\nimport { MarkdownRenderer } from '../ai/MarkdownRenderer'\nimport { TagEntity } from '../entities/TagEntity'\nimport { Badge } from '../ui/badge'\nimport { cn } from '../lib/utils'\nimport type { ParsedChunk } from './parsed-types'\n\ntype DocResponse = components['schemas']['DocResponse']\n\nexport interface DocumentReviewProps {\n /** Document to review. */\n docId: string\n /** The document object (from `useDocuments`) — supplies title + AI findings\n * (`doctags[].citations`). Optional: without it the viewer is a plain reader. */\n doc?: DocResponse\n /** Workspace id — used to resolve tag ids → human names for findings. */\n workspaceId?: string\n /** Parse stage to render. Default `final`. */\n stage?: string\n /**\n * A chunk to scroll to and persistently highlight — the join key is the\n * parsed chunk's `chunk_ext_id`. This is how a semantic-search hit drives the\n * viewer: passing the matched passage's `chunkExtId` scrolls the body to it\n * and marks it, mirroring the monolith's `viewingPassageId` behaviour.\n * Independent of AI findings (which highlight via `doctags[].citations`).\n */\n activeChunkId?: string | null\n /** When provided, a close button is shown in the header. */\n onClose?: () => void\n className?: string\n}\n\n/**\n * Statuses whose parsed text can be read (`low-content` is terminal, with sparse passages). Before\n * then the server has none (404): a copy just saved, still processing, is not an error.\n */\nconst PARSED_STATUSES = new Set<DocResponse['status']>(['completed', 'low-content'])\n\n/** Why a document has no text to review (yet). */\nfunction noTextMessage(status: DocResponse['status'] | undefined): string {\n if (status === 'failed')\n return 'This document could not be processed, so it has no text to review.'\n if (status === 'empty' || status === 'skipped') return 'No readable content.'\n return 'Still processing. The text appears here when it is ready.'\n}\n\ninterface Finding {\n key: string\n tagExtId: string\n statement: string\n chunkIds: string[]\n}\n\nexport function DocumentReview({\n docId,\n doc,\n workspaceId,\n stage = 'final',\n activeChunkId,\n onClose,\n className,\n}: DocumentReviewProps) {\n // Without its record the reader just reads; with it, the final text waits until processing is\n // done. A record still processing is re-read here every few seconds until it finishes, so a\n // missed \"completed\" event (the host's list is not refetched) cannot leave it waiting.\n const processingInProp = !!doc?.status && !FINISHED_DOCUMENT_STATUSES.has(doc.status)\n const { data: polled } = useDocument(docId, {\n enabled: processingInProp,\n pollWhileProcessing: true,\n })\n const status = processingInProp ? (polled?.status ?? doc?.status) : doc?.status\n // Only the final parse waits for the status; another stage (`marker`) is read as asked.\n const noTextYet = stage === 'final' && !!status && !PARSED_STATUSES.has(status)\n const parsedQuery = useParsedDocument(docId, stage, { enabled: !noTextYet })\n // A read made before the record arrived may have stored a 404: once the text is readable, ask\n // again.\n const { isError: parsedFailed, refetch: refetchParsed } = parsedQuery\n const readable = !!status && !noTextYet\n React.useEffect(() => {\n if (readable && parsedFailed) void refetchParsed()\n // On the status becoming readable only, not on every failure (no retry loop).\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [readable])\n const tagsQuery = useTags(workspaceId)\n\n const tagNameById = React.useMemo(() => {\n const map = new Map<string, string>()\n for (const t of tagsQuery.data ?? []) {\n if (t.external_id) map.set(t.external_id, t.name ?? t.external_id.slice(0, 8))\n }\n return map\n }, [tagsQuery.data])\n\n const title = doc?.doc_metadata?.title || doc?.file_name || 'Document'\n\n // Findings: one per grounded doctag, plus an index of which chunks it\n // highlights. A doctag used to carry a per-statement citation map, so this\n // produced several findings per tag; each statement was a verbatim copy of\n // the doctag's own note, so the tag's note IS the finding text now.\n const { findings, chunkToTag } = React.useMemo(() => {\n const list: Finding[] = []\n const chunkTag = new Map<string, string>() // chunk_ext_id → tag_ext_id\n for (const dt of doc?.doctags ?? []) {\n const chunkIds = (dt.citations ?? []).flatMap((d) => (d.chunks ?? []).map((c) => c.chunk_id))\n if (chunkIds.length === 0) continue\n list.push({\n key: dt.tag_ext_id,\n tagExtId: dt.tag_ext_id,\n statement: dt.note ?? '',\n chunkIds,\n })\n for (const cid of chunkIds) if (!chunkTag.has(cid)) chunkTag.set(cid, dt.tag_ext_id)\n }\n return { findings: list, chunkToTag: chunkTag }\n }, [doc?.doctags])\n\n // Group parsed chunks by page.\n const pages = React.useMemo(() => {\n const chunks = (parsedQuery.data?.chunks ?? []) as ParsedChunk[]\n const byPage = new Map<number, ParsedChunk[]>()\n for (const c of chunks) {\n const p = c.metadata?.page_number ?? 0\n if (!byPage.has(p)) byPage.set(p, [])\n byPage.get(p)!.push(c)\n }\n return [...byPage.entries()].sort((a, b) => a[0] - b[0])\n }, [parsedQuery.data])\n\n const scrollRef = React.useRef<HTMLDivElement | null>(null)\n const [flash, setFlash] = React.useState<string | null>(null)\n\n const jumpToChunk = React.useCallback((chunkId: string) => {\n const el = scrollRef.current?.querySelector<HTMLElement>(`[data-chunk-id=\"${chunkId}\"]`)\n if (!el) return\n el.scrollIntoView({ behavior: 'smooth', block: 'center' })\n setFlash(chunkId)\n window.setTimeout(() => setFlash((c) => (c === chunkId ? null : c)), 1600)\n }, [])\n\n // Drive the viewer from an external passage selection (semantic-search hit).\n // Scroll to + flash the target chunk once its element is in the DOM — which,\n // since this viewer renders every chunk eagerly, is as soon as the parsed\n // body has loaded. Re-runs whenever the selected passage changes so clicking\n // successive results re-navigates, matching `viewingPassageId` in the monolith.\n const parsedReady = !parsedQuery.isLoading && !!parsedQuery.data\n React.useEffect(() => {\n if (!activeChunkId || !parsedReady) return\n // Defer to the next frame so the chunk nodes are committed before we query.\n const raf = window.requestAnimationFrame(() => jumpToChunk(activeChunkId))\n return () => window.cancelAnimationFrame(raf)\n }, [activeChunkId, parsedReady, jumpToChunk])\n\n return (\n <div\n data-testid=\"document-review\"\n className={cn(\n 'flex h-full min-h-0 flex-col overflow-hidden rounded-lg border bg-card',\n className\n )}\n >\n {/* Header */}\n <div className=\"flex items-center gap-3 border-b px-4 py-3\">\n <div className=\"min-w-0 flex-1\">\n <div className=\"truncate text-sm font-semibold\" title={title}>\n {title}\n </div>\n <div className=\"text-xs text-muted-foreground\">\n {noTextYet\n ? ''\n : parsedQuery.data?.metadata?.total_number_of_pages\n ? `${parsedQuery.data.metadata.total_number_of_pages} pages`\n : `${pages.length} pages`}\n {findings.length ? ` · ${findings.length} findings` : ''}\n </div>\n </div>\n {status ? <Badge variant=\"secondary\">{status}</Badge> : null}\n {onClose ? (\n <button\n type=\"button\"\n aria-label=\"Close review\"\n data-testid=\"document-review-close\"\n onClick={onClose}\n className=\"rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground\"\n >\n <X className=\"size-4\" />\n </button>\n ) : null}\n </div>\n\n <div className=\"flex min-h-0 flex-1\">\n {/* Findings rail */}\n {findings.length > 0 ? (\n <aside\n className=\"hidden w-64 shrink-0 overflow-y-auto border-r p-3 md:block\"\n data-testid=\"document-review-findings\"\n >\n <div className=\"mb-2 text-xs font-medium uppercase tracking-wide text-muted-foreground\">\n AI findings\n </div>\n <ul className=\"space-y-2\">\n {findings.map((f) => (\n <li key={f.key}>\n {/* role=button (not <button>) so the TagEntity pill — itself a\n button — isn't nested inside a button (invalid HTML). */}\n <div\n role=\"button\"\n tabIndex={0}\n data-testid=\"review-finding\"\n onClick={() => jumpToChunk(f.chunkIds[0])}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n jumpToChunk(f.chunkIds[0])\n }\n }}\n className=\"w-full cursor-pointer rounded-md border p-2 text-left text-xs transition hover:border-ring hover:bg-muted/50 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <TagEntity\n size=\"sm\"\n tag={{\n external_id: f.tagExtId,\n name: tagNameById.get(f.tagExtId) ?? f.tagExtId.slice(0, 8),\n }}\n />\n <p className=\"mt-1 line-clamp-3 text-muted-foreground\">{f.statement}</p>\n </div>\n </li>\n ))}\n </ul>\n </aside>\n ) : null}\n\n {/* Document body */}\n <div ref={scrollRef} className=\"min-w-0 flex-1 overflow-y-auto px-6 py-4\">\n {noTextYet ? (\n <div\n className=\"flex h-full items-center justify-center text-sm text-muted-foreground\"\n data-testid=\"document-review-no-text\"\n >\n {noTextMessage(status)}\n </div>\n ) : parsedQuery.isLoading ? (\n <div className=\"flex h-full items-center justify-center text-sm text-muted-foreground\">\n Loading document…\n </div>\n ) : parsedQuery.isError ? (\n <div className=\"flex h-full items-center justify-center text-sm text-muted-foreground\">\n Could not load this document’s content.\n </div>\n ) : pages.length === 0 ? (\n <div className=\"flex h-full items-center justify-center text-sm text-muted-foreground\">\n No readable content.\n </div>\n ) : (\n <div className=\"mx-auto max-w-3xl space-y-8\">\n {pages.map(([pageNum, chunks]) => (\n <section key={pageNum}>\n <div className=\"mb-3 flex items-center gap-3\">\n <span className=\"text-xs font-medium uppercase tracking-wide text-muted-foreground\">\n Page {pageNum}\n </span>\n <div className=\"h-px flex-1 bg-border\" />\n </div>\n <div className=\"space-y-3\">\n {chunks.map((c, i) => {\n const cid = c.metadata?.chunk_ext_id\n const tagExtId = cid ? chunkToTag.get(cid) : undefined\n const highlighted = !!tagExtId\n const isActive = !!cid && cid === activeChunkId\n return (\n <div\n key={cid ?? i}\n data-chunk-id={cid}\n data-testid={\n isActive\n ? 'review-chunk-active'\n : highlighted\n ? 'review-chunk-cited'\n : 'review-chunk'\n }\n className={cn(\n 'scroll-mt-4 rounded-md px-2 py-1 transition-colors',\n highlighted &&\n 'bg-[var(--color-ai-accent-soft,theme(colors.amber.100))] ring-1 ring-inset ring-border',\n // The externally-selected search passage wins the\n // styling: a stronger accent ring so the matched\n // hit stands out from any AI-finding highlights.\n isActive &&\n 'bg-[var(--color-ai-accent-soft,theme(colors.amber.100))] ring-2 ring-inset ring-ai-accent',\n flash === cid && 'ring-2 ring-ring'\n )}\n >\n {highlighted ? (\n <div className=\"mb-1\">\n <TagEntity\n size=\"sm\"\n tag={{\n external_id: tagExtId!,\n name: tagNameById.get(tagExtId!) ?? tagExtId!.slice(0, 8),\n }}\n />\n </div>\n ) : null}\n <MarkdownRenderer className=\"prose prose-sm max-w-none dark:prose-invert\">\n {c.content}\n </MarkdownRenderer>\n </div>\n )\n })}\n </div>\n </section>\n ))}\n </div>\n )}\n </div>\n </div>\n </div>\n )\n}\n","/**\n * VoiceNoteRecorder\n *\n * A toggle-style recorder (press to start, pause/resume, stop, review, then\n * save or discard) as opposed to a press-and-hold mic. Shares its\n * capture/metering engine (useAudioRecorder) and its REC-badge/timer/waveform\n * visual (MicWaveformIndicator) with any other recorder a host app builds.\n *\n * REUSE-FIRST: no app coupling. The host supplies `onSave`/`onDiscard` (and\n * optionally `onError`) — this component owns only the recording UI and\n * in-memory blob, never persistence. Nothing is uploaded until the host's\n * `onSave` is called and resolves.\n */\n\nimport { useEffect, useState } from 'react'\nimport { Mic, Pause, Play, Square, Trash2, Check, Loader2, RotateCcw } from 'lucide-react'\nimport { Button } from '../ui/button'\nimport { AudioViewer } from '../viewers/AudioViewer'\nimport { useAudioRecorder } from './useAudioRecorder'\nimport { MicWaveformIndicator } from './MicWaveformIndicator'\n\nexport interface VoiceNoteRecorderProps {\n /** Called with the reviewed recording when the user hits Save. Resolve to\n * let the host close/replace this recorder; the recorder shows a saving\n * spinner while the promise is pending. */\n onSave: (blob: Blob, mimeType: string | null) => Promise<void> | void\n /** Called when the user discards the draft. */\n onDiscard: () => void\n /** Surfaces recorder failures (e.g. denied mic permission) — wire this to\n * the host's own notification system. Without it, failures are silent. */\n onError?: (message: string) => void\n /** Title passed through to the playback preview. */\n title?: string\n /** External saving state, e.g. while the host's onSave promise is\n * pending — disables actions and shows a spinner on Save. */\n isSaving?: boolean\n /**\n * Optional: called once with the finished recording as soon as it stops,\n * to produce a quick rough transcript shown inline during review. Purely\n * client-side and ephemeral — it's never uploaded and has no bearing on\n * what onSave receives; a host with real (e.g. diarized) transcription as\n * part of its normal document processing can skip this prop entirely.\n */\n transcribe?: (blob: Blob) => Promise<string>\n}\n\nexport function VoiceNoteRecorder({\n onSave,\n onDiscard,\n onError,\n title = 'Voice Memo',\n isSaving = false,\n transcribe,\n}: VoiceNoteRecorderProps) {\n const recorder = useAudioRecorder()\n const [transcript, setTranscript] = useState<string | null>(null)\n const [isTranscribing, setIsTranscribing] = useState(false)\n\n useEffect(() => {\n if (recorder.error) onError?.(recorder.error)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [recorder.error])\n\n // Kick off the rough transcript the moment a recording is ready to review,\n // so it's usually done by the time the user has looked at the playback\n // controls. Reset on any state other than 'stopped' (re-record, discard)\n // so a stale transcript from a previous take never lingers.\n useEffect(() => {\n if (recorder.state !== 'stopped' || !recorder.blob) {\n setTranscript(null)\n setIsTranscribing(false)\n return\n }\n if (!transcribe) return\n let cancelled = false\n setIsTranscribing(true)\n transcribe(recorder.blob)\n .then((text) => {\n if (!cancelled) setTranscript(text)\n })\n .catch(() => {\n // Best-effort: a failed rough transcript just means the review UI\n // shows nothing extra — the real transcript still arrives later.\n })\n .finally(() => {\n if (!cancelled) setIsTranscribing(false)\n })\n return () => {\n cancelled = true\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [recorder.state, recorder.blob])\n\n const handleSave = () => {\n if (!recorder.blob) return\n void onSave(recorder.blob, recorder.mimeType)\n }\n\n return (\n <div className=\"flex h-full flex-col items-center justify-center gap-6 p-8\">\n {recorder.state === 'idle' && (\n <>\n <Button\n type=\"button\"\n size=\"lg\"\n className=\"h-16 w-16 rounded-full p-0\"\n onClick={() => void recorder.start()}\n data-testid=\"voice-note-record-button\"\n >\n <Mic className=\"h-6 w-6\" />\n </Button>\n <p className=\"text-sm text-muted-foreground\">Press to start recording</p>\n </>\n )}\n\n {(recorder.state === 'recording' || recorder.state === 'paused') && (\n <>\n <MicWaveformIndicator\n level={recorder.level}\n elapsedMs={recorder.elapsedMs}\n paused={recorder.state === 'paused'}\n />\n <div className=\"flex items-center gap-3\">\n {recorder.state === 'recording' ? (\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={recorder.pause}\n data-testid=\"voice-note-pause-button\"\n >\n <Pause className=\"mr-1.5 h-4 w-4\" />\n Pause\n </Button>\n ) : (\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={recorder.resume}\n data-testid=\"voice-note-resume-button\"\n >\n <Play className=\"mr-1.5 h-4 w-4\" />\n Resume\n </Button>\n )}\n <Button type=\"button\" onClick={recorder.stop} data-testid=\"voice-note-stop-button\">\n <Square className=\"mr-1.5 h-3.5 w-3.5 fill-current\" />\n Stop\n </Button>\n </div>\n </>\n )}\n\n {recorder.state === 'stopped' && recorder.blob && (\n <>\n <div className=\"w-full max-w-md\">\n <AudioViewer blob={recorder.blob} title={title} />\n </div>\n {(isTranscribing || transcript) && (\n <div\n className=\"w-full max-w-md rounded-md border border-border bg-muted/30 p-3 text-sm text-muted-foreground\"\n data-testid=\"voice-note-rough-transcript\"\n >\n {isTranscribing ? (\n <span className=\"flex items-center gap-1.5\">\n <Loader2 className=\"h-3.5 w-3.5 animate-spin\" />\n Transcribing…\n </span>\n ) : (\n <>\n <p className=\"mb-1 text-xs font-semibold uppercase tracking-wide\">\n Rough transcript\n </p>\n <p>{transcript}</p>\n </>\n )}\n </div>\n )}\n <div className=\"flex items-center gap-3\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={onDiscard}\n disabled={isSaving}\n data-testid=\"voice-note-discard-button\"\n >\n <Trash2 className=\"mr-1.5 h-4 w-4\" />\n Discard\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={recorder.reset}\n disabled={isSaving}\n data-testid=\"voice-note-record-again-button\"\n >\n <RotateCcw className=\"mr-1.5 h-4 w-4\" />\n Record again\n </Button>\n <Button\n type=\"button\"\n onClick={handleSave}\n disabled={isSaving}\n data-testid=\"voice-note-save-button\"\n >\n {isSaving ? (\n <Loader2 className=\"mr-1.5 h-4 w-4 animate-spin\" />\n ) : (\n <Check className=\"mr-1.5 h-4 w-4\" />\n )}\n {isSaving ? 'Saving…' : 'Save'}\n </Button>\n </div>\n </>\n )}\n </div>\n )\n}\n","/**\n * DraftTitleControls\n *\n * A title field + an auto-name toggle for an unsaved draft (blank document,\n * voice note, or anything else a host app drafts before it exists on the\n * backend) — so picking a name or leaving AI generation on doesn't require a\n * separate settings surface.\n *\n * REUSE-FIRST: props/callbacks in, no store or config-API coupling. The host\n * owns where `title` is stored and what `autoRename` actually controls (in\n * ARBI-frontend, the same `DoctagLLM.AUTO_RENAME` config field the Upload\n * modal's toggle already writes).\n */\n\nimport { Sparkles } from 'lucide-react'\nimport { IconToggle } from '../ui/IconToggle'\n\nconst AUTO_RENAME_COLORS = { text: 'text-amber-700', bg: 'bg-amber-500' }\n\nexport interface DraftTitleControlsProps {\n title: string\n onTitleChange: (title: string) => void\n placeholder: string\n autoRename: boolean\n onAutoRenameChange: (value: boolean) => void\n}\n\nexport function DraftTitleControls({\n title,\n onTitleChange,\n placeholder,\n autoRename,\n onAutoRenameChange,\n}: DraftTitleControlsProps) {\n return (\n <div className=\"flex min-w-0 flex-shrink-0 items-center gap-1.5\">\n <input\n type=\"text\"\n value={title}\n onChange={(e) => onTitleChange(e.target.value)}\n placeholder={placeholder}\n className=\"min-w-0 max-w-[220px] rounded-md bg-muted px-2 py-1 text-sm font-medium outline-none focus-visible:ring-1 focus-visible:ring-primary\"\n data-testid=\"draft-title-input\"\n />\n <IconToggle\n icon={Sparkles}\n isActive={autoRename}\n onToggle={onAutoRenameChange}\n colors={AUTO_RENAME_COLORS}\n tooltipActive=\"Auto-name from content is on — generates a title once saved\"\n tooltipInactive=\"Auto-name from content is off — uses the name typed above\"\n data-testid=\"draft-auto-rename-toggle\"\n />\n </div>\n )\n}\n","/**\n * useCameraStream\n *\n * Shared camera-acquisition engine for photo and video capture — requests\n * `getUserMedia`, hands back the live `MediaStream` for a host to bind to a\n * `<video>` element, and tears the tracks down on stop()/unmount. Mirrors\n * `useAudioRecorder`'s permission/error handling (same DOMException\n * classification, via `classifyMediaError`) but stays a separate hook rather\n * than folding into it: audio's state machine centers on an AnalyserNode\n * level meter with no visual preview, while camera capture centers on a live\n * video preview with no metering — sharing \"here is a device stream and an\n * error string\" is the useful overlap, not the recording state machine\n * itself. `useVideoRecorder` layers MediaRecorder on top of the stream this\n * returns; photo capture reads a frame off it directly (see capture-frame.ts).\n *\n * REUSE-FIRST: no app coupling, failures surface via `error` rather than a\n * toast call — same contract as useAudioRecorder.\n */\n\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport { classifyMediaError } from './media-error'\n\nexport interface UseCameraStreamResult {\n /** The live camera stream, or null before start()/after stop(). */\n stream: MediaStream | null\n /** True while the getUserMedia() prompt/negotiation is in flight. */\n isStarting: boolean\n /** A human-readable message from the last failed start() attempt. */\n error: string | null\n start: () => Promise<void>\n /** Stops all tracks and clears the stream. Safe to call repeatedly. */\n stop: () => void\n}\n\n/**\n * @param constraints The `video`/`audio` constraints passed to getUserMedia.\n * Defaults to video-only (photo capture never needs a mic); video capture\n * passes `{ video: true, audio: true }` to record sound with the picture.\n */\nexport function useCameraStream(\n constraints: MediaStreamConstraints = { video: true, audio: false }\n): UseCameraStreamResult {\n const [stream, setStream] = useState<MediaStream | null>(null)\n const [isStarting, setIsStarting] = useState(false)\n const [error, setError] = useState<string | null>(null)\n const streamRef = useRef<MediaStream | null>(null)\n\n const stop = useCallback(() => {\n streamRef.current?.getTracks().forEach((t) => t.stop())\n streamRef.current = null\n setStream(null)\n }, [])\n\n // Constraints are read fresh each start() call rather than becoming a hook\n // dependency: a host re-rendering with a new (but equivalent) constraints\n // object shouldn't force callers to memoize it just to avoid an effect loop.\n const constraintsRef = useRef(constraints)\n constraintsRef.current = constraints\n\n const start = useCallback(async () => {\n if (streamRef.current) return\n setError(null)\n setIsStarting(true)\n try {\n const media = await navigator.mediaDevices.getUserMedia(constraintsRef.current)\n streamRef.current = media\n setStream(media)\n } catch (err) {\n setError(classifyMediaError(err, 'camera'))\n } finally {\n setIsStarting(false)\n }\n }, [])\n\n useEffect(() => () => stop(), [stop])\n\n return { stream, isStarting, error, start, stop }\n}\n","/**\n * useVideoRecorder\n *\n * MediaRecorder lifecycle for video capture, layered on top of an\n * already-live camera `MediaStream` (see useCameraStream — this hook does\n * NOT call getUserMedia itself, so the same stream stays open across a\n * stop()/reset() \"record again\" without re-prompting for permission).\n *\n * Deliberately simpler than useAudioRecorder: no pause/resume (tap-to-start,\n * tap-to-stop is the whole interaction — see VideoCapture) and no\n * level meter (there's a live video preview instead; a bar-graph loudness\n * meter would be redundant chrome on top of it).\n */\n\nimport { useCallback, useEffect, useRef, useState } from 'react'\n\nexport type VideoRecorderState = 'idle' | 'recording' | 'stopped'\n\nexport interface UseVideoRecorderResult {\n state: VideoRecorderState\n /** Recorded duration so far (ms). Frozen at its final value once stopped. */\n elapsedMs: number\n /** The finished recording. Only set once state === 'stopped'. */\n blob: Blob | null\n /** The MediaRecorder MIME type used (e.g. 'video/webm'). */\n mimeType: string | null\n start: () => void\n stop: () => void\n /** Back to idle: clears blob/elapsedMs, ready to record again on the same stream. */\n reset: () => void\n}\n\nconst ELAPSED_TICK_MS = 200\n\n/** @param stream The live camera stream to record — null while the camera\n * hasn't started yet; start() is a no-op until it's set. */\nexport function useVideoRecorder(stream: MediaStream | null): UseVideoRecorderResult {\n const [state, setState] = useState<VideoRecorderState>('idle')\n const [elapsedMs, setElapsedMs] = useState(0)\n const [blob, setBlob] = useState<Blob | null>(null)\n const [mimeType, setMimeType] = useState<string | null>(null)\n\n const mediaRecorderRef = useRef<MediaRecorder | null>(null)\n const chunksRef = useRef<Blob[]>([])\n const startedAtRef = useRef(0)\n const tickRef = useRef<ReturnType<typeof setInterval> | null>(null)\n const stateRef = useRef<VideoRecorderState>('idle')\n stateRef.current = state\n\n const stopTicking = useCallback(() => {\n if (tickRef.current !== null) clearInterval(tickRef.current)\n tickRef.current = null\n }, [])\n\n useEffect(() => stopTicking, [stopTicking])\n\n const start = useCallback(() => {\n if (!stream || stateRef.current === 'recording') return\n const mt = MediaRecorder.isTypeSupported('video/webm') ? 'video/webm' : 'video/mp4'\n const recorder = new MediaRecorder(stream, { mimeType: mt })\n chunksRef.current = []\n recorder.ondataavailable = (e) => {\n if (e.data.size > 0) chunksRef.current.push(e.data)\n }\n mediaRecorderRef.current = recorder\n setMimeType(mt)\n setBlob(null)\n startedAtRef.current = performance.now()\n setElapsedMs(0)\n recorder.start()\n setState('recording')\n tickRef.current = setInterval(() => {\n setElapsedMs(performance.now() - startedAtRef.current)\n }, ELAPSED_TICK_MS)\n }, [stream])\n\n const stop = useCallback(() => {\n const recorder = mediaRecorderRef.current\n if (!recorder || recorder.state === 'inactive') return\n const finalElapsed = performance.now() - startedAtRef.current\n stopTicking()\n recorder.onstop = () => {\n const finalBlob = chunksRef.current.length\n ? new Blob(chunksRef.current, { type: recorder.mimeType })\n : null\n setBlob(finalBlob)\n setElapsedMs(finalElapsed)\n setState('stopped')\n }\n recorder.stop()\n }, [stopTicking])\n\n const reset = useCallback(() => {\n setState('idle')\n setBlob(null)\n setElapsedMs(0)\n setMimeType(null)\n }, [])\n\n return { state, elapsedMs, blob, mimeType, start, stop, reset }\n}\n","/**\n * Captures the current frame of a live `<video>` element (bound to a camera\n * `MediaStream`, e.g. via useCameraStream) as an image Blob — the shutter\n * action for photo capture. Draws to an off-screen canvas rather than reading\n * pixels any other way, since `HTMLCanvasElement.toBlob` is the one\n * cross-browser path from \"a decoded video frame\" to \"an encoded image file\".\n */\nexport function captureFrameAsBlob(video: HTMLVideoElement, mimeType = 'image/png'): Promise<Blob> {\n return new Promise((resolve, reject) => {\n const canvas = document.createElement('canvas')\n canvas.width = video.videoWidth\n canvas.height = video.videoHeight\n const ctx = canvas.getContext('2d')\n if (!ctx) {\n reject(new Error('Canvas 2D context is not available'))\n return\n }\n ctx.drawImage(video, 0, 0, canvas.width, canvas.height)\n canvas.toBlob((blob) => {\n if (blob) resolve(blob)\n else reject(new Error('Failed to capture the photo'))\n }, mimeType)\n })\n}\n","/**\n * PhotoCapture\n *\n * Camera capture UI: live preview → shutter → review (retake or save).\n * Shares its shape (onSave/onDiscard/onError/isSaving) with VoiceNoteRecorder\n * so a host app wires them identically — see ViewerCaptureDraft\n * (`@arbidocs/blocks`, connection/viewer/drafts.tsx) for how the three capture\n * modes plug into the same draft/save contract.\n *\n * REUSE-FIRST: no app coupling. This component owns only the capture UI and\n * in-memory blob, never persistence — nothing is uploaded until the host's\n * `onSave` is called.\n */\n\nimport { useEffect, useRef, useState } from 'react'\nimport { Camera, Check, Loader2, RotateCcw, Trash2 } from 'lucide-react'\nimport { Button } from '../ui/button'\nimport { ImageViewer } from '../viewers/ImageViewer'\nimport { useCameraStream } from './useCameraStream'\nimport { captureFrameAsBlob } from './capture-frame'\n\nexport interface PhotoCaptureProps {\n /** Called with the captured photo when the user hits Save. Resolve to let\n * the host close/replace this capture UI; shows a saving spinner while\n * the promise is pending. */\n onSave: (blob: Blob, mimeType: string | null) => Promise<void> | void\n /** Called when the user discards the draft. */\n onDiscard: () => void\n /** Surfaces camera failures (e.g. denied permission) — wire this to the\n * host's own notification system. Without it, failures are silent. */\n onError?: (message: string) => void\n isSaving?: boolean\n}\n\nexport function PhotoCapture({ onSave, onDiscard, onError, isSaving = false }: PhotoCaptureProps) {\n const camera = useCameraStream({ video: true, audio: false })\n const videoRef = useRef<HTMLVideoElement>(null)\n const [capturedBlob, setCapturedBlob] = useState<Blob | null>(null)\n const [captureError, setCaptureError] = useState<string | null>(null)\n\n useEffect(() => {\n void camera.start()\n // Start the camera once on mount — camera.start is stable (useCallback\n // with no deps), so this intentionally doesn't re-run per render.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n useEffect(() => {\n if (camera.error) onError?.(camera.error)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [camera.error])\n\n useEffect(() => {\n const video = videoRef.current\n if (!video) return\n video.srcObject = camera.stream\n if (camera.stream) void video.play().catch(() => {})\n }, [camera.stream])\n\n const handleShutter = () => {\n const video = videoRef.current\n if (!video) return\n setCaptureError(null)\n captureFrameAsBlob(video)\n .then(setCapturedBlob)\n .catch((err) => {\n const message = err instanceof Error ? err.message : 'Failed to capture the photo'\n setCaptureError(message)\n onError?.(message)\n })\n }\n\n const handleRetake = () => setCapturedBlob(null)\n\n const handleSave = () => {\n if (!capturedBlob) return\n void onSave(capturedBlob, 'image/png')\n }\n\n return (\n <div className=\"flex h-full flex-col items-center justify-center gap-6 p-8\">\n {!capturedBlob && (\n <>\n <div className=\"w-full max-w-md overflow-hidden rounded-lg bg-muted/30\">\n <video\n ref={videoRef}\n autoPlay\n muted\n playsInline\n className=\"w-full max-h-[60vh] object-contain\"\n data-testid=\"photo-capture-preview\"\n />\n </div>\n <Button\n type=\"button\"\n size=\"lg\"\n className=\"h-16 w-16 rounded-full p-0\"\n onClick={handleShutter}\n disabled={!camera.stream}\n data-testid=\"photo-capture-shutter-button\"\n >\n <Camera className=\"h-6 w-6\" />\n </Button>\n <p className=\"text-sm text-muted-foreground\">\n {camera.isStarting\n ? 'Starting camera…'\n : camera.stream\n ? 'Press to take a photo'\n : 'Waiting for camera access…'}\n </p>\n {captureError && <p className=\"text-sm text-red-text\">{captureError}</p>}\n </>\n )}\n\n {capturedBlob && (\n <>\n <div className=\"w-full max-w-md\">\n <ImageViewer blob={capturedBlob} alt=\"Captured photo\" />\n </div>\n <div className=\"flex items-center gap-3\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={onDiscard}\n disabled={isSaving}\n data-testid=\"photo-capture-discard-button\"\n >\n <Trash2 className=\"mr-1.5 h-4 w-4\" />\n Discard\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={handleRetake}\n disabled={isSaving}\n data-testid=\"photo-capture-retake-button\"\n >\n <RotateCcw className=\"mr-1.5 h-4 w-4\" />\n Retake\n </Button>\n <Button\n type=\"button\"\n onClick={handleSave}\n disabled={isSaving}\n data-testid=\"photo-capture-save-button\"\n >\n {isSaving ? (\n <Loader2 className=\"mr-1.5 h-4 w-4 animate-spin\" />\n ) : (\n <Check className=\"mr-1.5 h-4 w-4\" />\n )}\n {isSaving ? 'Saving…' : 'Save'}\n </Button>\n </div>\n </>\n )}\n </div>\n )\n}\n","/**\n * VideoCapture\n *\n * Camera capture UI: live preview → tap to record / tap to stop → review\n * (playback, retake, or save). Shares its shape (onSave/onDiscard/onError/\n * isSaving) with VoiceNoteRecorder and PhotoCapture — see ViewerCaptureDraft\n * (`@arbidocs/blocks`, connection/viewer/drafts.tsx) for how the three capture\n * modes plug into the same draft/save contract.\n *\n * Deliberately a simple tap-to-start/tap-to-stop toggle rather than a\n * press-and-hold gesture — matches VoiceNoteRecorder's toggle interaction\n * and needs no extra gesture handling for a first cut of camera video.\n *\n * REUSE-FIRST: no app coupling. This component owns only the capture UI and\n * in-memory blob, never persistence — nothing is uploaded until the host's\n * `onSave` is called.\n */\n\nimport { useEffect, useRef } from 'react'\nimport { Check, Circle, Loader2, RotateCcw, Square, Trash2 } from 'lucide-react'\nimport { Button } from '../ui/button'\nimport { VideoViewer } from '../viewers/VideoViewer'\nimport { useCameraStream } from './useCameraStream'\nimport { useVideoRecorder } from './useVideoRecorder'\nimport { formatElapsed } from './format-elapsed'\n\nexport interface VideoCaptureProps {\n /** Called with the recorded clip when the user hits Save. Resolve to let\n * the host close/replace this capture UI; shows a saving spinner while\n * the promise is pending. */\n onSave: (blob: Blob, mimeType: string | null) => Promise<void> | void\n /** Called when the user discards the draft. */\n onDiscard: () => void\n /** Surfaces camera failures (e.g. denied permission) — wire this to the\n * host's own notification system. Without it, failures are silent. */\n onError?: (message: string) => void\n isSaving?: boolean\n}\n\nexport function VideoCapture({ onSave, onDiscard, onError, isSaving = false }: VideoCaptureProps) {\n // Camera audio too, not just video — a silent clip would surprise anyone\n // used to phone camera video capture.\n const camera = useCameraStream({ video: true, audio: true })\n const recorder = useVideoRecorder(camera.stream)\n const videoRef = useRef<HTMLVideoElement>(null)\n\n useEffect(() => {\n void camera.start()\n // Start the camera once on mount — see PhotoCapture's identical effect.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n useEffect(() => {\n if (camera.error) onError?.(camera.error)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [camera.error])\n\n // Live preview binds to the camera stream while previewing/recording; once\n // stopped, the video element is replaced by VideoViewer playing the\n // recorded blob (below), so this effect only matters pre-stop.\n useEffect(() => {\n const video = videoRef.current\n if (!video || recorder.state === 'stopped') return\n video.srcObject = camera.stream\n if (camera.stream) void video.play().catch(() => {})\n }, [camera.stream, recorder.state])\n\n const handleRetake = () => {\n recorder.reset()\n }\n\n const handleSave = () => {\n if (!recorder.blob) return\n void onSave(recorder.blob, recorder.mimeType)\n }\n\n return (\n <div className=\"flex h-full flex-col items-center justify-center gap-6 p-8\">\n {recorder.state !== 'stopped' && (\n <>\n <div className=\"w-full max-w-md overflow-hidden rounded-lg bg-muted/30\">\n <video\n ref={videoRef}\n autoPlay\n muted\n playsInline\n className=\"w-full max-h-[60vh] object-contain\"\n data-testid=\"video-capture-preview\"\n />\n </div>\n {recorder.state === 'recording' && (\n <div className=\"flex items-center gap-2\" data-testid=\"video-capture-rec-indicator\">\n <span className=\"relative flex h-2 w-2\">\n <span className=\"absolute inline-flex h-full w-full animate-ping rounded-full bg-red-500 opacity-75\" />\n <span className=\"relative inline-flex h-2 w-2 rounded-full bg-red-500\" />\n </span>\n <span className=\"text-xs font-semibold uppercase tracking-wide text-red-500\">\n Rec\n </span>\n <span className=\"font-mono text-xs tabular-nums text-muted-foreground\">\n {formatElapsed(recorder.elapsedMs)}\n </span>\n </div>\n )}\n {recorder.state === 'recording' ? (\n <Button\n type=\"button\"\n size=\"lg\"\n className=\"h-16 w-16 rounded-full p-0\"\n onClick={recorder.stop}\n data-testid=\"video-capture-stop-button\"\n >\n <Square className=\"h-5 w-5 fill-current\" />\n </Button>\n ) : (\n <Button\n type=\"button\"\n size=\"lg\"\n className=\"h-16 w-16 rounded-full p-0\"\n onClick={recorder.start}\n disabled={!camera.stream}\n data-testid=\"video-capture-record-button\"\n >\n <Circle className=\"h-6 w-6 fill-current\" />\n </Button>\n )}\n <p className=\"text-sm text-muted-foreground\">\n {recorder.state === 'recording'\n ? 'Tap to stop recording'\n : camera.isStarting\n ? 'Starting camera…'\n : camera.stream\n ? 'Tap to start recording'\n : 'Waiting for camera access…'}\n </p>\n </>\n )}\n\n {recorder.state === 'stopped' && recorder.blob && (\n <>\n <div className=\"w-full max-w-md\">\n <VideoViewer blob={recorder.blob} title=\"Captured video\" />\n </div>\n <div className=\"flex items-center gap-3\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={onDiscard}\n disabled={isSaving}\n data-testid=\"video-capture-discard-button\"\n >\n <Trash2 className=\"mr-1.5 h-4 w-4\" />\n Discard\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={handleRetake}\n disabled={isSaving}\n data-testid=\"video-capture-retake-button\"\n >\n <RotateCcw className=\"mr-1.5 h-4 w-4\" />\n Record again\n </Button>\n <Button\n type=\"button\"\n onClick={handleSave}\n disabled={isSaving}\n data-testid=\"video-capture-save-button\"\n >\n {isSaving ? (\n <Loader2 className=\"mr-1.5 h-4 w-4 animate-spin\" />\n ) : (\n <Check className=\"mr-1.5 h-4 w-4\" />\n )}\n {isSaving ? 'Saving…' : 'Save'}\n </Button>\n </div>\n </>\n )}\n </div>\n )\n}\n","/**\n * Content-based audio-vs-video detection for containers that don't tell you\n * from the extension alone. WebM in particular can hold audio-only, video-only,\n * or both, and a host app bucketing purely by file extension will get an\n * audio-only recording (e.g. a voice note) wrong, since `.webm` is what\n * MediaRecorder produces either way.\n *\n * No backend involvement needed: most document APIs don't expose a\n * content-type field to check post-upload (only a file name), but loading the\n * bytes into a hidden <video> element and reading its decoded metadata does\n * the job entirely client-side — videoWidth/videoHeight report 0x0 when\n * there's no video track, even though duration/audio still work fine.\n */\nexport function hasVideoTrack(blob: Blob): Promise<boolean> {\n return new Promise((resolve) => {\n const url = URL.createObjectURL(blob)\n const video = document.createElement('video')\n video.preload = 'metadata'\n video.muted = true\n\n const cleanup = () => {\n video.removeAttribute('src')\n video.load()\n URL.revokeObjectURL(url)\n }\n\n video.onloadedmetadata = () => {\n resolve(video.videoWidth > 0 && video.videoHeight > 0)\n cleanup()\n }\n // Couldn't even decode it as a video container — treat conservatively as\n // \"no video track\" rather than leaving the caller hanging.\n video.onerror = () => {\n resolve(false)\n cleanup()\n }\n\n video.src = url\n })\n}\n","/**\n * Choosing files to upload: what the picker accepts, which files are refused and why, folders\n * dropped whole (each file keeps its path below the dropped folder), zip archives opened into\n * their files, and the folder a file goes to.\n */\n\nimport { documents } from '@arbidocs/sdk/browser'\n\nconst { SUPPORTED_EXTENSIONS, mimeFromName, sanitizeFolderPath } = documents\n\n/** The file picker's `accept`: every type an upload takes, zip archives included. */\nexport const UPLOAD_ACCEPT =\n '.pdf,.txt,.md,.html,.doc,.docx,.rtf,.ppt,.pptx,.xls,.xlsx,.jpg,.jpeg,.png,.gif,.bmp,.tiff,.tif,.webp,.mp4,.mpeg,.mpg,.webm,.mov,.avi,.mkv,.mp3,.wav,.m4a,.aac,.ogg,.flac,.eml,.msg,.mbox,.pst,.ost,.zip,application/pdf,text/plain,text/markdown,text/html,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/rtf,application/vnd.ms-powerpoint,application/vnd.openxmlformats-officedocument.presentationml.presentation,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,image/jpeg,image/png,image/gif,image/bmp,image/tiff,image/webp,video/mp4,video/mpeg,video/webm,video/quicktime,video/x-msvideo,video/x-matroska,audio/mpeg,audio/wav,audio/mp4,audio/aac,audio/ogg,audio/flac,message/rfc822,application/vnd.ms-outlook,application/mbox,application/zip,application/x-zip-compressed'\n\n/** The largest file a browser upload takes. */\nexport const UPLOAD_MAX_FILE_SIZE = 2 * 1024 * 1024 * 1024\n\nconst SUPPORTED_TYPES = new Set([\n 'application/pdf',\n 'text/plain',\n 'text/markdown',\n 'text/html',\n 'application/msword',\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n 'application/rtf',\n 'application/vnd.ms-powerpoint',\n 'application/vnd.openxmlformats-officedocument.presentationml.presentation',\n 'application/vnd.ms-excel',\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n 'image/jpeg',\n 'image/png',\n 'image/gif',\n 'image/bmp',\n 'image/tiff',\n 'image/webp',\n 'video/mp4',\n 'video/mpeg',\n 'video/webm',\n 'video/quicktime',\n 'video/x-msvideo',\n 'video/x-matroska',\n 'audio/mpeg',\n 'audio/wav',\n 'audio/mp4',\n 'audio/aac',\n 'audio/ogg',\n 'audio/flac',\n 'message/rfc822',\n 'application/vnd.ms-outlook',\n 'application/mbox',\n])\n\n/** Why a chosen file is not uploaded. */\nexport type UploadRefusal =\n 'empty' | 'too_large' | 'no_extension' | 'unsupported' | 'empty_zip' | 'zip_error'\n\nexport interface RefusedUploadFile {\n name: string\n reason: UploadRefusal\n}\n\n/** A zip archive's files, and the names of those too large to take. */\nexport interface ExtractedZip {\n extractedFiles: File[]\n skippedLargeFiles: string[]\n}\n\n/** Opens a zip archive into its files (each with its path in `webkitRelativePath`). */\nexport type ZipExtractor = (zip: File, maxFileSize: number) => Promise<ExtractedZip>\n\nfunction extensionOf(name: string): string {\n const dot = name.lastIndexOf('.')\n return dot === -1 ? '' : name.slice(dot).toLowerCase()\n}\n\n/** A file with its path below a dropped or picked folder (as the browser's folder picker sets). */\nexport function withRelativePath(file: File, relativePath: string): File {\n const copy = new File([file], file.name, { type: file.type, lastModified: file.lastModified })\n Object.defineProperty(copy, 'webkitRelativePath', { value: relativePath, writable: false })\n return copy\n}\n\nexport function isZipFile(file: Pick<File, 'name' | 'type'>): boolean {\n return (\n file.name.toLowerCase().endsWith('.zip') ||\n file.type === 'application/zip' ||\n file.type === 'application/x-zip-compressed'\n )\n}\n\n/**\n * Open a zip archive into the files an upload takes. An archive whose files all sit in one folder\n * keeps that folder; otherwise they go under a folder named after the archive.\n */\nexport const extractZipFile: ZipExtractor = async (zip, maxFileSize) => {\n const { unzip } = await import('unzipit')\n const { entries } = await unzip(await zip.arrayBuffer())\n const names = Object.keys(entries).filter((name) => !entries[name].isDirectory)\n const roots = new Set(names.map((name) => name.split('/')[0]))\n const hasSingleRoot = roots.size === 1 && names.every((name) => name.includes('/'))\n const base = zip.name.replace(/\\.zip$/i, '')\n\n const extractedFiles: File[] = []\n const skippedLargeFiles: string[] = []\n for (const name of names) {\n const entry = entries[name]\n if (!SUPPORTED_EXTENSIONS.has(extensionOf(name))) continue\n const fileName = name.split('/').pop() ?? name\n if (entry.size > maxFileSize) {\n skippedLargeFiles.push(fileName)\n continue\n }\n const file = new File([await entry.arrayBuffer()], fileName, {\n type: mimeFromName(fileName) ?? 'application/octet-stream',\n lastModified: entry.lastModDate?.getTime() ?? Date.now(),\n })\n extractedFiles.push(withRelativePath(file, hasSingleRoot ? name : `${base}/${name}`))\n }\n return { extractedFiles, skippedLargeFiles }\n}\n\n/**\n * The chosen files an upload takes (zip archives opened into theirs), sorted by path, and those it\n * refuses with why.\n */\nexport async function prepareUploadFiles(\n chosen: ArrayLike<File>,\n options: { maxFileSize?: number; extractZip?: ZipExtractor } = {}\n): Promise<{ accepted: File[]; refused: RefusedUploadFile[] }> {\n const maxFileSize = options.maxFileSize ?? UPLOAD_MAX_FILE_SIZE\n const extractZip = options.extractZip ?? extractZipFile\n const accepted: File[] = []\n const refused: RefusedUploadFile[] = []\n const zips: File[] = []\n\n for (const file of Array.from(chosen)) {\n if (isZipFile(file)) {\n // An archive has no size limit: its files are checked one by one.\n zips.push(file)\n continue\n }\n const extension = extensionOf(file.name)\n if (file.size === 0) refused.push({ name: file.name, reason: 'empty' })\n else if (file.size > maxFileSize) refused.push({ name: file.name, reason: 'too_large' })\n else if (!extension) refused.push({ name: file.name, reason: 'no_extension' })\n else if (!SUPPORTED_TYPES.has(file.type) && !SUPPORTED_EXTENSIONS.has(extension))\n refused.push({ name: file.name, reason: 'unsupported' })\n else accepted.push(file)\n }\n\n for (const zip of zips) {\n try {\n const { extractedFiles, skippedLargeFiles } = await extractZip(zip, maxFileSize)\n for (const name of skippedLargeFiles)\n refused.push({ name: `${name} (from ${zip.name})`, reason: 'too_large' })\n if (extractedFiles.length === 0 && skippedLargeFiles.length === 0)\n refused.push({ name: zip.name, reason: 'empty_zip' })\n accepted.push(...extractedFiles)\n } catch {\n refused.push({ name: zip.name, reason: 'zip_error' })\n }\n }\n\n // Sorted by path, for a predictable (e-discovery) order.\n accepted.sort((a, b) =>\n (a.webkitRelativePath || a.name)\n .toLowerCase()\n .localeCompare((b.webkitRelativePath || b.name).toLowerCase())\n )\n return { accepted, refused }\n}\n\nfunction readDirectory(directory: FileSystemDirectoryEntry, path: string, into: File[]) {\n return new Promise<void>((resolve) => {\n const reader = directory.createReader()\n const readBatch = () =>\n reader.readEntries(async (entries) => {\n if (entries.length === 0) return resolve()\n await Promise.all(\n entries.map((entry) =>\n entry.isFile\n ? new Promise<void>((done) =>\n (entry as FileSystemFileEntry).file(\n (file) => {\n into.push(withRelativePath(file, `${path}/${file.name}`))\n done()\n },\n () => done()\n )\n )\n : entry.isDirectory\n ? readDirectory(entry as FileSystemDirectoryEntry, `${path}/${entry.name}`, into)\n : Promise.resolve()\n )\n )\n // A directory reader hands entries over in batches: read until it returns none.\n readBatch()\n })\n readBatch()\n })\n}\n\n/** The files of a drop: dropped folders are read whole, each file keeping its path. */\nexport async function filesFromDrop(transfer: DataTransfer): Promise<File[]> {\n const items = Array.from(transfer.items ?? [])\n if (items.length === 0) return Array.from(transfer.files ?? [])\n const files: File[] = []\n const folders: Promise<void>[] = []\n for (const item of items) {\n if (item.kind !== 'file') continue\n const entry = item.webkitGetAsEntry?.()\n if (entry?.isDirectory) {\n folders.push(readDirectory(entry as FileSystemDirectoryEntry, entry.name, files))\n } else {\n const file = item.getAsFile()\n if (file) files.push(file)\n }\n }\n await Promise.all(folders)\n return files\n}\n\n/**\n * The folder a file goes to: `base` (where the upload was started), then the folders the file sat\n * in below what was dropped or picked. Null at the workspace root.\n */\nexport function uploadFolderOf(file: File, base?: string | null): string | null {\n const relative = file.webkitRelativePath\n const slash = relative ? relative.lastIndexOf('/') : -1\n const own = slash > 0 ? relative.slice(0, slash) : ''\n return sanitizeFolderPath([base, own].filter(Boolean).join('/')) || null\n}\n","/**\n * Upload chosen files to the open workspace, with progress. Files go in batches (one per folder\n * they land in, at most 100 files each, four at a time); each file keeps the folder it sat in below\n * where the upload started. With direct upload on in the user's settings, and the workspace key\n * held here, files are encrypted here and sent straight to storage; otherwise through the server.\n * The new documents join their list in their folder; the labels asked for fill their AI fields.\n */\n\nimport { useCallback } from 'react'\nimport { useQueryClient } from '@tanstack/react-query'\nimport { documents as documentOps } from '@arbidocs/sdk/browser'\nimport { useArbi } from '../useArbi'\nimport { arbiQueryKeys } from '../hooks'\nimport { useUserSettings } from '../account/settings'\nimport { patchDocuments } from './documents-cache'\nimport { refreshDocuments } from './documents-data'\nimport { useGenerateDocTags } from './documents-writes'\nimport { useDocumentsSupport } from './support'\nimport { uploadFolderOf } from './upload-files'\n\nconst { mimeFromName } = documentOps\n\nconst BATCH_SIZE = 100\nconst CONCURRENT_BATCHES = 4\n\nexport interface UploadFilesInput {\n files: File[]\n /** Upload to this member workspace instead of the currently open workspace. */\n workspaceExtId?: string\n /** Where the upload started (a folder path); null or absent: the workspace root. */\n folder?: string | null\n shared: boolean\n configExtId?: string | null\n /** Labels whose AI fields are filled on the new documents. */\n generateTagIds?: string[]\n}\n\nexport interface UploadFilesProgress {\n loaded: number\n total: number\n /** Share of the files sent (one on the wire counts by its bytes sent); it never goes back. */\n percentage: number\n /** Batches done of all, when there is more than one. */\n batches: { current: number; total: number } | null\n}\n\nexport interface UploadFilesResult {\n docIds: string[]\n /** Files the server did not take, and why. */\n skipped: { file_name: string; reason: string }[]\n}\n\ninterface PendingFolder {\n workspaceId: string\n folder: string | null\n}\n\n// The folder of each document an upload made, until its row is read: a row announced live before\n// that (processing started) is shown in it.\nconst uploadedFolders = new Map<string, PendingFolder>()\n\n/** The folder an upload put `docId` in, while its row has not been read yet. */\nexport function uploadedDocumentFolder(\n workspaceId: string,\n docId: string\n): string | null | undefined {\n const pending = uploadedFolders.get(docId)\n return pending?.workspaceId === workspaceId ? pending.folder : undefined\n}\n\n/** `docId`'s row was read: its folder is known. */\nexport function forgetUploadedDocumentFolder(docId: string): void {\n uploadedFolders.delete(docId)\n}\n\n/** Run `tasks` at most `limit` at a time; resolves with their results in order. */\nasync function runLimited<T>(tasks: Array<() => Promise<T>>, limit: number): Promise<T[]> {\n const results = new Array<T>(tasks.length)\n let next = 0\n const worker = async () => {\n while (next < tasks.length) {\n const index = next++\n results[index] = await tasks[index]()\n }\n }\n await Promise.all(Array.from({ length: Math.min(limit, tasks.length) }, worker))\n return results\n}\n\nexport function useUploadFiles() {\n const arbi = useArbi()\n const qc = useQueryClient()\n const { resolveWorkspaceKey } = useDocumentsSupport()\n const { data: settings } = useUserSettings()\n const { mutateAsync: generateDocTags } = useGenerateDocTags()\n const direct = settings?.use_s3_direct_upload === true\n\n return useCallback(\n async (\n input: UploadFilesInput,\n onProgress?: (progress: UploadFilesProgress) => void\n ): Promise<UploadFilesResult> => {\n const workspaceId = input.workspaceExtId ?? arbi.getWorkspaceId()\n const groups = new Map<string | null, File[]>()\n for (const file of input.files) {\n const folder = uploadFolderOf(file, input.folder)\n groups.set(folder, [...(groups.get(folder) ?? []), file])\n }\n const batches: { folder: string | null; files: File[] }[] = []\n for (const [folder, files] of groups)\n for (let i = 0; i < files.length; i += BATCH_SIZE)\n batches.push({ folder, files: files.slice(i, i + BATCH_SIZE) })\n\n // The direct upload needs the workspace key here; without it the server encrypts. The key and\n // the workspace its init and commit name are both this upload's `workspaceId`, captured now,\n // so a switch while it runs cannot move a batch (or encrypt one for another workspace).\n let workspaceKey: Uint8Array | null = null\n if (direct && workspaceId && resolveWorkspaceKey) {\n try {\n workspaceKey = await resolveWorkspaceKey(workspaceId)\n } catch {\n workspaceKey = null\n }\n }\n\n const total = input.files.reduce((sum, file) => sum + file.size, 0)\n // Per batch: the bytes sent, and how many of its files that is (a file part-sent counts by its\n // share of bytes). The bar follows the files, and with four batches on the wire it only grows.\n const loadedByBatch = new Array<number>(batches.length).fill(0)\n const filesByBatch = new Array<number>(batches.length).fill(0)\n let done = 0\n let highest = 0\n const report = () => {\n const loaded = loadedByBatch.reduce((sum, bytes) => sum + bytes, 0)\n const sent = filesByBatch.reduce((sum, files) => sum + files, 0)\n const share = input.files.length > 0 ? sent / input.files.length : 0\n highest = Math.max(highest, Math.min(Math.round(share * 100), 100))\n onProgress?.({\n loaded,\n total,\n percentage: highest,\n batches: batches.length > 1 ? { current: done, total: batches.length } : null,\n })\n }\n report()\n\n const results = await runLimited(\n batches.map(({ folder, files }, index) => async () => {\n const bytes = files.reduce((sum, file) => sum + file.size, 0)\n const throughServer = () =>\n arbi.documents.upload(files, {\n shared: input.shared,\n folder: folder ?? undefined,\n configExtId: input.configExtId ?? undefined,\n // Named even when it is the open one: batches sent after a switch stay in this workspace.\n workspaceExtId: workspaceId,\n // One request for the batch: its files count by the share of its bytes sent.\n onProgress: (loaded) => {\n loadedByBatch[index] = Math.min(loaded, bytes)\n filesByBatch[index] = bytes > 0 ? (loadedByBatch[index] / bytes) * files.length : 0\n report()\n },\n })\n // One PUT per file: how much of each has gone.\n const fileShares = new Array<number>(files.length).fill(0)\n const directly = async (key: Uint8Array, workspace: string) =>\n arbi.documents.uploadDirect(\n workspace,\n key,\n await Promise.all(\n files.map(async (file) => ({\n name: file.name,\n data: new Uint8Array(await file.arrayBuffer()),\n contentType: file.type || mimeFromName(file.name),\n }))\n ),\n {\n shared: input.shared,\n folder: folder ?? undefined,\n configExtId: input.configExtId ?? undefined,\n // Per file, in ciphertext bytes: that file's share sent, scaled back to its own\n // size so the byte total stays true.\n onBytesProgress: ({ fileIndex, loaded, total: sent }) => {\n const share = sent > 0 ? Math.min(loaded / sent, 1) : 0\n fileShares[fileIndex] = Math.max(fileShares[fileIndex] ?? 0, share)\n loadedByBatch[index] = Math.round(\n files.reduce((sum, file, i) => sum + (fileShares[i] ?? 0) * file.size, 0)\n )\n filesByBatch[index] = fileShares.reduce((sum, part) => sum + part, 0)\n report()\n },\n }\n )\n const result =\n workspaceKey && workspaceId\n ? await directly(workspaceKey, workspaceId)\n : await throughServer()\n const docIds = result.doc_ext_ids ?? []\n if (docIds.length > 0) {\n for (const docId of docIds) uploadedFolders.set(docId, { workspaceId, folder })\n const made = new Set(docIds)\n patchDocuments(\n qc,\n (rows) => rows.map((doc) => (made.has(doc.external_id) ? { ...doc, folder } : doc)),\n workspaceId\n )\n }\n loadedByBatch[index] = bytes\n filesByBatch[index] = files.length\n done += 1\n report()\n return result\n }),\n CONCURRENT_BATCHES\n )\n\n const docIds = results.flatMap((result) => result.doc_ext_ids ?? [])\n const skipped = results.flatMap((result) => result.skipped ?? [])\n if (docIds.length > 0) {\n const read = await refreshDocuments(qc, arbi, docIds)\n for (const doc of read) forgetUploadedDocumentFolder(doc.external_id)\n }\n await qc.invalidateQueries({ queryKey: arbiQueryKeys.workspaces() })\n if (docIds.length > 0 && input.generateTagIds?.length) {\n // The upload stands even when filling the AI fields could not start.\n await generateDocTags({ tagIds: input.generateTagIds, docIds, overwrite: false }).catch(\n () => undefined\n )\n }\n return { docIds, skipped }\n },\n [arbi, qc, direct, resolveWorkspaceKey, generateDocTags]\n )\n}\n","/**\n * Add documents from web addresses to a workspace (default: the one open when it is called, named on\n * the request so a switch while a zip archive is fetched cannot move them). A zip archive's address is fetched here\n * and opened into its files, handed back to be uploaded like chosen files (the server cannot open\n * one); every other address is fetched by the server.\n */\n\nimport { useCallback } from 'react'\nimport { useArbi } from '../useArbi'\nimport { useUploadUrls } from './documents-writes'\nimport { useDocumentsSupport } from './support'\nimport { extractZipFile, UPLOAD_MAX_FILE_SIZE } from './upload-files'\n\nexport interface UploadFromUrlsInput {\n urls: string[]\n shared: boolean\n configExtId?: string | null\n /** The workspace the documents go to. Default: the one open when this is called. */\n workspaceId?: string | null\n}\n\nexport interface UploadFromUrlsResult {\n /** The documents the server made. */\n docIds: string[]\n /** Addresses the server did not take, and why. */\n skipped: { file_name: string; reason: string }[]\n /** The files of the zip archives, to upload like chosen files. */\n zipFiles: File[]\n /** Files inside the archives too large to take. */\n oversizedInZips: string[]\n /** Archive addresses that could not be fetched or opened. */\n failedZipUrls: string[]\n}\n\nfunction isZipUrl(url: string): boolean {\n try {\n return new URL(url).pathname.toLowerCase().endsWith('.zip')\n } catch {\n return url.toLowerCase().endsWith('.zip')\n }\n}\n\nexport function useUploadFromUrls() {\n const arbi = useArbi()\n const { mutateAsync: uploadUrls } = useUploadUrls()\n const { extractZip = extractZipFile } = useDocumentsSupport()\n return useCallback(\n async ({\n urls,\n shared,\n configExtId,\n workspaceId: named,\n }: UploadFromUrlsInput): Promise<UploadFromUrlsResult> => {\n const workspaceId = named ?? arbi.getWorkspaceId()\n const zipUrls = urls.filter(isZipUrl)\n const others = urls.filter((url) => !isZipUrl(url))\n const zipFiles: File[] = []\n const oversizedInZips: string[] = []\n const failedZipUrls: string[] = []\n await Promise.all(\n zipUrls.map(async (url) => {\n try {\n const response = await fetch(url)\n if (!response.ok) throw new Error(`HTTP ${response.status}`)\n const name =\n decodeURIComponent(new URL(url).pathname.split('/').pop() || '') || 'archive.zip'\n const zip = new File([await response.blob()], name, { type: 'application/zip' })\n const { extractedFiles, skippedLargeFiles } = await extractZip(\n zip,\n UPLOAD_MAX_FILE_SIZE\n )\n zipFiles.push(...extractedFiles)\n oversizedInZips.push(...skippedLargeFiles)\n } catch {\n failedZipUrls.push(url)\n }\n })\n )\n const result = others.length\n ? ((await uploadUrls({ urls: others, shared, configExtId, workspaceId })) as {\n doc_ext_ids?: string[]\n skipped?: { file_name: string; reason: string }[]\n })\n : {}\n return {\n docIds: result.doc_ext_ids ?? [],\n skipped: result.skipped ?? [],\n zipFiles,\n oversizedInZips,\n failedZipUrls,\n }\n },\n [arbi, uploadUrls, extractZip]\n )\n}\n","/**\n * The documents related to each document of a workspace. It computes a map of related documents for each document in the workspace.\n * Relationships include:\n * - Email family: parent/child via parent_ext_id (an attachment and its email, a message and its\n * mailbox archive). Versions are NOT relations: they live inside their document.\n * - Made from: derivations (a crop's source image, a redline's inputs, a redacted copy's original,\n * a production's documents) from `derived_from`, with the source version when it is not the\n * current one; and the other way round, the copies made from a document\n * - Exact duplicates (same content_hash / fingerprint)\n * - Near-duplicates (from similarity API)\n *\n * Returns a stable Map<docExtId, RelatedDocs> recomputed only when\n * the documents array or similarity data changes.\n */\n\nimport { useMemo, useRef } from 'react'\nimport type { WorkspaceDocument } from './documents-cache'\nimport { SIMILARITY_THRESHOLD, useSimilarDocuments } from './documents-data'\n\nexport interface RelatedDocs<D extends WorkspaceDocument = WorkspaceDocument> {\n /** The email / mailbox archive this document was extracted from. */\n parent?: D\n /** Attachments: documents extracted from this one. */\n children: D[]\n /** Documents this one was made from (crop, redline, redacted copy); not the previous version. */\n madeFrom: D[]\n /** Documents made from this one (a redacted or annotated copy, a production, a crop). */\n copies: D[]\n /** How each made-from / copy document is related, by its id (a `derived_from` role). */\n roles: Record<string, string>\n /**\n * The version of a made-from document this one was made from, by its id — only when that is\n * not the source's current version (the copy was made from an older version).\n */\n versions?: Record<string, number>\n duplicates: D[]\n similar: Array<{ doc: D; similarity: number }>\n}\n\nexport type RelatedDocsMap<D extends WorkspaceDocument = WorkspaceDocument> = Map<\n string,\n RelatedDocs<D>\n>\n\n/** Count total related documents for a given entry */\nexport function getRelatedTotal(related: RelatedDocs<WorkspaceDocument>): number {\n return (\n (related.parent ? 1 : 0) +\n related.children.length +\n related.madeFrom.length +\n related.copies.length +\n related.duplicates.length +\n related.similar.length\n )\n}\n\n/** Build human-readable count labels per relationship type */\nexport function getRelatedLabels(related: RelatedDocs<WorkspaceDocument>): string[] {\n const parts: string[] = []\n if (related.parent) parts.push('1 parent')\n if (related.children.length > 0) {\n const n = related.children.length\n parts.push(`${n} ${n === 1 ? 'attachment' : 'attachments'}`)\n }\n if (related.madeFrom.length > 0) parts.push(`made from ${related.madeFrom.length}`)\n if (related.copies.length > 0) {\n const n = related.copies.length\n parts.push(`${n} ${n === 1 ? 'copy' : 'copies'}`)\n }\n if (related.duplicates.length > 0) {\n const n = related.duplicates.length\n parts.push(`${n} ${n === 1 ? 'duplicate' : 'duplicates'}`)\n }\n if (related.similar.length > 0) {\n const n = related.similar.length\n parts.push(`${n} similar`)\n }\n return parts\n}\n\n/**\n * Computes related documents map from workspace documents and similarity API.\n * Call this in a component that has access to the documents array.\n */\nexport function useRelatedDocuments<D extends WorkspaceDocument>(\n documents: D[]\n): RelatedDocsMap<D> {\n const { data: similarData } = useSimilarDocuments()\n\n // Structural fingerprint — only recompute when fields that affect relationships change.\n // Metadata-only changes (title rename, tag toggle, status update) produce the same\n // fingerprint and skip the expensive map rebuild.\n const structuralKey = useMemo(() => {\n const parts: string[] = []\n for (const doc of documents) {\n parts.push(doc.external_id)\n parts.push(doc.parent_ext_id || '')\n parts.push(doc.content_hash || '')\n parts.push(String(doc.current_version ?? 1))\n for (const source of doc.derived_from ?? [])\n parts.push(source.doc_ext_id, source.role, String(source.version ?? ''))\n }\n return parts.join('|')\n }, [documents])\n\n const prevKeyRef = useRef(structuralKey)\n const prevMapRef = useRef<RelatedDocsMap<D>>(new Map())\n // Also track documents ref so we rebuild map with fresh Doc objects when structure changes\n const prevDocsRef = useRef(documents)\n const prevSimilarRef = useRef(similarData)\n\n return useMemo(() => {\n // If nothing that affects relationships has changed, reuse the previous result.\n // Must also check similarData — it arrives async after the initial build.\n if (\n prevKeyRef.current === structuralKey &&\n prevSimilarRef.current === similarData &&\n prevMapRef.current.size > 0 &&\n prevDocsRef.current === documents\n ) {\n return prevMapRef.current\n }\n prevKeyRef.current = structuralKey\n prevDocsRef.current = documents\n prevSimilarRef.current = similarData\n const map = new Map<string, RelatedDocs<D>>()\n\n const getOrCreate = (docId: string): RelatedDocs<D> => {\n let entry = map.get(docId)\n if (!entry) {\n entry = { children: [], madeFrom: [], copies: [], roles: {}, duplicates: [], similar: [] }\n map.set(docId, entry)\n }\n return entry\n }\n\n // Index documents by ID for O(1) lookups\n const docById = new Map<string, D>()\n for (const doc of documents) {\n docById.set(doc.external_id, doc)\n }\n\n // Build content_hash index for exact duplicate detection\n const byHash = new Map<string, D[]>()\n for (const doc of documents) {\n if (doc.content_hash) {\n const list = byHash.get(doc.content_hash) || []\n list.push(doc)\n byHash.set(doc.content_hash, list)\n }\n }\n\n // Parent/child relationships\n for (const doc of documents) {\n if (doc.parent_ext_id) {\n const parent = docById.get(doc.parent_ext_id)\n if (parent) {\n getOrCreate(doc.external_id).parent = parent\n getOrCreate(parent.external_id).children.push(doc)\n }\n }\n }\n\n // Made from / copies — derivations of separate documents (versions live inside a document).\n for (const doc of documents) {\n for (const source of doc.derived_from ?? []) {\n const from = docById.get(source.doc_ext_id)\n if (!from) continue\n const made = getOrCreate(doc.external_id)\n made.madeFrom.push(from)\n made.roles[from.external_id] = source.role\n if (source.version && source.version !== (from.current_version ?? 1)) {\n made.versions = { ...made.versions, [from.external_id]: source.version }\n }\n const original = getOrCreate(from.external_id)\n original.copies.push(doc)\n original.roles[doc.external_id] = source.role\n }\n }\n\n // Exact duplicates — same content_hash, excluding self\n for (const [, docs] of byHash) {\n if (docs.length > 1) {\n for (const doc of docs) {\n getOrCreate(doc.external_id).duplicates = docs.filter(\n (d) => d.external_id !== doc.external_id\n )\n }\n }\n }\n\n // Near-duplicates from similarity API\n // Only include pairs with SIMILARITY_THRESHOLD ≤ similarity < 1.0\n // (1.0 exact matches are already in duplicates above)\n if (similarData?.pairs) {\n for (const pair of similarData.pairs) {\n if (pair.similarity < SIMILARITY_THRESHOLD || pair.similarity >= 1.0) continue\n const docA = docById.get(pair.doc_a.external_id)\n const docB = docById.get(pair.doc_b.external_id)\n if (docA && docB) {\n getOrCreate(docA.external_id).similar.push({\n doc: docB,\n similarity: pair.similarity,\n })\n getOrCreate(docB.external_id).similar.push({\n doc: docA,\n similarity: pair.similarity,\n })\n }\n }\n }\n\n prevMapRef.current = map\n return map\n }, [documents, similarData, structuralKey])\n}\n","/**\n * Offline writes that survive a reload — opt in. A mutation made while offline pauses and is sent on\n * reconnect; a host that also persists its query cache (`@tanstack/react-query-persist-client`)\n * keeps the paused write across a reload, but the restored mutation has lost its function. Call\n * {@link registerArbiMutationDefaults} once on the query client, before the persisted cache is\n * restored and `resumePausedMutations()` runs: it gives each replayable package write its request\n * back (on a bare client: the hook's `Arbi` may not exist yet) and what its success does to the\n * cache. {@link isReplayableArbiMutation} says which writes those are, for a host's\n * `shouldDehydrateMutation` and its pending-changes list.\n *\n * Replayable: creating a tag (`useCreateTag`), editing documents' fields (`useUpdateDocuments`),\n * and applying, removing or re-noting a tag on documents (`useAssignDocTags`, `useRemoveDocTags`,\n * `useUpdateDocTag`). Each keeps the workspace it was made in and is replayed there\n * (`queued-writes.ts`), whichever workspace is open after the reload.\n */\n\nimport type { MutationKey, QueryClient, QueryKey } from '@tanstack/react-query'\nimport { partialMatchKey } from '@tanstack/react-query'\nimport type { ArbiClient } from '@arbidocs/client'\nimport { replayableTagMutations } from './tags'\nimport { replayableDocumentMutations } from './documents/documents-writes'\nimport { FINISHED_DOCUMENT_STATUSES } from './documents/documents-data'\nimport { QUEUED_WRITE_RETRY } from './queued-writes'\n\ninterface ReplayableMutation {\n mutationKey: MutationKey\n // Each entry types its own variables and result; the registry only passes them through.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n run: (client: ArbiClient, variables: any) => Promise<unknown>\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n settle: (qc: QueryClient, data: any, variables: any) => unknown\n}\n\nconst REPLAYABLE: readonly ReplayableMutation[] = [\n ...replayableTagMutations,\n ...replayableDocumentMutations,\n]\n\n/** Whether a mutation is a package write that can be queued offline and replayed after a reload. */\nexport function isReplayableArbiMutation(mutationKey: MutationKey | undefined): boolean {\n return !!mutationKey && REPLAYABLE.some((m) => partialMatchKey(mutationKey, m.mutationKey))\n}\n\n/**\n * Re-supply the replayable package writes on `queryClient` (see the module comment). `client` is\n * the host's API client, read when a restored write is sent.\n */\nexport function registerArbiMutationDefaults(\n queryClient: QueryClient,\n client: () => ArbiClient\n): void {\n for (const m of REPLAYABLE) {\n queryClient.setMutationDefaults(m.mutationKey, {\n // Each write is sent in the workspace it was made in (kept in its variables), never in the\n // one open when it is replayed; one whose workspace can't be opened is tried again, then\n // kept as not sent.\n mutationFn: (variables: unknown) => m.run(client(), variables),\n onSuccess: (data: unknown, variables: unknown) => m.settle(queryClient, data, variables),\n ...QUEUED_WRITE_RETRY,\n })\n }\n}\n\n/** The package query families holding document metadata (never content). */\nconst DOCUMENT_FAMILIES = [\n 'documents',\n 'document',\n 'documentsById',\n 'documentVersions',\n 'similarDocuments',\n]\n\n/**\n * The package query families a host may persist for an offline start. The entitlements too: the\n * paid pages (Mail, Calendar) open only once they are known, so without them a reopened tab offline\n * showed an empty page instead of the mailbox and Outbox kept on this device.\n */\nconst OFFLINE_READABLE = [\n ...DOCUMENT_FAMILIES,\n 'workspaces',\n 'userSettings',\n 'projects',\n 'entitlements',\n]\n\n/**\n * Whether a package query is worth persisting for an offline start (a host's\n * `shouldDehydrateQuery`): the documents lists, documents, their versions and near-duplicate\n * pairs (metadata, never a document's content), the workspace list (its keys stay wrapped), the\n * user settings, the projects and the entitlements.\n */\nexport function isOfflineReadableArbiQuery(queryKey: QueryKey): boolean {\n return queryKey[0] === 'arbi' && OFFLINE_READABLE.includes(queryKey[1] as string)\n}\n\n/**\n * Whether a persisted package query may be restored when the app starts online. Not a documents\n * list (it is never re-read on its own, so a stale copy would be trusted all session: it loads\n * fresh instead), nor a document saved while still processing (its saved freshness would keep it\n * \"processing\" with no re-read), nor the entitlements (kept for an offline start only: online they\n * are read fresh, so a plan bought since shows at once). The other families (the workspace list,\n * the settings) always. Offline, everything persisted is restored.\n */\nexport function isRestorableArbiQueryOnline(queryKey: QueryKey, data: unknown): boolean {\n if (queryKey[0] !== 'arbi') return true\n if (queryKey[1] === 'documents' || queryKey[1] === 'entitlements') return false\n if (!DOCUMENT_FAMILIES.includes(queryKey[1] as string)) return true\n const docs = Array.isArray(data) ? data : [data]\n return !docs.some((doc) => {\n const status = (doc as { status?: string | null } | null)?.status\n return !!status && !FINISHED_DOCUMENT_STATUSES.has(status)\n })\n}\n","/**\n * Changes made offline that wait to sync: the documents' writes held back by React Query while\n * offline (paused mutations, persisted by the host's query persister) or that failed when they\n * were replayed. What changed and where (`usePendingSyncItems`), how many (`usePendingSyncCounts`),\n * whether a document has one (`useDocumentPendingSync`), and undoing them before they reach the\n * server (`useCancelManyPendingSync`). These only read the mutation cache (plus the explicit\n * undo), so they never change how online writes behave.\n */\n\nimport { useCallback, useMemo, useState } from 'react'\nimport {\n partialMatchKey,\n useMutationState,\n useQueryClient,\n type Mutation,\n type MutationKey,\n type QueryClient,\n} from '@tanstack/react-query'\nimport { create } from 'zustand'\nimport { arbiMutationKeys } from '../query-keys'\nimport { isReplayableArbiMutation } from '../offline'\nimport { useTags } from '../hooks'\nimport { getDocumentTitle } from '../entities'\nimport { useDocuments } from './documents-data'\nimport {\n rollbackOptimisticDocumentEdit,\n type AssignDocTagsInput,\n type OptimisticDocumentEdit,\n type UpdateDocTagInput,\n type UpdateDocumentsInput,\n} from './documents-writes'\nimport type { CreateTagInput } from '../tags'\nimport type { WorkspaceDocument } from './documents-cache'\nimport { QUEUED_WRITE_BLOCKED_MESSAGE, isBlockedOnWorkspace } from '../queued-writes'\n\ntype PendingStatus = 'queued' | 'syncing' | 'error'\n\nexport interface PendingSyncItem {\n mutationId: number\n /** Affected document name(s) — resolved, e.g. \"Exhibit R-007\". */\n document: string\n /** The exact change, in plain words — e.g. \"Moved to Contracts\", \"Title → \\\"X\\\"\". */\n change: string\n status: PendingStatus\n /** When the change was made (ms epoch). */\n at: number\n docIds: string[]\n /** Why it is held back, when it is: its workspace can't be opened, so it was not sent. */\n notice?: string\n}\n\n/** Doc-metadata sub-fields the table can edit, with their display labels. */\nconst META_LABELS: Record<string, string> = {\n title: 'Title',\n doc_date: 'Date',\n doc_nature: 'Type',\n doc_author: 'Author',\n doc_subject: 'Abstract',\n}\n\n/** Which queued write a pending change is. */\ntype PendingKind = 'fields' | 'assignTag' | 'removeTag' | 'noteTag' | 'createTag'\n\nconst KIND_BY_KEY: ReadonlyArray<readonly [MutationKey, PendingKind]> = [\n [arbiMutationKeys.updateDocuments(), 'fields'],\n [arbiMutationKeys.assignDocTags(), 'assignTag'],\n [arbiMutationKeys.removeDocTags(), 'removeTag'],\n [arbiMutationKeys.updateDocTag(), 'noteTag'],\n [arbiMutationKeys.createTag(), 'createTag'],\n]\n\nfunction kindOf(mutationKey: MutationKey | undefined): PendingKind | undefined {\n return mutationKey\n ? KIND_BY_KEY.find(([key]) => partialMatchKey(mutationKey, key))?.[1]\n : undefined\n}\n\n/** The raw projection pulled out of each pending mutation, before enrichment. */\nexport interface RawPending {\n mutationId: number\n kind: PendingKind\n variables: unknown\n context: unknown\n status: PendingStatus\n at: number\n /** Not sent because its workspace can't be opened (retried, then kept). */\n blocked?: boolean\n}\n\nfunction statusOf(isPaused: boolean, status: string, blocked = false): PendingStatus {\n if (status === 'error') return 'error'\n return isPaused || blocked ? 'queued' : 'syncing'\n}\n\n/** Pull the affected document ext_ids out of a mutation's input. */\nfunction docIdsFromVariables(kind: PendingKind | undefined, variables: unknown): string[] {\n if (kind === 'fields')\n return ((variables as UpdateDocumentsInput | undefined)?.documents ?? []).map(\n (d) => d.external_id\n )\n if (kind === 'assignTag' || kind === 'removeTag')\n return (variables as AssignDocTagsInput | undefined)?.docIds ?? []\n if (kind === 'noteTag') {\n const docId = (variables as UpdateDocTagInput | undefined)?.docId\n return docId ? [docId] : []\n }\n return []\n}\n\n/** Map of docId → the pre-edit document, from a mutation's rollback snapshot. */\nfunction prevDocsFrom(context: unknown): Map<string, WorkspaceDocument> {\n const edit = context as OptimisticDocumentEdit | undefined\n if (!edit?.optimistic) return new Map()\n return new Map(edit.previous.map((doc) => [doc.external_id, doc]))\n}\n\n/** Describe a single document-field edit by diffing the new values vs the snapshot. */\nfunction describeDocEdit(variables: unknown, context: unknown): string {\n const first = (variables as UpdateDocumentsInput | undefined)?.documents?.[0] as\n Record<string, unknown> | undefined\n if (!first) return 'Edited document'\n const prevDocs = prevDocsFrom(context)\n\n // Top-level fields carry the value directly.\n if ('folder' in first) {\n const folder = (first.folder as string | null) ?? null\n return folder ? `Moved to ${folder}` : 'Removed from folder'\n }\n if ('shared' in first) return first.shared ? 'Shared in chat' : 'Removed from chat'\n if ('labels' in first) return 'Changed labels'\n\n // doc_metadata edits: diff against the pre-edit snapshot to name the field(s).\n if ('doc_metadata' in first) {\n const nextMeta = (first.doc_metadata ?? {}) as Record<string, unknown>\n const prevMeta = (prevDocs.get(first.external_id as string)?.doc_metadata ?? {}) as Record<\n string,\n unknown\n >\n const changed: string[] = []\n for (const [key, label] of Object.entries(META_LABELS)) {\n const next = nextMeta[key] ?? ''\n const prev = prevMeta[key] ?? ''\n if (String(next) === String(prev)) continue\n changed.push(next ? `${label} → “${String(next)}”` : `${label} cleared`)\n }\n if (changed.length > 0) return changed.join(', ')\n return 'Edited details'\n }\n return 'Edited document'\n}\n\nconst TAG_VERBS: Partial<Record<PendingKind, string>> = {\n assignTag: 'Applied',\n removeTag: 'Removed',\n noteTag: 'Edited the note on',\n}\n\n/** A human change summary for one pending mutation. */\nfunction describeChange(raw: RawPending, tagNameById: Map<string, string>): string {\n const { kind, variables, context } = raw\n const verb = TAG_VERBS[kind]\n if (verb) {\n const tagId = (variables as { tagId?: string } | undefined)?.tagId\n const tagName = tagId ? tagNameById.get(tagId) : undefined\n return tagName ? `${verb} tag “${tagName}”` : `${verb} a tag`\n }\n if (kind === 'createTag') {\n const name = (variables as CreateTagInput | undefined)?.name\n return name ? `Created tag “${name}”` : 'Created a tag'\n }\n return describeDocEdit(variables, context)\n}\n\n/**\n * Pure enrichment: turn one raw pending mutation into a display item, resolving\n * the document name(s) and change summary from the supplied maps. Exported for\n * direct unit testing (the bug-prone part is name/change resolution, not the\n * thin useMutationState wiring around it).\n */\nexport function buildPendingSyncItem(\n raw: RawPending,\n docNameById: Map<string, string>,\n tagNameById: Map<string, string>\n): PendingSyncItem {\n const docIds = docIdsFromVariables(raw.kind, raw.variables)\n const names = docIds.map((id) => docNameById.get(id)).filter(Boolean) as string[]\n const document =\n raw.kind === 'createTag'\n ? 'Workspace labels'\n : names.length > 0\n ? names.join(', ')\n : docIds.length > 1\n ? `${docIds.length} documents`\n : 'A document'\n return {\n mutationId: raw.mutationId,\n document,\n change: describeChange(raw, tagNameById),\n status: raw.status,\n at: raw.at,\n docIds,\n ...(raw.blocked ? { notice: QUEUED_WRITE_BLOCKED_MESSAGE } : {}),\n }\n}\n\nexport const PENDING_SYNC_PREDICATE = (m: Mutation): boolean =>\n // Only real offline EDITS belong in the queue. An incidental paused mutation\n // (e.g. POST /v1/workspace/{id}/open fired on an offline cold-boot) is not a\n // user \"change\" and must not show as a phantom pending item.\n //\n // Gated on offline: a mutation only `isPaused` when React Query holds it back\n // for being offline, so this is the natural \"offline mode\" gate. We\n // deliberately do NOT count a plain in-flight (`status === 'pending'`) edit —\n // that's just a normal ONLINE save mid-request, and counting it made rows\n // flash \"pending/syncing\" while fully online. `error` is kept so a failed\n // sync stays visible to review/undo.\n // A write held back because its workspace can't be opened (tried again meanwhile) is waiting too.\n isReplayableArbiMutation(m.options.mutationKey) &&\n (m.state.isPaused || m.state.status === 'error' || isBlockedOnWorkspace(m))\n\n/**\n * Full, enriched list of unsynced writes for the offline-changes modal — newest\n * last, each with a resolved document name, the exact change, and a timestamp.\n * Resolves names from the live document + tag caches (reactively, so they fill\n * in as those load — unlike a one-shot cache read).\n */\nexport function usePendingSyncItems(): PendingSyncItem[] {\n const { data: documents } = useDocuments()\n const { data: tags } = useTags()\n\n const raw = useMutationState<RawPending>({\n filters: { predicate: PENDING_SYNC_PREDICATE },\n select: (m) => ({\n mutationId: m.mutationId,\n kind: kindOf(m.options.mutationKey) ?? 'fields',\n variables: m.state.variables,\n context: m.state.context,\n status: statusOf(m.state.isPaused, m.state.status, isBlockedOnWorkspace(m)),\n at: m.state.submittedAt,\n blocked: isBlockedOnWorkspace(m),\n }),\n })\n\n return useMemo(() => {\n const docNameById = new Map<string, string>()\n for (const doc of documents ?? [])\n docNameById.set(doc.external_id, getDocumentTitle(doc, doc.file_name ?? ''))\n const tagNameById = new Map<string, string>()\n for (const tag of tags ?? []) tagNameById.set(tag.external_id, tag.name)\n\n return raw.map((r) => buildPendingSyncItem(r, docNameById, tagNameById))\n }, [raw, documents, tags])\n}\n\n/** Cheap counts for the sidebar badge — no name resolution. */\nexport function usePendingSyncCounts(): { pending: number; failed: number } {\n const statuses = useMutationState({\n filters: { predicate: PENDING_SYNC_PREDICATE },\n select: (m) => (m.state.status === 'error' ? 'error' : 'pending'),\n })\n return useMemo(\n () => ({ pending: statuses.length, failed: statuses.filter((s) => s === 'error').length }),\n [statuses]\n )\n}\n\n/**\n * Cancel many changes at once. Rolls back newest-first so layered edits to the\n * same doc restore in LIFO order (matching how they'd replay). Only undoable\n * (queued/failed) mutations are touched — anything already syncing is left alone.\n */\nexport function useCancelManyPendingSync(): (mutationIds: number[]) => void {\n const queryClient = useQueryClient()\n return useCallback(\n (mutationIds) => {\n const wanted = new Set(mutationIds)\n const cache = queryClient.getMutationCache()\n const undoable = cache\n .getAll()\n .filter((m) => wanted.has(m.mutationId) && (m.state.isPaused || m.state.status === 'error'))\n .sort((a, b) => b.state.submittedAt - a.state.submittedAt)\n for (const mutation of undoable) {\n rollbackOptimisticDocumentEdit(queryClient, mutation.state.context)\n cache.remove(mutation)\n }\n },\n [queryClient]\n )\n}\n\n/** The documents with a change waiting to sync, kept from one watch of each query client. */\nconst usePendingDocIds = create<{ ids: ReadonlySet<string> }>(() => ({ ids: new Set() }))\nconst watched = new WeakSet<QueryClient>()\n\nfunction sameSet(a: ReadonlySet<string>, b: ReadonlySet<string>): boolean {\n if (a.size !== b.size) return false\n for (const v of a) if (!b.has(v)) return false\n return true\n}\n\n/**\n * Watch a query client's mutation cache once, keeping the set of documents with a pending change:\n * a grid of thousands of status cells then reads one cheap boolean each instead of subscribing to\n * the mutation cache thousands of times.\n */\nfunction watchPendingDocIds(queryClient: QueryClient): void {\n if (watched.has(queryClient)) return\n watched.add(queryClient)\n const cache = queryClient.getMutationCache()\n const update = () => {\n const ids = new Set(\n cache\n .findAll({ predicate: PENDING_SYNC_PREDICATE })\n .flatMap((m) => docIdsFromVariables(kindOf(m.options.mutationKey), m.state.variables))\n )\n if (!sameSet(usePendingDocIds.getState().ids, ids)) usePendingDocIds.setState({ ids })\n }\n update()\n cache.subscribe(update)\n}\n\n/** Whether a document has a change waiting to sync (a cheap boolean, for per-row status). */\nexport function useDocumentPendingSync(docId: string | null | undefined): boolean {\n const queryClient = useQueryClient()\n useState(() => watchPendingDocIds(queryClient))\n return usePendingDocIds((s) => (docId ? s.ids.has(docId) : false))\n}\n","/**\n * Documents kept on this device (\"available offline\"): the bytes a viewer shows (the PDF, or for\n * media the stored file), so a pinned document opens with no network, and can be attached to an\n * email offline. A deliberate, user-pinned cache in IndexedDB: entries live until the user removes\n * them or signs out (`wipeOfflineDocuments`).\n *\n * The bytes are always ciphertext, sealed to the user's own key (the cache is private to one user\n * on one device). The store persists a raw `Uint8Array` (it structured-clones everywhere, unlike a\n * `Blob`); sealing and opening happen in `keepDocumentsOffline` / `loadOfflineDocument`.\n */\n\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'\nimport {\n base64ToBytes,\n bytesToBase64,\n getUserEncryptionKeypair,\n sealedBoxDecrypt,\n sealedBoxEncrypt,\n} from '@arbidocs/client'\nimport { arbiQueryKeys } from '../query-keys'\nimport { notify } from '../notifications/notify-store'\nimport { getDocumentTitle } from '../entities'\nimport { usesOriginalBytesForViewer } from '../entities/media-type'\nimport { useArbi } from '../useArbi'\nimport { fetchDocumentFile, fetchDocumentPdf } from '../document-tools/document-pdf'\nimport type { DocumentToolsClient } from '../document-tools/environment'\nimport { setCachedDocument, type WorkspaceDocument } from './documents-cache'\nimport { useDocumentsSupport } from './support'\n\nconst DB_NAME = 'arbi-offline-docs'\nconst DB_VERSION = 1\nconst STORE = 'documents'\n\nexport interface OfflineDocumentRecord {\n /** Document external id (the primary key). */\n docExtId: string\n /** Display name, captured at save time so the offline list can render without metadata. */\n fileName: string\n /**\n * Which bytes were cached: 'pdf' = the server-generated PDF preview (`/view`),\n * 'original' = the source file (`/download`, used for image/audio/video).\n */\n kind: 'pdf' | 'original'\n /** Sealed-box ciphertext (the user's personal key); decrypted on read. */\n data: Uint8Array\n /** MIME type, used to rebuild the Blob on read. */\n contentType: string\n /** Epoch ms when cached. */\n savedAt: number\n}\n\nlet dbInstance: IDBDatabase | null = null\n\nasync function openDB(): Promise<IDBDatabase> {\n if (dbInstance) return dbInstance\n\n return new Promise((resolve, reject) => {\n const request = indexedDB.open(DB_NAME, DB_VERSION)\n request.onerror = () => reject(request.error)\n request.onsuccess = () => {\n const db = request.result\n // Another tab deleting the database (a sign-out) must not be blocked by this handle.\n db.onversionchange = () => {\n db.close()\n if (dbInstance === db) dbInstance = null\n }\n dbInstance = db\n resolve(db)\n }\n request.onupgradeneeded = (event) => {\n const db = (event.target as IDBOpenDBRequest).result\n if (!db.objectStoreNames.contains(STORE)) {\n db.createObjectStore(STORE, { keyPath: 'docExtId' })\n }\n }\n })\n}\n\nfunction promisify<T>(request: IDBRequest<T>): Promise<T> {\n return new Promise((resolve, reject) => {\n request.onsuccess = () => resolve(request.result)\n request.onerror = () => reject(request.error)\n })\n}\n\n/**\n * Open a fresh transaction and run the request creator synchronously.\n *\n * The DB handle is awaited first, then the transaction is created and the\n * request issued in the same microtask — never awaiting *between* opening the\n * transaction and using it, which would let it auto-close.\n */\nasync function withStore<T>(\n mode: IDBTransactionMode,\n run: (store: IDBObjectStore) => IDBRequest<T>\n): Promise<T> {\n const db = await openDB()\n const store = db.transaction(STORE, mode).objectStore(STORE)\n return promisify(run(store))\n}\n\nasync function putOfflineDocument(record: OfflineDocumentRecord): Promise<void> {\n await withStore('readwrite', (store) => store.put(record))\n}\n\nexport async function getOfflineDocument(\n docExtId: string\n): Promise<OfflineDocumentRecord | undefined> {\n const record = await withStore('readonly', (store) => store.get(docExtId))\n return record as OfflineDocumentRecord | undefined\n}\n\nasync function deleteOfflineDocument(docExtId: string): Promise<void> {\n await withStore('readwrite', (store) => store.delete(docExtId))\n}\n\nasync function listOfflineDocumentIds(): Promise<string[]> {\n const keys = await withStore('readonly', (store) => store.getAllKeys())\n return keys as string[]\n}\n\n/**\n * Ask the browser to mark this origin's storage as persistent, so the offline\n * cache isn't evicted under disk pressure (without this, IndexedDB is\n * \"best-effort\" and can be cleared). Best-effort + idempotent; returns whether\n * storage is persisted afterwards.\n */\nexport async function requestPersistentStorage(): Promise<boolean> {\n try {\n if (!navigator.storage?.persist || !navigator.storage.persisted) return false\n if (await navigator.storage.persisted()) return true\n return await navigator.storage.persist()\n } catch {\n return false\n }\n}\n\n/** Drop every document kept on this device (signing out: nothing stays behind). */\nexport async function wipeOfflineDocuments(): Promise<void> {\n dbInstance?.close()\n dbInstance = null\n await new Promise<void>((resolve) => {\n const request = indexedDB.deleteDatabase(DB_NAME)\n request.onsuccess = request.onerror = request.onblocked = () => resolve()\n })\n}\n\n/** Open a kept document's bytes (`undefined` when it is not kept on this device). */\nexport async function loadOfflineDocument(docId: string): Promise<Blob | undefined> {\n const record = await getOfflineDocument(docId)\n if (!record) return undefined\n const keypair = await getUserEncryptionKeypair()\n if (!keypair) throw new Error('Cannot open the offline copy: no personal key in this session')\n const bytes = sealedBoxDecrypt(bytesToBase64(record.data), keypair.secretKey)\n return new Blob([bytes as BlobPart], { type: record.contentType })\n}\n\n/**\n * Keep documents on this device: fetch what the viewer shows (the PDF, or for media the stored\n * file), seal it to the user's key and store it. One at a time; a failure stops the rest.\n */\nasync function keepDocumentsOffline(\n client: DocumentToolsClient,\n docs: WorkspaceDocument[]\n): Promise<void> {\n // Ask for durable storage so the pinned copies are not evicted later.\n await requestPersistentStorage()\n const keypair = await getUserEncryptionKeypair()\n if (!keypair) throw new Error('Could not derive an encryption key for the offline copy.')\n for (const doc of docs) {\n const original = usesOriginalBytesForViewer(doc.file_name)\n const blob = original\n ? await fetchDocumentFile(client, doc.external_id)\n : await fetchDocumentPdf(client, doc.external_id)\n const plain = new Uint8Array(await blob.arrayBuffer())\n await putOfflineDocument({\n docExtId: doc.external_id,\n fileName: getDocumentTitle(doc, 'document'),\n kind: original ? 'original' : 'pdf',\n data: base64ToBytes(sealedBoxEncrypt(plain, keypair.publicKey)),\n contentType: blob.type,\n savedAt: Date.now(),\n })\n }\n}\n\n/** The documents kept on this device (a local read: it runs offline too). */\nexport function useOfflineDocumentIds(): ReadonlySet<string> {\n const { data } = useQuery({\n queryKey: arbiQueryKeys.offlineDocuments(),\n queryFn: async () => new Set(await listOfflineDocumentIds()),\n staleTime: Infinity,\n // Offline the default network mode would hold this local read back, and a cold start\n // offline would lose every \"available offline\" badge.\n networkMode: 'always',\n })\n return data ?? EMPTY\n}\nconst EMPTY: ReadonlySet<string> = new Set()\n\n/**\n * Keep documents on this device. Their metadata goes into the cache too (the persister keeps it),\n * so a pinned document never opened online still has it offline; the host may then warm its\n * viewer code (`documents.onKeptOffline`) so it opens offline as well.\n */\nexport function useKeepDocumentsOffline() {\n const queryClient = useQueryClient()\n const arbi = useArbi()\n const { onKeptOffline } = useDocumentsSupport()\n return useMutation({\n mutationFn: async (docs: WorkspaceDocument[]) => {\n await keepDocumentsOffline(arbi.getClient().fetch, docs)\n for (const doc of docs) setCachedDocument(queryClient, doc)\n await onKeptOffline?.()\n return docs.length\n },\n onSettled: () => queryClient.invalidateQueries({ queryKey: arbiQueryKeys.offlineDocuments() }),\n onSuccess: (count) =>\n notify.success(`${count} document${count === 1 ? '' : 's'} available offline`),\n onError: () => notify.error('Could not save documents for offline use'),\n })\n}\n\n/** Stop keeping documents on this device. */\nexport function useRemoveDocumentsOffline() {\n const queryClient = useQueryClient()\n return useMutation({\n mutationFn: async (docIds: string[]) => {\n for (const id of docIds) await deleteOfflineDocument(id)\n return docIds.length\n },\n onSettled: () => queryClient.invalidateQueries({ queryKey: arbiQueryKeys.offlineDocuments() }),\n onSuccess: (count) =>\n notify.success(`Removed ${count} offline ${count === 1 ? 'copy' : 'copies'}`),\n onError: () => notify.error('Could not remove offline copy'),\n })\n}\n","/**\n * The chat engine's stream handlers: what each frame of an assistant turn does to the conversation\n * cache (`conversation-cache`), the session (`ArbiSessionState`: generation, cursor, queued\n * follow-ups, run control) and the host (`ArbiHostConfig.chat`: documents shown, mail drafts, used-up\n * quota). `createStreamHandlers` builds one set per stream, sharing that stream's mutable state\n * (its conversation id moves from `new` to the server's, its answer id arrives with\n * `response.created`).\n */\n\nimport { useCallback } from 'react'\nimport { useQueryClient, type QueryClient } from '@tanstack/react-query'\nimport {\n quotaFromStreamError,\n type AgentControlStateEvent,\n type ArtifactEvent,\n type ChatMessage as Message,\n type ConversationResponse as Conversation,\n type DeferredInterjectionEvent,\n type MailDraftSSEEvent,\n type MessageMetadataPayload,\n type MessageQueuedEvent,\n type OutputItemDone,\n type ProbeAnswerEvent,\n type SSEStreamStartData,\n type TokenBudgetContext,\n type UserInputRequestEvent,\n type UserMessageEvent,\n} from '@arbidocs/sdk/browser'\nimport { arbiQueryKeys } from '../hooks'\nimport { useArbi } from '../useArbi'\nimport { useArbiHost } from '../host/config'\nimport { refreshDocuments } from '../documents'\nimport { useArbiSessionStore } from '../session'\nimport type { ArbiSessionStore } from '../session/store'\nimport { invalidateConversationLists, patchConversationList } from '../conversation-list'\nimport type { ArbiChatHost } from './host'\nimport { MIN_QUEUED_MESSAGE_VISIBILITY_MS, queuedMessages } from './run-state'\nimport {\n addAssistantMessageToCache,\n addUserMessageToCache,\n appendTokenToMessage,\n applyFinalContextToMessage,\n applyOutputItemToMessage,\n commitFinalMessage,\n completeQueuedUserMessageByContent,\n ensureAssistantMessageLoading,\n flushStreamingTokens,\n getInterjectionText,\n getThreadsQueryKey,\n isMessageRunning,\n markMessageAsFailed,\n markNarrationSettled,\n removeSettledNarration,\n setUserInputRequest,\n threadEndingAtContains,\n updateUserMessageInCache,\n updateUserMessageStateInCache,\n} from './conversation-cache'\nimport { adoptNewChatDocument } from './thread-binding'\nimport { recordChatArtifact } from './chat-artifacts'\n\n/**\n * How long freshly-arrived narration must stay readable on screen before the\n * turn's one resolving commit is allowed to remove it.\n *\n * The whole point is that the user can READ what the agent narrated. If a\n * narration line settles a few hundred ms before the answer completes, resolving\n * immediately would flash that line away — the original complaint, in a new\n * costume. So the commit that hands the window to the answer waits until the\n * newest narration has had this long on screen.\n *\n * 4000 ms, set from measurement rather than taste. A live turn (see\n * answer-resolves.visual.spec) narrated \"Now I'll open and read the most relevant\n * document — test-case.pdf (PDF)\" — 13 words, ~3.9 s of reading at a normal\n * 200-250 wpm — and the answer began almost immediately after it. At a 2500 ms\n * dwell that sentence measured 2446 ms on screen: not comfortably readable.\n *\n * Being generous is close to free: the answer streams in BELOW the narration\n * while it dwells, so nothing is hidden or delayed — and in the common case the\n * answer takes longer than this to stream, so the wait is already over when\n * `response.completed` lands and the delay is exactly zero.\n *\n * (Formerly MIN_PREAMBLE_DWELL_MS. Same 4 s, same purpose; renamed because there\n * is no \"preamble\" any more — nothing is folded out of the window mid-turn.)\n */\nexport const MIN_NARRATION_DWELL_MS = 4000\n\n/** The measure of the time to an answer's first token (from the send's `arbi:send-message:start`). */\nexport const FIRST_TOKEN_MEASURE = 'arbi:send-message:first-token'\n\nexport interface StreamHandlers {\n onMessageQueued: (data: MessageQueuedEvent) => void\n onUserMessage: (msg: UserMessageEvent) => void\n onStreamStart: (msg: SSEStreamStartData) => void\n onToken: (content: string) => void\n onMetadata: (msg: MessageMetadataPayload) => void\n onOutputItemDone: (ev: OutputItemDone) => void\n onOutputTextDelta: (data: { item_id: string; delta: string }) => void\n onUserInputRequest: (request: UserInputRequestEvent) => void\n onProbeAnswer: (probe: ProbeAnswerEvent) => void\n onDeferredInterjection: (data: DeferredInterjectionEvent) => void\n onAgentControlState: (event: AgentControlStateEvent) => void\n onArtifact: (artifact: ArtifactEvent) => void\n onMailDraft: (draft: MailDraftSSEEvent) => void\n onElapsedTime: (t: number) => void\n onContextUpdate: (context: TokenBudgetContext) => void\n onError: (error: unknown) => void\n onComplete: () => void\n}\n\n/** The mutable state of one stream, shared by its handlers and the send that started it. */\nexport interface StreamState {\n conversationId: string\n /**\n * The workspace the turn is in (captured when it started; the server's if it moved the turn to\n * its thread's). A new conversation joins this workspace's list, whatever the session is on now.\n */\n workspaceId?: string | null\n assistantId: string | null\n /**\n * Epoch ms when the newest narration block settled — the dwell clock's start. 0 while the turn\n * has narrated nothing, which is the honest answer to \"how long must this stay readable\": no time\n * at all.\n */\n lastNarrationSettledAt: number\n /**\n * The model has pivoted to a tool call and not yet resumed prose. The next prose therefore opens\n * a new narration and closes the previous one — the only reliable paragraph boundary, since one\n * sentence can span several message items.\n */\n pivotedSinceProse: boolean\n /**\n * Steering messages the backend deferred because they landed after the agent had committed to\n * its answer. Collected during the stream and resubmitted as a new turn once it completes.\n */\n deferredInterjections: string[]\n queuedContinuation: boolean\n queuedUserMessageId: string | null\n hasStreamStarted: boolean\n /** The backend refused a queued follow-up before its turn started. */\n queuedFailed: boolean\n abortController: AbortController\n /**\n * The person pressed Stop on this turn. Stop cancels the run on the server first, and that can\n * drop this connection before the local abort lands: a stopped turn must not then be recorded as\n * a failed one.\n */\n isStopped: () => boolean\n queueOwnerAssistantId: string | null\n queuedClientId: string | null\n /**\n * A memory tool (`create_fact` / `label_facts`) ran this turn, so the Facts table and the\n * workspace label vocabulary may have changed on the server. The tags query never auto-refetches\n * (staleTime: Infinity), so both are refreshed when the turn completes rather than making the\n * person reload the page to see a label the model just created.\n */\n factsTouched: boolean\n /**\n * The document the turn's thread is bound to, sent with it: a new chat's binding becomes the\n * conversation's once the server names it.\n */\n threadDocumentId?: string | null\n /** The server confirmed this turn's user message: it is stored, so the turn exists there. */\n userMessageId?: string | null\n /**\n * The server's own failure report (`response.failed` / `arbi.error` / an HTTP error), as opposed\n * to a dropped connection, which does not end the run on the server.\n */\n serverError?: string | null\n}\n\n/** What the handlers write to besides the cache. */\nexport interface StreamHandlerContext {\n queryClient: QueryClient\n session: ArbiSessionStore\n host: ArbiChatHost\n /** The signed-in user (the owner of a conversation this stream creates). */\n userId: () => string\n /** Re-read documents a turn wrote, into every documents cache. */\n refreshDocuments: (docIds: string[]) => Promise<unknown>\n}\n\nexport interface StreamHandlerParams {\n streamState: StreamState\n /** The message the send continued from (the cursor when it was sent). */\n parentMessageId: string | null\n /** The message the turn replies to. */\n parentId?: string | null\n}\n\n/** One stream's handlers. */\nexport function createStreamHandlers(\n ctx: StreamHandlerContext,\n params: StreamHandlerParams\n): StreamHandlers {\n const { queryClient, session, host } = ctx\n const { streamState, parentMessageId, parentId } = params\n\n // The user message this turn answers, as the server placed it.\n let turnUserMessageId: string | null = null\n let queuedEntryRetired = false\n\n const isViewingConversation = () =>\n session.getState().conversationId === streamState.conversationId\n\n /**\n * Take this follow-up out of the agent bar's queue box: the server has confirmed it\n * as a message of its own. The bubble in the thread shows it from here on. A follow-up\n * the server answers this fast still stays readable for a moment.\n */\n const retireQueuedEntry = () => {\n const clientId = streamState.queuedClientId\n if (!clientId || queuedEntryRetired) return\n queuedEntryRetired = true\n const entry = queuedMessages.find(session.getState().queuedMessages, clientId)\n if (!entry) return\n const remainingVisibility = Math.max(\n 0,\n MIN_QUEUED_MESSAGE_VISIBILITY_MS - (Date.now() - entry.createdAt)\n )\n if (remainingVisibility === 0) {\n session.removeQueuedMessage(clientId)\n } else {\n setTimeout(() => session.removeQueuedMessage(clientId), remainingVisibility)\n }\n }\n\n const handleUserMessage = (userMessage: UserMessageEvent) => {\n console.debug('[SSE] user_message:', userMessage.external_id, userMessage.status)\n\n const serverConversationId = userMessage.conversation_ext_id\n\n // Handle conversation ID transition from 'new' to real conversation\n if (serverConversationId && streamState.conversationId === 'new') {\n streamState.conversationId = serverConversationId\n\n // Its generation, documents, facts and tab move to the server id, and it stays open.\n session.moveConversation('new', serverConversationId)\n\n // Append a synthetic row to the conversations list so the sidebar /\n // ConversationList shows it immediately. We initialize every field\n // we know of so column readers (message count cell, last-message\n // status cell, owner cell) don't render `undefined`. Fields the\n // server may add later (generated title, message_count once the\n // first assistant message lands) get corrected when the user opens\n // the conversation (which fetches its detail) or by subsequent\n // events that touch the same conversation.\n const userExtId = ctx.userId()\n const nowIso = new Date().toISOString()\n patchConversationList(\n queryClient,\n streamState.workspaceId ?? session.getState().workspaceId,\n (old) =>\n old.some((c) => c.external_id === serverConversationId)\n ? old\n : [\n {\n external_id: serverConversationId,\n title: null,\n created_by_ext_id: userExtId,\n updated_by_ext_id: null,\n created_at: nowIso,\n updated_at: nowIso,\n is_shared: false,\n message_count: 1,\n last_message_status: 'in_progress',\n } as Conversation,\n ...old,\n ]\n )\n // The server bound it with this turn (a chat about a document): the row says so at once.\n adoptNewChatDocument(\n session,\n queryClient,\n serverConversationId,\n streamState.threadDocumentId ?? null\n )\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { type: _type, ...messageData } = userMessage\n // Mark the freshly-arrived user message as in-flight (isLoading=true)\n // so getOrphanedLastMessage suppresses the red \"Response Incomplete\"\n // banner during the brief gap between this event and the assistant's\n // stream_start. clearLoadingState (called when streams end / fail)\n // clears it back. Backend-loaded historical messages don't get this\n // flag, so genuine orphans from prior sessions still surface.\n const userMsg: Message = { ...messageData, isLoading: true }\n\n if (userMessage.status === 'queued') {\n streamState.queuedUserMessageId = userMessage.external_id\n }\n\n // If the message was already added from arbi.message_queued (with status=queued),\n // update it in-place (e.g., status → completed) instead of duplicating.\n const updated = updateUserMessageInCache(queryClient, streamState.conversationId, userMsg)\n if (!updated) {\n // Placed under the server's parent (userMessage.parent_message_ext_id) when the\n // cache has it, so queued follow-ups line up one after another.\n addUserMessageToCache(queryClient, streamState.conversationId, userMsg, {\n parentId,\n parentMessageId,\n currentParentMessageId: session.getState().cursor,\n })\n }\n turnUserMessageId = userMessage.external_id\n streamState.userMessageId = userMessage.external_id\n\n if (streamState.queuedContinuation) {\n retireQueuedEntry()\n // Follow the thread to its newest turn: when the follow-up extends the line being\n // viewed, view the line that now ends at it, not the sibling it would otherwise be.\n const viewedLeaf = session.getState().cursor\n if (\n isViewingConversation() &&\n viewedLeaf &&\n threadEndingAtContains(\n queryClient,\n streamState.conversationId,\n userMessage.external_id,\n viewedLeaf\n )\n ) {\n session.setCursor(userMessage.external_id)\n }\n }\n }\n\n const handleMessageQueued = (data: MessageQueuedEvent) => {\n // The queued acknowledgement precedes response.created but already has\n // the canonical assistant response ID. Seed the generation state now so\n // the docked agent bar appears with the user message instead of popping\n // in later. A queued continuation belongs to the existing parent bar, so\n // never replace its ID with the acknowledgement's throwaway response ID.\n if (!streamState.queuedContinuation && data.response_id && !streamState.assistantId) {\n streamState.assistantId = data.response_id\n session.setStreamingAssistantId(streamState.conversationId, data.response_id)\n }\n streamState.queuedUserMessageId =\n data.user_message?.external_id ?? data.user_message_id ?? streamState.queuedUserMessageId\n if (streamState.queuedClientId) {\n session.acknowledgeQueuedMessage(streamState.queuedClientId, streamState.queuedUserMessageId)\n }\n }\n\n const handleStreamStart = (streamStart: SSEStreamStartData) => {\n console.debug('[SSE] stream_start:', streamStart.assistant_message_ext_id)\n\n streamState.hasStreamStarted = true\n if (streamState.queuedUserMessageId) {\n updateUserMessageStateInCache(\n queryClient,\n streamState.conversationId,\n streamState.queuedUserMessageId,\n 'completed',\n false\n )\n }\n if (streamState.queuedContinuation) {\n retireQueuedEntry()\n // Follow-ups still waiting were queued on the turn that just finished; they now\n // wait on this one, so show them in its bar.\n if (streamState.queueOwnerAssistantId) {\n session.moveQueuedMessages(\n streamState.queueOwnerAssistantId,\n streamStart.assistant_message_ext_id\n )\n }\n }\n\n if (streamState.queuedContinuation) {\n session.setConversationGenerating(\n streamState.conversationId,\n true,\n streamState.abortController\n )\n }\n\n streamState.assistantId = streamStart.assistant_message_ext_id\n\n // The session holds the answer's id, so interjections and Stop can name it.\n session.setStreamingAssistantId(\n streamState.conversationId,\n streamStart.assistant_message_ext_id\n )\n\n const assistantMsg: Message = {\n role: 'assistant',\n content: '',\n external_id: streamState.assistantId,\n created_at: new Date().toISOString(),\n config_ext_id: null,\n created_by_ext_id: '',\n conversation_ext_id: streamState.conversationId,\n tokens: 0,\n status: 'in_progress',\n isLoading: true,\n }\n\n const placed = addAssistantMessageToCache(\n queryClient,\n streamState.conversationId,\n assistantMsg,\n turnUserMessageId ?? streamState.queuedUserMessageId\n )\n if (!placed) {\n // The answer's user message is not in the cache, so the answer could not be placed\n // after it. Re-read the thread for the server's order, then mark the row as streaming\n // again (the refetched row has no local loading flag).\n const conversationId = streamState.conversationId\n const answerId = streamStart.assistant_message_ext_id\n void queryClient\n .invalidateQueries({ queryKey: getThreadsQueryKey(conversationId) })\n .then(() => {\n if (\n streamState.assistantId === answerId &&\n !streamState.isStopped() &&\n isMessageRunning(queryClient, conversationId, answerId)\n )\n ensureAssistantMessageLoading(queryClient, conversationId, answerId)\n })\n }\n\n // The turn's user and assistant messages are stored now, so the list's Messages count\n // must include them while the answer generates (it is re-read again on completion).\n void invalidateConversationLists(queryClient)\n\n // The backend persists the assistant message at response.created,\n // so this ID is permanent and safe to use for chaining.\n session.setCursor(streamState.assistantId)\n }\n\n let firstTokenSeen = false\n const markFirstToken = () => {\n if (firstTokenSeen) return\n firstTokenSeen = true\n // Time to first token, from the send's own mark (the host reports the measure).\n try {\n performance.mark('arbi:send-message:first-token')\n if (performance.getEntriesByName('arbi:send-message:start', 'mark').length > 0)\n performance.measure(\n 'arbi:send-message:first-token',\n 'arbi:send-message:start',\n 'arbi:send-message:first-token'\n )\n } catch {\n // No performance timeline here: nothing to measure.\n }\n }\n\n // Raw tokens (non-agent LLM / fallback) — no item id. Stream straight through.\n const handleToken = (tokenContent: string) => {\n if (!streamState.assistantId) return\n markFirstToken()\n appendTokenToMessage(\n queryClient,\n streamState.conversationId,\n streamState.assistantId,\n tokenContent\n )\n }\n\n // A message output_item streaming its text (#2075). Every delta is APPENDED,\n // rendered provisionally (faded — see Message.tsx), until `response.completed`\n // says which of it was the answer. The one removal mid-turn is an item the\n // server settles as Narration (see handleOutputItemDone).\n //\n // There is deliberately no attempt to spot the answer mid-stream. The\n // previous design guessed (\"a new text block, once a tool call has settled,\n // is the answer\") and was wrong by construction: a turn may make any number\n // of tool calls, so every intermediate block after the first tool call was\n // mis-called. It survived only because the correcting event usually landed\n // inside the dwell — a race, not correctness.\n //\n // Deltas are appended VERBATIM, with no separator injected at item\n // boundaries. An item boundary is not an utterance boundary: the backend\n // settles the open narration item whenever it needs to emit a tool event,\n // which routinely splits one sentence across several items. A real captured\n // run shows the three items \"I've\" / \" started two background research tasks\n // …for both Apple and\" / \" Microsoft. Let me collect those results now.\\n\\n\" —\n // one sentence in three parts. Injecting a blank line per item would break\n // that into three mangled paragraphs. The model supplies its own line breaks\n // (note the trailing \"\\n\\n\" ending the utterance above), so plain appending\n // reproduces exactly the layout it intended: one line per utterance.\n const handleOutputTextDelta = (data: { item_id: string; delta: string }) => {\n if (!streamState.assistantId) return\n markFirstToken()\n // Prose resuming after a tool call is a NEW narration, not a continuation\n // of the one before it. Close the previous one here rather than when it\n // settled: only now is it known that the model went away and came back,\n // which is what makes this a paragraph boundary and what makes the prose\n // above it superseded.\n if (streamState.pivotedSinceProse) {\n streamState.pivotedSinceProse = false\n markNarrationSettled(queryClient, streamState.conversationId, streamState.assistantId)\n }\n appendTokenToMessage(\n queryClient,\n streamState.conversationId,\n streamState.assistantId,\n data.delta\n )\n }\n\n /**\n * The earliest moment the turn may resolve: a full dwell after the newest\n * narration settled. Zero when the turn narrated nothing — there is no prose\n * to protect, so a one-shot answer resolves the instant it completes.\n */\n const resolveNotBefore = () =>\n streamState.lastNarrationSettledAt === 0\n ? 0\n : streamState.lastNarrationSettledAt + MIN_NARRATION_DWELL_MS\n\n const handleMetadata = (metadata: MessageMetadataPayload) => {\n console.debug('[SSE] message_metadata:', metadata.external_id)\n\n const serverAssistantId = metadata.external_id\n\n // Update parentMessageId with the server-confirmed ID, but only if the user\n // is still viewing this conversation. Without this guard, metadata arriving from\n // a background stream would overwrite the active tab's parentMessageId.\n // A follow-up queued behind this turn may already extend the thread past it: keep\n // viewing that newer leaf rather than stepping back to this answer.\n const viewedLeaf = session.getState().cursor\n const viewingNewerLeaf =\n !!viewedLeaf &&\n threadEndingAtContains(queryClient, streamState.conversationId, viewedLeaf, serverAssistantId)\n if (isViewingConversation() && !viewingNewerLeaf) {\n session.setCursor(serverAssistantId)\n }\n\n // Backend-suggested follow-up (SUGGESTED_QUERIES config) — stashed\n // keyed to its conversation; the composer offers it as a chip.\n if (metadata.suggested_query) {\n session.setSuggestedQuery({\n conversationExtId: streamState.conversationId,\n text: metadata.suggested_query,\n })\n }\n\n if (streamState.assistantId) {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { type: _type, ...messageData } = metadata\n\n // `response.completed` is the ONLY place the main window resolves, and it\n // resolves in ONE commit: metadata.content is the authoritative answer\n // (the backend's _answer_final persists the answer alone, no narration),\n // it carries the citation offsets computed against that exact string, and\n // it clears `isLoading` so the body stops rendering provisionally.\n //\n // Doing all three together is the fix for the jitter: the answer used to\n // re-render un-faded with its footnotes, and the narration used to leave\n // the body on a separate timer, so the window reflowed twice in quick\n // succession. One commit, one reflow.\n commitFinalMessage(\n queryClient,\n streamState.conversationId,\n streamState.assistantId,\n messageData,\n resolveNotBefore()\n )\n }\n }\n\n // A settled output_item (#2075). Every item folds into the trace via the\n // reducer — including narration, which is why the body can drop narration's\n // text without losing it. Narration is the only text that leaves the body\n // before `response.completed`.\n const handleOutputItemDone = (ev: OutputItemDone) => {\n if (!streamState.assistantId) return\n const item = ev.item as {\n type?: string\n name?: string\n arbi?: { label?: string; step?: string; detail?: Array<{ tool?: string }> }\n summary?: unknown\n content?: unknown\n }\n // An interjection reasoning item settles the queued prompts it steered in.\n const interjection = getInterjectionText(item)\n if (interjection) {\n completeQueuedUserMessageByContent(queryClient, streamState.conversationId, interjection)\n session.consumeQueuedMessage(streamState.assistantId, interjection)\n }\n // A narration message settles the instant the model pivots to a tool call —\n // which is the moment its prose is complete on screen, and so the moment its\n // reading window starts. The answer's own item is excluded: the answer is\n // what stays, so it needs no protection from being removed.\n //\n // Timing off the settled ITEM (not off deltas) is what keeps a normal turn\n // free of any added delay. Deltas cannot distinguish narration from the\n // answer, so a delta clock would restart on the answer's own last token and\n // make every single turn wait out the full dwell.\n const isAnswerMessage = item.arbi?.step === 'answering' || item.arbi?.label === 'Answered'\n // An item the server settles as Narration (a working note, or a first draft the\n // grounding guard re-rolled into a tool call) is not the answer: it leaves the body now\n // and lives on in Show steps. Left in place it read as the finished answer. Having left,\n // it needs no reading window, so it does not hold the resolution either.\n if (item.type === 'message' && !isAnswerMessage && item.arbi?.label === 'Narration') {\n removeSettledNarration(\n queryClient,\n streamState.conversationId,\n streamState.assistantId,\n item.content\n )\n } else if (item.type === 'message' && !isAnswerMessage) {\n streamState.lastNarrationSettledAt = Date.now()\n }\n // A message item ending is NOT a paragraph ending. The backend splits one\n // sentence across several items — \"I've\" / \" started two background\n // research tasks…\" / \" Microsoft. Let me collect those results now.\" —\n // so breaking at every settle would shred prose mid-sentence.\n //\n // What genuinely ends a narration is the model PIVOTING to a tool call\n // and coming back. Record the pivot; the next prose acts on it.\n if (item.type === 'function_call') {\n streamState.pivotedSinceProse = true\n // A memory tool changed facts / labels server-side. Note it now and\n // refresh those views at completion, by when the tool has executed and\n // committed (invalidating on the call itself would race the DB write).\n // The tool name rides on `item.name`; fall back to the display detail.\n const tool = item.name || item.arbi?.detail?.[0]?.tool || ''\n if (tool === 'create_fact' || tool === 'label_facts') {\n streamState.factsTouched = true\n }\n }\n\n applyOutputItemToMessage(queryClient, streamState.conversationId, streamState.assistantId, ev)\n }\n\n const handleUserInputRequest = (request: UserInputRequestEvent) => {\n if (!streamState.assistantId) return\n setUserInputRequest(queryClient, streamState.conversationId, streamState.assistantId, request)\n }\n\n const handleProbeAnswer = (probe: ProbeAnswerEvent) => {\n if (!streamState.assistantId) return\n // Out-of-band status answer — a transient note on the streaming turn.\n session.setAgentProbeAnswer(streamState.assistantId, probe)\n }\n\n const handleDeferredInterjection = (data: DeferredInterjectionEvent) => {\n // Steering that reached the agent after it had committed to its answer.\n // Too late to fold into this turn — collect it and let the send\n // resubmit it as a new turn once the current turn finishes (submitting\n // now would race the in-flight stream).\n if (!data.message) return\n streamState.deferredInterjections.push(data.message)\n }\n\n const handleAgentControlState = (event: AgentControlStateEvent) => {\n if (!streamState.assistantId) return\n // Server-confirmed pause/resume state overrides the optimistic client state.\n session.setAgentControlState(streamState.assistantId, event.state)\n }\n\n // ARBI saved an email draft (a reply it was asked for): the host opens it beside this chat.\n const handleMailDraft = (draft: MailDraftSSEEvent) => host.onMailDraft?.(draft)\n\n const handleArtifact = (artifact: ArtifactEvent) => {\n console.info('[SSE] Received artifact event:', {\n doc_ext_id: artifact.doc_ext_id,\n title: artifact.title,\n is_complete: artifact.is_complete,\n })\n\n // Kept for every surface that shows the document as it is written; the host shows it.\n recordChatArtifact(artifact, streamState.conversationId)\n host.onArtifact?.(artifact, streamState.conversationId)\n\n // Auto-pin a freshly created artifact as this conversation's full-context\n // document once it's done streaming — \"make it bigger\", \"change the\n // color\" means the thing just shown, not whatever was pinned before.\n // Deliberately scoped to artifact CREATION, not general document\n // viewing: opening an unrelated doc to check something must not\n // silently redirect full-context to it (that's exactly the footgun the\n // existing manual-pin-only design avoids). The pin button\n // (the context chip's PinnedDocChip) remains the cancel/override — same\n // setPinnedDocumentId it already uses, so unpinning or pinning\n // something else works exactly as it does today. the conversation's documents\n // are required too: selectFullContextDocument only honours a pin that's\n // also in the conversation's document list (`selectFullContextDocument`),\n // and a just-generated artifact was never added there.\n if (artifact.is_complete) {\n const documents = session.getState().conversationDocuments[streamState.conversationId] ?? []\n if (!documents.some((d) => d.docId === artifact.doc_ext_id))\n session.setConversationDocuments(streamState.conversationId, [\n ...documents,\n { docId: artifact.doc_ext_id, isPinned: false },\n ])\n // A document draft is a Word document (stored as DOCX): the assistant drafts in it through\n // the open document (read on demand, tracked changes), so it is never pinned — a pin\n // would resend the whole document every turn. Only html/react artifacts, whose source\n // the assistant edits directly, are pinned.\n if (artifact.mode === 'html' || artifact.mode === 'react')\n session.setPinnedDocumentId(artifact.doc_ext_id)\n // The pin only WORKS once the doc is in the workspace-documents\n // cache: the composer's pill lookup and selectFullContextDocument\n // both intersect against it, and a just-generated artifact isn't\n // there until some later refetch. Without this, the auto-pin was\n // set but invisible AND dropped from the next send — same append\n // the upload path does.\n ctx.refreshDocuments([artifact.doc_ext_id]).catch(() => {})\n }\n }\n\n const handleElapsedTime = (t: number) => {\n session.setBackendElapsed(streamState.conversationId, t)\n }\n\n const handleContextUpdate = (context: TokenBudgetContext) => {\n if (!streamState.assistantId) return\n applyFinalContextToMessage(\n queryClient,\n streamState.conversationId,\n streamState.assistantId,\n context\n )\n }\n\n const handleError = (error: unknown) => {\n // A stop ends the stream as well; the stop itself settles the turn.\n if (streamState.isStopped()) return\n console.error('Stream error:', error)\n if (streamState.queuedContinuation && !streamState.hasStreamStarted) {\n streamState.queuedFailed = true\n }\n // If the stream error carries LiteLLM's ExceededBudget payload, open\n // the upgrade modal proactively. The \"Response Failed\" inline alert\n // still appears (driven by message status), but the user gets the\n // popup explaining why and offering to upgrade.\n const quota = quotaFromStreamError(error)\n if (quota) host.onQuotaExceeded?.(quota)\n // A thrown error is the connection, not the run: the run goes on on the server, and the\n // send re-reads the thread to attach to it or show how it ended (see useMessageActions).\n // Marking it failed here offered Retry, which deleted the question under a live answer.\n if (error instanceof Error) return\n streamState.serverError = String(error)\n // The server failed the answer: mark it failed so the UI shows the error state\n if (streamState.assistantId) {\n markMessageAsFailed(queryClient, streamState.conversationId, streamState.assistantId)\n }\n }\n\n const handleComplete = () => {\n console.debug('[SSE] Stream complete')\n // A Stop can end the run with a completed frame that carries only the partial answer,\n // either before its abort lands or with no local stream to abort. That frame's status\n // is not the run's: re-read the thread so the message shows how the server ended it.\n const generation = session.getState().generating[streamState.conversationId]\n if (streamState.isStopped() || generation?.isGenerating === false) {\n void queryClient.invalidateQueries({\n queryKey: getThreadsQueryKey(streamState.conversationId),\n })\n }\n // Ensure any rAF-buffered tokens are committed before the consumer\n // considers the stream finished. Without this, final deltas that\n // arrived in the same frame as the complete event would be dropped.\n flushStreamingTokens(queryClient)\n // Turn is over — drop its transient control state (pause/probe).\n if (streamState.assistantId) {\n session.clearAgentControl(streamState.assistantId)\n }\n // The model added a fact or a new label this turn: refresh the Facts\n // list and the workspace label vocabulary so they appear without a page\n // reload. `refetchType: 'all'` updates the cache even when the Facts view\n // is not currently mounted (the tags query has staleTime: Infinity and\n // would otherwise never pick the new label up on its own).\n if (streamState.factsTouched) {\n streamState.factsTouched = false\n queryClient.invalidateQueries({ queryKey: arbiQueryKeys.allFacts(), refetchType: 'all' })\n queryClient.invalidateQueries({ queryKey: arbiQueryKeys.allTags(), refetchType: 'all' })\n }\n }\n\n return {\n onMessageQueued: handleMessageQueued,\n onUserMessage: handleUserMessage,\n onStreamStart: handleStreamStart,\n onToken: handleToken,\n onMetadata: handleMetadata,\n onOutputItemDone: handleOutputItemDone,\n onOutputTextDelta: handleOutputTextDelta,\n onUserInputRequest: handleUserInputRequest,\n onProbeAnswer: handleProbeAnswer,\n onDeferredInterjection: handleDeferredInterjection,\n onAgentControlState: handleAgentControlState,\n onArtifact: handleArtifact,\n onMailDraft: handleMailDraft,\n onElapsedTime: handleElapsedTime,\n onContextUpdate: handleContextUpdate,\n onError: handleError,\n onComplete: handleComplete,\n }\n}\n\n/** The stream handlers of this host's chat (its cache, session and chat host). */\nexport function useStreamHandlers(): (params: StreamHandlerParams) => StreamHandlers {\n const queryClient = useQueryClient()\n const session = useArbiSessionStore()\n const config = useArbiHost()\n const arbi = useArbi()\n return useCallback(\n (params: StreamHandlerParams) =>\n createStreamHandlers(\n {\n queryClient,\n session,\n host: config.chat ?? {},\n userId: () => {\n try {\n return arbi.user.identity()?.externalId ?? ''\n } catch {\n return ''\n }\n },\n refreshDocuments: (ids) => refreshDocuments(queryClient, arbi, ids),\n },\n params\n ),\n [queryClient, session, config, arbi]\n )\n}\n","/**\n * What the chat engine checks and coordinates around a turn: whether a send can go out (online),\n * the run a Stop waits for, the attached runs a Stop closes, the run-control commands, and whether\n * a failed turn ran out of AI usage.\n */\n\nimport { onlineManager, type QueryClient } from '@tanstack/react-query'\nimport { STOP_ID_WAIT_MS, type QuotaExceeded } from '@arbidocs/sdk/browser'\nimport { notify } from '../shell'\nimport { arbiQueryKeys } from '../hooks'\nimport type { ArbiSessionStore } from '../session/store'\n\n/**\n * The slash-command text of each run-control action: the composer (typed) and the agent bar's\n * menu (clicked) send the same text, interjected into the running turn.\n */\nexport const AGENT_CONTROL_COMMANDS = {\n pause: '/pause',\n resume: '/resume',\n report: '/report',\n} as const\n\n/**\n * Chat runs against the server-side AI, so nothing can be sent offline. Call before any chat send:\n * when offline it tells the person the text is still in the box, and returns true so the caller\n * leaves the draft untouched.\n */\nexport function refuseChatWhenOffline(): boolean {\n if (onlineManager.isOnline()) return false\n notify.warning(\"You're offline — your message is still in the box. Reconnect to send it.\")\n return true\n}\n\nfunction findStream(session: ArbiSessionStore, controller: AbortController) {\n const generating = session.getState().generating\n // The stream keeps its controller where it ended (a stopped `new` entry still holds it), so\n // prefer the entry that is still generating with it.\n const keys = Object.keys(generating).filter((k) => generating[k]?.abortController === controller)\n const key = keys.find((k) => generating[k].isGenerating) ?? keys[0]\n return key ? { conversationKey: key, state: generating[key] } : null\n}\n\n/**\n * Wait for the local stream started with `controller` to report its response id. Resolves with the\n * id and the conversation it now belongs to, or null once that stream ends or `timeoutMs` passes.\n */\nexport function waitForResponseId(\n session: ArbiSessionStore,\n controller: AbortController,\n timeoutMs = STOP_ID_WAIT_MS\n): Promise<{ conversationKey: string; responseId: string } | null> {\n return new Promise((resolve) => {\n let done = false\n const finish = (result: { conversationKey: string; responseId: string } | null) => {\n if (done) return\n done = true\n clearTimeout(timer)\n unsubscribe()\n resolve(result)\n }\n const check = () => {\n const stream = findStream(session, controller)\n if (stream?.state.streamingAssistantId) {\n finish({\n conversationKey: stream.conversationKey,\n responseId: stream.state.streamingAssistantId,\n })\n } else if (!stream || !stream.state.isGenerating || controller.signal.aborted) {\n finish(null)\n }\n }\n const timer = setTimeout(() => finish(null), timeoutMs)\n const unsubscribe = session.subscribe(check)\n check()\n })\n}\n\n// Stop for each conversation's live attach, with the run it follows. An attach has no local\n// AbortController, so Stop reaches it through `disconnectAttachedRun` instead.\nconst attachedRunStops = new Map<string, { responseId: string; stop: () => void }>()\n\n/** Register a conversation's live attach; returns the unregister. */\nexport function registerAttachedRun(\n conversationId: string,\n responseId: string,\n stop: () => void\n): () => void {\n attachedRunStops.set(conversationId, { responseId, stop })\n return () => {\n if (attachedRunStops.get(conversationId)?.stop === stop) attachedRunStops.delete(conversationId)\n }\n}\n\n/**\n * Close the live attach stream of a run in a conversation, if that run is the one attached.\n * Matching the run matters: Stop awaits the cancel, and by then the server may have started the\n * next queued follow-up and attached it. Closing \"whatever is attached\" would cut that one off.\n */\nexport function disconnectAttachedRun(conversationId: string, responseId: string): void {\n const attached = attachedRunStops.get(conversationId)\n if (attached?.responseId === responseId) attached.stop()\n}\n\n/**\n * The workspace's AI usage as the cache knows it, when it is used up (its project's `ai_usage`\n * quota reached): the reason a failed turn failed.\n */\nexport function cachedQuotaUsedUp(\n queryClient: QueryClient,\n workspaceId: string | null | undefined\n): QuotaExceeded | null {\n if (!workspaceId) return null\n const workspaces = queryClient.getQueryData<\n Array<{ external_id: string; project_ext_id?: string | null }>\n >(arbiQueryKeys.workspaces())\n const projectExtId = workspaces?.find((w) => w.external_id === workspaceId)?.project_ext_id\n if (!projectExtId) return null\n const projects = queryClient.getQueryData<\n Array<{ external_id: string; quotas?: { ai_usage?: { used?: number; limit?: number } } }>\n >(arbiQueryKeys.projects())\n const project = projects?.find((p) => p.external_id === projectExtId)\n if (!project) return null\n const used = project.quotas?.ai_usage?.used ?? 0\n const limit = project.quotas?.ai_usage?.limit ?? 0\n if (limit <= 0 || used < limit) return null\n return { spend: used, budget: limit, projectExtId }\n}\n","/**\n * The chat engine's actions on a conversation: send (a turn, or a comment to the people in a\n * thread), branch, retry, stop, and the run-control commands typed while a turn runs. A turn goes\n * through `arbi.assistant.ask`, its frames through the stream handlers, and its state lives in the\n * session (`ArbiSessionState`) and the conversation cache.\n */\n\nimport { pendingChatModelSave } from '../config/config-hooks'\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport { useQueryClient, type QueryClient } from '@tanstack/react-query'\nimport {\n ArbiApiError,\n STOP_REPEAT_WINDOW_MS,\n getRunToCancel,\n quotaFromStreamError,\n type ConversationResponse as Conversation,\n type ThreadsResponse,\n} from '@arbidocs/sdk/browser'\nimport type { components } from '@arbidocs/client'\nimport { notify } from '../shell'\nimport { arbiQueryKeys } from '../hooks'\nimport { useArbi } from '../useArbi'\nimport { useArbiHost } from '../host/config'\nimport { selectDraft, useArbiSessionStore } from '../session'\nimport type { ArbiSessionStore } from '../session/store'\nimport {\n invalidateConversationLists,\n isConversationShared,\n patchConversation,\n patchConversationList,\n removeConversationFromLists,\n} from '../conversation-list'\nimport {\n allConversationThreads,\n clearLoadingState,\n flushStreamingTokens,\n getThreadsQueryKey,\n updateUserMessageStateInCache,\n} from './conversation-cache'\nimport {\n assistantLabels,\n cachedAssistantMode,\n cachedMentionCandidates,\n isCommentToPeople,\n} from './conversation-mentions'\nimport { useAssistantName } from '../host/assistant-copy'\nimport { hasMessageBody, toMessageMentions, extractMentions } from './mentions'\nimport { takeDocumentForTurn } from './open-document'\nimport { agentChatOwnerOf, creatorOf } from './agent-chat-owner'\nimport { bindThreadDocument, boundDocumentOf } from './thread-binding'\nimport { resolveReplyTarget } from './reply-target'\nimport {\n confirmConversationWorkspace,\n conversationWorkspaceOf,\n watchConversationWorkspaces,\n} from './conversation-workspace'\nimport { useStreamHandlers, type StreamState } from './stream-handlers'\nimport {\n AGENT_CONTROL_COMMANDS,\n cachedQuotaUsedUp,\n disconnectAttachedRun,\n refuseChatWhenOffline,\n waitForResponseId,\n} from './turn-control'\n\ntype MessageInput = components['schemas']['MessageInput']\ntype MessageMention = components['schemas']['MessageMention']\n\n/** How long a dropped turn holds its generating state while the thread is re-read. */\nconst RECONCILE_TIMEOUT_MS = 5000\n\nexport interface SendMessageOptions {\n /** An explicit edit/fork, rather than appending a human message to the shared thread. */\n branch?: boolean\n queuedContinuation?: boolean\n queueOwnerAssistantId?: string\n queuedClientId?: string\n /**\n * Bypasses the normal single-pinned-document tools computation (the chat's documents and its\n * pin, see `buildTurnRequest`) for this one send.\n * The app's general \"pin a document\" feature is deliberately one-at-a-time\n * (`selectFullContextDocument`) — a pinned TEXT doc's full content goes\n * straight into the AGENT's chat prompt, so more than one at a time risks\n * blowing that context window. Generate image is a different resource\n * entirely: reference images never touch the agent's chat context — they go\n * to the separate ImageGen model in its own request — so multiple\n * references (e.g. \"combine these two logos\") don't compound against that\n * budget, even though they still cost real tokens against ImageGen's own\n * call. This lets that caller build its own tools object with every\n * selected reference doc instead of touching the single global pin.\n */\n toolsOverride?: MessageInput['tools']\n /**\n * Send in this conversation and workspace rather than the open ones: a follow-up captured when\n * its turn started (a deferred interjection), sent after the view may have moved on.\n */\n target?: TurnTarget\n}\n\n/** The conversation and workspace a turn belongs to, captured when it starts. */\nexport interface TurnTarget {\n workspaceId: string\n conversationId: string\n}\n\n/**\n * The draft a send leaves behind. A shared chat addresses ARBI again, except after a comment to\n * people: then the box is left empty, which a shared chat reads as a comment to the thread.\n */\nfunction draftAfterSend(\n queryClient: QueryClient,\n session: ArbiSessionStore,\n wasComment: boolean,\n assistantName: string\n): string {\n const shared = isConversationShared(queryClient, session.getState().conversationId)\n return shared && !wasComment ? `@${assistantName} ` : ''\n}\n\n/**\n * A queued follow-up the backend refused before its turn started: mark its bubble failed and\n * take it out of the queue, so it does not sit there as if it were still waiting.\n */\nfunction failQueuedContinuation(\n queryClient: QueryClient,\n session: ArbiSessionStore,\n streamState: {\n conversationId: string\n queuedUserMessageId: string | null\n queueOwnerAssistantId: string | null\n queuedClientId: string | null\n }\n): void {\n if (streamState.queuedUserMessageId) {\n updateUserMessageStateInCache(\n queryClient,\n streamState.conversationId,\n streamState.queuedUserMessageId,\n 'failed',\n false\n )\n }\n if (streamState.queuedClientId) {\n session.removeQueuedMessage(streamState.queuedClientId)\n }\n notify.error('Queued message failed to send')\n}\n\n/** The signed-in user's id, or null before the session is known. */\nfunction signedInUserId(arbi: { user: { identity: () => { externalId: string } | null } }) {\n try {\n return arbi.user.identity()?.externalId ?? null\n } catch {\n return null\n }\n}\n\n/** What the actions act on: the open workspace and conversation, as the session holds them. */\nexport interface ConversationActionsInput {\n selectedWorkspaceId: string | null\n /** The cursor when the view rendered (the stream handlers place a branch against it). */\n parentMessageId: string | null\n /** The open conversation's key (`new` for a new chat). */\n conversationKey: string\n isGenerating: boolean\n lastFailedMessage: string | null\n}\n\n/** The actions on the open conversation. */\nexport function useConversationActions({\n selectedWorkspaceId,\n parentMessageId,\n conversationKey,\n isGenerating,\n lastFailedMessage,\n}: ConversationActionsInput) {\n const queryClient = useQueryClient()\n const session = useArbiSessionStore()\n const currentConversationId = conversationKey === 'new' ? null : conversationKey\n const invalidateUserWorkspaces = useCallback(\n () => void queryClient.invalidateQueries({ queryKey: arbiQueryKeys.workspaces() }),\n [queryClient]\n )\n\n const arbi = useArbi()\n // Each conversation stays in the workspace it was opened in, though the surface switches.\n useState(() => watchConversationWorkspaces(queryClient, session))\n const createHandlers = useStreamHandlers()\n const chatHost = useArbiHost().chat\n const assistantName = useAssistantName()\n const mentionCandidates = useCallback(\n () =>\n cachedMentionCandidates(\n queryClient,\n session.getState().workspaceId,\n signedInUserId(arbi),\n assistantName\n ),\n [queryClient, session, arbi, assistantName]\n )\n // The local stream a Stop is closing. Stop cancels the run on the server before it aborts the\n // stream, so the connection can drop first with a network error that is not an abort.\n const stoppedStreamRef = useRef<AbortController | null>(null)\n // True while a Stop's server cancel is in flight, so a second press does not cancel again.\n const stopInFlightRef = useRef(false)\n // When the last Stop was pressed. A press within STOP_REPEAT_WINDOW_MS of it is a double tap.\n const lastStopAtRef = useRef(0)\n // True while a Retry deletes and resends, so a second press does not do it again.\n const retryInFlightRef = useRef(false)\n // Lets sendMessage resubmit a deferred interjection as a new turn without a\n // self-reference (it is a useCallback that would otherwise close over a stale\n // or not-yet-defined copy of itself). Kept current just below its definition.\n const sendMessageRef = useRef<\n | ((content: string, parentId?: string | null, options?: SendMessageOptions) => Promise<void>)\n | null\n >(null)\n\n /**\n * Shared posts, and posts in a `mentioned` thread, run ARBI only when addressed; posts in an\n * ordinary solo chat address it implicitly.\n */\n const routeMessage = useCallback(\n (content: string, conversationId?: string | null) => {\n const state = session.getState()\n const convId = conversationId === undefined ? state.conversationId : conversationId\n const { newConversationAssistantMode } = state\n const candidates = mentionCandidates()\n const mentioned = extractMentions(content, candidates)\n const assistantMode = cachedAssistantMode(queryClient, convId, newConversationAssistantMode)\n const isComment = isCommentToPeople(queryClient, convId, content, candidates)\n const mentions = toMessageMentions(mentioned) as MessageMention[]\n // A message not taken as a comment addresses ARBI. In an existing `mentioned` thread that is\n // only one that @mentions it; what is left is the first message of a thread not created\n // yet, whose turn creates it in `mentioned` mode.\n if (\n !isComment &&\n assistantMode === 'mentioned' &&\n !mentions.some((m) => m.type === 'assistant')\n ) {\n mentions.push({ type: 'assistant' })\n }\n return {\n mentions,\n assistantMode,\n isComment,\n }\n },\n [queryClient, session, mentionCandidates]\n )\n\n /** Post a comment (no assistant run) and land the thread on it. */\n const postComment = useCallback(\n async (\n content: string,\n parentId: string | null,\n mentions: MessageMention[],\n branch = false\n ) => {\n const convId = session.getState().conversationId\n try {\n const saved = await arbi.conversations.postMessage({\n content,\n mentions,\n // Only an explicit edit creates a branch. Ordinary comments append to the\n // server's latest message, so simultaneous sends stay visible together. Else\n // (nothing yet) start a thread. The mode only applies to a conversation it creates.\n ...(branch && parentId\n ? { previous_message_ext_id: parentId }\n : convId\n ? { conversation_ext_id: convId }\n : {}),\n assistant_mode: 'mentioned',\n })\n const conversationId = saved.conversation_ext_id\n const nowIso = new Date().toISOString()\n if (!convId) {\n // A comment starts the thread without a turn to carry its binding: bind it right after.\n const bindTo = session.getState().newChatDocumentId\n session.moveConversation('new', conversationId)\n if (bindTo) session.setNewChatDocumentId(null)\n patchConversationList(queryClient, session.getState().workspaceId, (old) => [\n {\n external_id: conversationId,\n title: content.slice(0, 40),\n created_by_ext_id: saved.created_by_ext_id,\n updated_by_ext_id: null,\n created_at: nowIso,\n updated_at: nowIso,\n // A mention of someone who cannot see it yet shares it server-side: refetched below.\n is_shared: false,\n message_count: 1,\n last_message_status: 'completed',\n assistant_mode: 'mentioned',\n } as Conversation,\n ...old,\n ])\n if (bindTo)\n bindThreadDocument(arbi, queryClient, conversationId, bindTo).catch(() =>\n notify.error('Could not attach the document to this thread')\n )\n invalidateUserWorkspaces()\n } else {\n patchConversation(queryClient, conversationId, (c) => ({\n ...c,\n message_count: c.message_count + 1,\n updated_at: nowIso,\n }))\n }\n // Mentioning someone shares the conversation on the server, which this cache cannot know.\n if (mentions.some((m) => m.type === 'user')) {\n await invalidateConversationLists(queryClient)\n }\n await queryClient.invalidateQueries({ queryKey: getThreadsQueryKey(conversationId) })\n session.setCursor(saved.external_id)\n } catch (error) {\n notify.error(\n (error instanceof ArbiApiError && error.detail) || 'Failed to post the message'\n )\n // Give the text back rather than lose it.\n if (!selectDraft(session.getState())) session.setDraft(content)\n }\n },\n [arbi, session, queryClient, invalidateUserWorkspaces]\n )\n\n const sendMessage = useCallback(\n async (content: string, requestedParentId?: string | null, options?: SendMessageOptions) => {\n // Never reply to a failed or deleted message: the server refuses it, so every Retry and every\n // new message would fail again. A queued follow-up names the running turn on purpose. With\n // nothing above to reply to, the parent stays: only a fresh conversation could take it.\n const target = options?.target\n const parentId =\n options?.queuedContinuation || !requestedParentId\n ? requestedParentId\n : (resolveReplyTarget(\n queryClient,\n (target ? target.conversationId : session.getState().conversationId) || 'new',\n requestedParentId\n ) ?? requestedParentId)\n const route = routeMessage(content, target?.conversationId)\n if (route.isComment && !options?.queuedContinuation && !target) {\n await postComment(content, parentId ?? null, route.mentions, options?.branch)\n return\n }\n // A model picked just now is still being saved: the turn runs on it, not on the config before.\n const modelSave = pendingChatModelSave(session)\n if (modelSave) await modelSave.catch(() => undefined)\n const state = session.getState()\n const convId = target ? target.conversationId : state.conversationId\n const convKey = convId || 'new'\n // The turn's workspace, captured now: the conversation's own (a docked or scoped chat keeps\n // its conversation across a switch), else the surface's for a new conversation. Named on the\n // request, so neither a switch nor the session's open workspace can move it.\n const turnWorkspaceId =\n target?.workspaceId ?? conversationWorkspaceOf(queryClient, convId) ?? selectedWorkspaceId\n const agentChat = state.newAgentChat\n // An existing conversation's agent: as recorded, else its creator when that is one of the\n // person's own agents (an agent chat runs under the agent's session; the record does not\n // survive a sign-out, or another device).\n let agentExtId = convId\n ? state.agentChatOwners[convId]\n : agentChat?.workspaceId === turnWorkspaceId\n ? agentChat.agentId\n : undefined\n // Only a conversation an agent created is looked up (an ordinary send never waits on it).\n if (convId && !agentExtId && creatorOf(queryClient, convId)?.startsWith('agt-')) {\n agentExtId = await agentChatOwnerOf(queryClient, () => arbi.agents.list(), convId)\n if (agentExtId) session.setAgentChatOwner(convId, agentExtId)\n }\n const queuedContinuation = options?.queuedContinuation === true\n // First message of a brand-new conversation bumps the workspace's\n // conversation_count — used to tick the \"Ask ARBI\" onboarding step.\n const isNewConversation = !convId\n\n const documentIds = (state.conversationDocuments[convKey] || []).map((doc) => doc.docId)\n // The chat's facts ride every message of it (snapshot semantics, like its documents).\n const factIds = [...(state.conversationFacts[convKey] || [])]\n\n const newConfigId = state.chatModel\n\n // Frontend is the single source of truth for which config a request\n // uses (Option B): send the same config the model selector resolves &\n // displays (see useConversationSettings) — explicit per-conversation\n // choice (`newConfigId`) wins, otherwise the user's persisted\n // `last_config`, so a selected config (e.g. one with ARTIFACTS_ENABLED)\n // actually drives the chat instead of being silently dropped to an\n // empty config. `newConfigId` alone is insufficient — it is transient\n // and cleared on every new conversation. Read `last_config` from the\n // shared settings cache by partial key match: openapi-react-query\n // suffixes the query key with request options and the settings hook is\n // token-gated, so the hook value can momentarily be undefined here even\n // though the data is cached app-wide.\n const cachedSettings = queryClient\n .getQueriesData<{ last_config?: string }>({ queryKey: arbiQueryKeys.userSettings() })\n .map(([, data]) => data)\n .find((data) => data?.last_config)\n const lastConfigId = cachedSettings?.last_config\n const resolvedConfigId = newConfigId || (agentExtId ? undefined : lastConfigId)\n\n // PA mode delegates the turn to the personal agent (`buildTurnRequest` prefixes `/pa ` so\n // the backend routes it straight to the delegation stream).\n const isPaMode = !agentExtId && state.paMode\n\n // Drafting mode: the thread's own document is named (a reference, never its content): the one\n // the thread is bound to (started from it, or attached in it), else one made in this thread\n // and open. A document merely open beside a chat is not: a new chat starts unbound. While an\n // earlier version of it is on screen the viewer returns to the live document. For a Word\n // document the server binds the live document: the assistant reads what it needs on demand\n // and edits it as tracked changes. For an html/react artifact it gets the source and a\n // targeted edit tool. PA-mode turns are delegated to a separate agent and never touch\n // artifacts.\n const threadDocumentId = boundDocumentOf(queryClient, { ...state, conversationId: convId })\n const activeArtifactExtId = isPaMode\n ? null\n : takeDocumentForTurn({\n boundDocumentId: threadDocumentId,\n conversationId: convId,\n workspaceId: turnWorkspaceId,\n })\n\n // A workflow launch can leave structured tools for its one send; consume them here.\n const pendingTools = state.pendingTools\n if (pendingTools) session.setPendingTools(null)\n const toolsOverride = options?.toolsOverride ?? pendingTools ?? undefined\n\n const request = {\n question: content,\n workspaceId: turnWorkspaceId!,\n docIds: documentIds,\n pinnedDocumentId: state.pinnedDocumentId,\n factIds,\n tools: toolsOverride,\n personalAgent: isPaMode,\n activeArtifactExtId,\n // A new chat about a document is bound by its first turn, on the server (every device).\n ...(!convId && threadDocumentId ? { bindDocumentId: threadDocumentId } : {}),\n previousResponseId: parentId,\n agentId: agentExtId,\n model: resolvedConfigId,\n mentions: route.mentions,\n // A brand-new conversation starts in the mode picked in the composer.\n ...(!convId && route.assistantMode === 'mentioned'\n ? { assistantMode: 'mentioned' as const }\n : {}),\n }\n\n const abortController = new AbortController()\n if (!queuedContinuation) {\n session.setConversationGenerating(convKey, true, abortController)\n }\n\n // Optimistically mark this conversation in-progress the instant we start a\n // turn. Without this, Conversation's \"reconcile stale isGenerating\" effect\n // runs on the setConversationGenerating(true) above, sees the conversation\n // list's last_message_status still 'completed' from the PREVIOUS turn (the\n // stream_start patch below only lands ~50ms later), and immediately clears\n // isGenerating — which race-hid the live status bar on every follow-up\n // turn (first turns were exempt: the new conversation isn't in the list\n // yet). Patching here closes that window. No-op for a brand-new\n // conversation (convKey === 'new' isn't in the list).\n if (!queuedContinuation) {\n patchConversation(queryClient, convKey, { last_message_status: 'in_progress' })\n }\n\n // Mutable stream state — shared by all SSE handlers via closure\n const streamState: StreamState = {\n conversationId: convKey,\n workspaceId: turnWorkspaceId,\n assistantId: null,\n // 0 = nothing narrated yet, so nothing is owed a reading window.\n lastNarrationSettledAt: 0,\n // True once the model has pivoted to a tool call and not yet resumed\n // prose. Prose arriving while this is set opens a NEW narration, so the\n // one before it closes: paragraph break, and everything above becomes\n // superseded. Item boundaries alone cannot say this — the backend splits\n // a single sentence across several items.\n pivotedSinceProse: false,\n // Steering that landed too late to steer this turn; resubmitted as a new\n // turn once this one completes (see after the ask below).\n deferredInterjections: [],\n queuedContinuation,\n queuedUserMessageId: null,\n hasStreamStarted: false,\n queuedFailed: false,\n abortController,\n isStopped: () => stoppedStreamRef.current === abortController,\n queueOwnerAssistantId: options?.queueOwnerAssistantId ?? null,\n queuedClientId: options?.queuedClientId ?? null,\n // Set when a create_fact / label_facts tool runs this turn, so the Facts\n // table + label vocabulary refresh on completion (see handleComplete).\n factsTouched: false,\n threadDocumentId,\n // Set by the handlers: the server stored the question / reported its own failure.\n userMessageId: null,\n serverError: null,\n }\n\n // A follow-up sent for another conversation than the one on screen places itself under its own\n // parent, not under the screen's cursor.\n const handlers = createHandlers({\n streamState,\n parentMessageId: target ? (parentId ?? null) : parentMessageId,\n parentId,\n })\n // The server's word on the turn's workspace binds the conversation to it.\n const confirmTurnWorkspace = () => {\n if (streamState.workspaceId)\n confirmConversationWorkspace(\n queryClient,\n streamState.conversationId,\n streamState.workspaceId\n )\n }\n const onUserMessageInWorkspace = handlers.onUserMessage\n handlers.onUserMessage = (message) => {\n onUserMessageInWorkspace(message)\n confirmTurnWorkspace()\n }\n if (agentExtId) {\n const onUserMessage = handlers.onUserMessage\n handlers.onUserMessage = (message) => {\n if (message.conversation_ext_id) {\n session.setAgentChatOwner(message.conversation_ext_id, agentExtId)\n queryClient.invalidateQueries({ queryKey: arbiQueryKeys.agentChats(agentExtId) })\n }\n onUserMessage(message)\n }\n }\n\n const ownsActiveGeneration = () => {\n const activeGeneration = session.getState().generating[streamState.conversationId]\n return (\n activeGeneration?.abortController === abortController ||\n (!!streamState.assistantId &&\n activeGeneration?.streamingAssistantId === streamState.assistantId)\n )\n }\n\n try {\n performance.mark('arbi:send-message:start')\n await arbi.assistant.ask(request, {\n signal: abortController.signal,\n onMessageQueued: handlers.onMessageQueued,\n onUserMessage: handlers.onUserMessage,\n onStreamStart: handlers.onStreamStart,\n onToken: handlers.onToken,\n onMetadata: handlers.onMetadata,\n onError: handlers.onError,\n onComplete: handlers.onComplete,\n // `response.output_item.added` is deliberately NOT consumed: an item\n // opening told us only that SOME block had started, which is exactly the\n // guess this design gave up. Text arrives via onOutputTextDelta and\n // settles via onOutputItemDone.\n onOutputItemDone: handlers.onOutputItemDone,\n onOutputTextDelta: handlers.onOutputTextDelta,\n onUserInputRequest: handlers.onUserInputRequest,\n onProbeAnswer: handlers.onProbeAnswer,\n onDeferredInterjection: handlers.onDeferredInterjection,\n onAgentControlState: handlers.onAgentControlState,\n onArtifact: handlers.onArtifact,\n onMailDraft: handlers.onMailDraft,\n onElapsedTime: handlers.onElapsedTime,\n onContextUpdate: handlers.onContextUpdate,\n onQuotaExceeded: (quota) => chatHost?.onQuotaExceeded?.(quota),\n onWorkspace: (workspaceId) => {\n streamState.workspaceId = workspaceId\n confirmTurnWorkspace()\n },\n })\n // The stream is over: commit the text still waiting for a frame now, while the message is\n // the streamed one. Left buffered, it lands after the thread is re-read and is appended\n // to the answer the server stored.\n flushStreamingTokens(queryClient)\n\n // A steering response has no assistant stream of its own. The backend\n // accepted the queued user message into the active tool loop. Keep it\n // visibly queued until the parent stream emits its interjection step at\n // the actual tool boundary; that event settles the cache entry.\n if (queuedContinuation && !streamState.hasStreamStarted) {\n if (streamState.queuedFailed) failQueuedContinuation(queryClient, session, streamState)\n return\n }\n\n // The server refused the turn before storing anything (a parent that is gone, a model\n // that is down): say the send failed and offer Retry with the question, instead of letting\n // it vanish with nothing in the thread. Re-read the thread in case the server did store it.\n if (\n streamState.serverError &&\n !streamState.userMessageId &&\n !streamState.assistantId &&\n !queuedContinuation\n ) {\n if (ownsActiveGeneration()) {\n session.setConversationError(\n streamState.conversationId,\n streamState.serverError,\n content\n )\n void queryClient.invalidateQueries({\n queryKey: getThreadsQueryKey(streamState.conversationId),\n })\n // Undo the optimistic 'in_progress' set when the send started.\n void invalidateConversationLists(queryClient)\n }\n return\n }\n\n const ownsGeneration = ownsActiveGeneration()\n if (ownsGeneration) {\n session.setConversationGenerating(streamState.conversationId, false, null)\n }\n\n // The user's own generation just consumed AI usage — refresh the\n // \"£ used today\" indicator now instead of polling for it.\n queryClient.invalidateQueries({ queryKey: arbiQueryKeys.userUsageToday() })\n\n // Steering that reached the agent too late to steer this turn was\n // deferred by the backend rather than allowed to derail the answer.\n // Now that the turn is done, submit it as a new turn — threaded off the\n // assistant message that just finished, exactly as if the user had sent\n // it a moment later. Sent as one turn so a burst reads as a single\n // follow-up. Fire-and-forget via the ref so we don't block this turn's\n // completion bookkeeping (and to sidestep the self-reference).\n if (streamState.deferredInterjections.length > 0) {\n const followUp = streamState.deferredInterjections.join('\\n\\n')\n const threadParent = streamState.assistantId\n if (threadParent) {\n session.clearQueuedMessages(threadParent)\n }\n // In the conversation and workspace of the turn it steered, captured now: the view (or\n // the surface's workspace) may have moved on while the turn ran.\n void sendMessageRef.current?.(\n followUp,\n threadParent,\n streamState.workspaceId && streamState.conversationId !== 'new'\n ? {\n target: {\n workspaceId: streamState.workspaceId,\n conversationId: streamState.conversationId,\n },\n }\n : undefined\n )\n }\n\n // The conversations list cache is patched to 'in_progress' on stream\n // start (see the stream handlers). Patch it back to 'completed' here\n // so the Status column / sidebar reflect reality without a refetch.\n if (ownsGeneration) {\n const lastStatus = streamState.serverError ? 'failed' : 'completed'\n patchConversation(queryClient, streamState.conversationId, {\n last_message_status: lastStatus,\n })\n }\n\n // A new conversation changes the workspace's conversation_count — refresh\n // the workspaces list so onboarding's \"Ask ARBI\" step ticks reactively.\n if (isNewConversation && ownsGeneration) invalidateUserWorkspaces()\n\n if (ownsGeneration) {\n clearLoadingState(queryClient, streamState.conversationId)\n }\n } catch (error) {\n flushStreamingTokens(queryClient)\n const isAbort = error instanceof Error && error.name === 'AbortError'\n // The server stored the turn and only the connection dropped: the run is not over.\n const isDroppedConnection = !streamState.serverError && !isAbort && !streamState.isStopped()\n if (queuedContinuation && !streamState.hasStreamStarted) {\n // The server holds this follow-up in its queue already, and runs it in turn.\n if (isDroppedConnection && streamState.queuedUserMessageId) {\n if (streamState.queuedClientId) {\n session.removeQueuedMessage(streamState.queuedClientId)\n }\n void queryClient.invalidateQueries({\n queryKey: getThreadsQueryKey(streamState.conversationId),\n })\n return\n }\n failQueuedContinuation(queryClient, session, streamState)\n return\n }\n\n if (streamState.isStopped() || isAbort) {\n console.debug('Message sending was aborted by user')\n // The stopped stream leaves its assistant message loading with no stream behind it, and\n // a queued follow-up is not the owner so nothing else clears it. Clear it and re-read the\n // thread: a follow-up the server still runs is attached again, a stopped one shows its end.\n clearLoadingState(queryClient, streamState.conversationId)\n void queryClient.invalidateQueries({\n queryKey: getThreadsQueryKey(streamState.conversationId),\n })\n if (ownsActiveGeneration()) {\n session.setConversationGenerating(streamState.conversationId, false, null)\n patchConversation(queryClient, streamState.conversationId, {\n last_message_status: 'completed',\n })\n }\n return\n }\n\n console.error('Message sending failed:', error)\n if (!ownsActiveGeneration()) return\n\n // A dropped connection after the server stored the question does not end the turn: the\n // run goes on there. Failing it here offered Retry, which deleted the question under the\n // live answer (its answer then landed in the thread with no question) and, if the resend\n // failed too, left the view on the deleted turn. Re-read the thread instead: a running\n // answer is attached again, a failed one shows Retry, a finished one shows its answer.\n // Generation is held until the thread is re-read (or a few seconds pass, offline), so no\n // \"Response Incomplete\" alert offers to delete the question meanwhile.\n if (isDroppedConnection && streamState.userMessageId) {\n let timer: ReturnType<typeof setTimeout> | undefined\n await Promise.race([\n queryClient.invalidateQueries({\n queryKey: getThreadsQueryKey(streamState.conversationId),\n }),\n new Promise((resolve) => {\n timer = setTimeout(resolve, RECONCILE_TIMEOUT_MS)\n }),\n ])\n clearTimeout(timer)\n clearLoadingState(queryClient, streamState.conversationId)\n if (ownsActiveGeneration()) {\n session.setConversationGenerating(streamState.conversationId, false, null)\n }\n void invalidateConversationLists(queryClient)\n return\n }\n\n patchConversation(queryClient, streamState.conversationId, {\n last_message_status: 'failed',\n })\n\n // Open the upgrade modal if either (a) the error string carries\n // LiteLLM's ExceededBudget payload directly, or (b) the project's\n // cached AI usage is used up. Either path beats showing only\n // the conversation's generic error.\n const quota =\n quotaFromStreamError(error) ??\n cachedQuotaUsedUp(queryClient, session.getState().workspaceId)\n if (quota) chatHost?.onQuotaExceeded?.(quota)\n\n session.setConversationError(\n streamState.conversationId,\n error instanceof Error ? error.message : String(error),\n content\n )\n }\n },\n [\n selectedWorkspaceId,\n parentMessageId,\n queryClient,\n session,\n createHandlers,\n chatHost,\n arbi,\n invalidateUserWorkspaces,\n routeMessage,\n postComment,\n ]\n )\n\n // Keep the ref pointing at the latest sendMessage so the deferred-interjection\n // resubmit inside sendMessage always calls the current closure.\n sendMessageRef.current = sendMessage\n\n const handleCreateBranch = useCallback(\n async (parentMessageExtId: string | null, newContent: string) => {\n if (!newContent.trim() || !selectedWorkspaceId) return\n await sendMessage(newContent, parentMessageExtId, { branch: true })\n },\n [selectedWorkspaceId, sendMessage]\n )\n\n const handleSendMessage = useCallback(\n async (options?: SendMessageOptions) => {\n const currentMessage = selectDraft(session.getState()).trim()\n // The draft a shared thread starts with (`@<assistant> `) is not a question yet.\n if (!selectedWorkspaceId || !hasMessageBody(currentMessage, assistantLabels(assistantName)))\n return\n\n // A send consumes the suggested follow-up, whether or not it was used —\n // the next turn's metadata brings a fresh one.\n session.setSuggestedQuery(null)\n\n // Chat runs against the server-side AI — there's nothing to queue offline.\n // Don't fire a mutation that would just pause and hang; tell the user.\n if (refuseChatWhenOffline()) return\n\n // While a turn is active, only true out-of-band controls use /interject.\n // Ordinary text still goes through the typed query endpoint, whose\n // arbi.message_queued event persists and renders it before the response gate\n // opens. The backend then either steers it into the next tool boundary or\n // starts a normal follow-up turn after the current final answer completes.\n if (isGenerating) {\n const convKey = session.getState().conversationId || 'new'\n const genState = session.getState().generating[convKey]\n const streamingAssistantId = genState?.streamingAssistantId\n\n // In a thread, a message that does not @mention the assistant is a comment between\n // people: post it straight away instead of queueing it into the running turn.\n const route = routeMessage(currentMessage)\n if (route.isComment && streamingAssistantId) {\n session.setDraft(draftAfterSend(queryClient, session, route.isComment, assistantName))\n await postComment(currentMessage, streamingAssistantId, route.mentions)\n return\n }\n\n if (streamingAssistantId) {\n const command = currentMessage.toLowerCase()\n const isPause = command === AGENT_CONTROL_COMMANDS.pause\n const isResume = command === AGENT_CONTROL_COMMANDS.resume\n const isReport =\n command === AGENT_CONTROL_COMMANDS.report ||\n command.startsWith(`${AGENT_CONTROL_COMMANDS.report} `)\n\n session.setDraft(draftAfterSend(queryClient, session, route.isComment, assistantName))\n\n if (isPause) {\n session.setAgentControlState(streamingAssistantId, 'pausing')\n } else if (isResume) {\n session.setAgentControlState(streamingAssistantId, 'resuming')\n } else if (isReport) {\n session.setAgentProbePending(streamingAssistantId, true)\n }\n\n if (isPause || isResume || isReport) {\n await arbi.assistant.interject(streamingAssistantId, currentMessage)\n } else {\n const queuedClientId = `queued-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`\n session.addQueuedMessage(streamingAssistantId, {\n clientId: queuedClientId,\n content: currentMessage,\n serverId: null,\n acknowledged: false,\n createdAt: Date.now(),\n })\n await sendMessage(currentMessage, streamingAssistantId, {\n ...options,\n queuedContinuation: true,\n queueOwnerAssistantId: streamingAssistantId,\n queuedClientId,\n })\n }\n return\n }\n // Keep the draft intact during the brief pre-stream window.\n return\n }\n\n const parentId = session.getState().cursor\n\n session.setDraft(\n draftAfterSend(queryClient, session, routeMessage(currentMessage).isComment, assistantName)\n )\n\n await sendMessage(currentMessage, parentId, options)\n },\n [\n selectedWorkspaceId,\n isGenerating,\n session,\n sendMessage,\n arbi,\n routeMessage,\n postComment,\n queryClient,\n assistantName,\n ]\n )\n\n const handleAbortGeneration = useCallback(async () => {\n // A second press (a double-click) must not stop the run again: it would cancel twice, and\n // once the local abort has landed it would clear the stopped-stream marker, so the stream's\n // error would read as a failed answer.\n const stream = session.getState().generating[conversationKey]\n if (stopInFlightRef.current || stream?.isGenerating === false) return\n // A tap right after a Stop must not stop the follow-up the queue started in the meantime.\n if (Date.now() - lastStopAtRef.current < STOP_REPEAT_WINDOW_MS) return\n lastStopAtRef.current = Date.now()\n stopInFlightRef.current = true\n try {\n // Stop the run on the server first; closing the stream alone leaves it running and\n // its answer would arrive later.\n const controller = stream?.abortController ?? null\n stoppedStreamRef.current = controller\n let streamKey = conversationKey\n let responseId = stream?.streamingAssistantId ?? null\n // Pressed before the stream reported its id: the run already exists on the server, so wait\n // for the id instead of only closing the stream. Further presses meanwhile do nothing.\n if (!responseId && controller) {\n const reported = await waitForResponseId(session, controller)\n if (reported) {\n streamKey = reported.conversationKey\n responseId = reported.responseId\n }\n }\n // In a sub-agent's branch this is the run that delegated it.\n const threads =\n queryClient.getQueryData<ThreadsResponse>(getThreadsQueryKey(streamKey))?.threads ?? []\n const runId = responseId ? getRunToCancel(threads, responseId) : null\n if (runId) {\n try {\n await arbi.assistant.cancel(runId)\n } catch {\n // Still stop here (the run may already have ended); say the server may keep going.\n notify.warning(\n \"Stopped here, but the server didn't confirm: the answer may still appear later.\"\n )\n }\n }\n // The cancel is awaited, and the server starts the next queued follow-up as soon as it lands:\n // that follow-up may already own this conversation's generation state and attach. Only close\n // the stream this Stop belongs to, or the next answer goes silent (\"Working\", no stop square).\n const current = session.getState().generating[streamKey]\n const isStoppedStream = controller\n ? current?.abortController === controller\n : !current?.streamingAssistantId || current.streamingAssistantId === responseId\n if (isStoppedStream) session.abortConversationGeneration(streamKey)\n // A reattached run has no local controller: close its stream too, or it keeps painting. The\n // attach follows this conversation's streaming message (in a sub-agent branch, the branch's\n // reply), not the delegating run that was cancelled, so match it by that id.\n if (responseId) disconnectAttachedRun(streamKey, responseId)\n } finally {\n stopInFlightRef.current = false\n }\n }, [session, arbi, conversationKey, queryClient])\n\n const handleRetryOrphanedMessage = useCallback(\n async (messageContent: string, parentId: string | null, messageExtId: string) => {\n // One retry at a time: the alert's Retry and the composer's retry (or a double click) must\n // not delete and resend twice. Released however the retry ends.\n if (retryInFlightRef.current) return\n // Offline the delete would be paused and the resend refused, leaving neither done.\n if (refuseChatWhenOffline()) return\n retryInFlightRef.current = true\n try {\n // A failed parent (a follow-up the restart sweep failed behind a failed answer) is\n // refused by the server, so the resend goes to the nearest message above it instead.\n const replyTo = currentConversationId\n ? resolveReplyTarget(queryClient, currentConversationId, parentId)\n : parentId\n if (!replyTo && currentConversationId) {\n try {\n await arbi.conversations.delete(currentConversationId)\n removeConversationFromLists(queryClient, currentConversationId)\n session.startNewConversation()\n } catch (error) {\n console.error('Failed to delete conversation with orphaned first message:', error)\n }\n } else if (replyTo) {\n try {\n await arbi.conversations.deleteMessage(messageExtId)\n // The message and its replies are gone from whichever thread held them.\n void queryClient.invalidateQueries(allConversationThreads)\n } catch (error) {\n console.error('Failed to delete orphaned message:', error)\n }\n }\n\n await sendMessage(messageContent, replyTo)\n } finally {\n retryInFlightRef.current = false\n }\n },\n [currentConversationId, arbi, session, sendMessage, queryClient]\n )\n\n const handleRetrySend = useCallback(async () => {\n if (isGenerating || !lastFailedMessage || retryInFlightRef.current) return\n if (refuseChatWhenOffline()) return\n retryInFlightRef.current = true\n try {\n session.clearConversationError(conversationKey)\n // sendMessage replies to the nearest message the server accepts: the view may still point at\n // a turn a Retry deleted, or at a failed answer.\n const parentId = session.getState().cursor\n await sendMessage(lastFailedMessage, parentId)\n } finally {\n retryInFlightRef.current = false\n }\n }, [isGenerating, lastFailedMessage, session, conversationKey, sendMessage])\n\n const clearErrorState = useCallback(() => {\n session.clearConversationError(conversationKey)\n }, [session, conversationKey])\n\n // Clear error state when starting a new conversation\n useEffect(() => {\n if (currentConversationId === null) {\n session.clearConversationError('new')\n }\n }, [currentConversationId, session])\n\n return {\n handleCreateBranch,\n handleSendMessage,\n handleAbortGeneration,\n handleRetrySend,\n handleRetryOrphanedMessage,\n clearErrorState,\n }\n}\n","/**\n * The open conversation's line of messages: which thread is viewed (the session's `cursor`, the\n * leaf of that line), kept on a thread that exists, opened on the conversation's own thread (never\n * a sub-agent's branch) or on the thread of a linked message, and the messages of that line with\n * their stored steps rebuilt.\n */\n\nimport { useCallback, useEffect, useMemo, useRef } from 'react'\nimport {\n extractDocumentIdsFromMessages,\n extractFactIdsFromMessages,\n hydrateAgentSteps,\n pickMainThread,\n type ChatMessage,\n type Thread,\n} from '@arbidocs/sdk/browser'\nimport { useConversationThreads } from '../hooks'\nimport { useArbiSessionState, useArbiSessionStore } from '../session'\nimport type { ArbiSessionStore } from '../session/store'\n\n/**\n * The measure of a conversation switch: from opening another conversation to its threads being\n * there (a host reporting performance can observe it).\n */\nexport const CONVERSATION_SWITCH_MEASURE = 'arbi:conversation-switch:ready'\nconst SWITCH_START = 'arbi:conversation-switch:start'\n\nfunction mark(name: string): void {\n try {\n performance.mark(name)\n } catch {\n // No performance timeline here (an old runtime, a test): nothing to record.\n }\n}\n\nfunction measureSwitch(): void {\n try {\n if (performance.getEntriesByName(SWITCH_START, 'mark').length === 0) return\n performance.measure(CONVERSATION_SWITCH_MEASURE, SWITCH_START, CONVERSATION_SWITCH_MEASURE)\n } catch {\n // The marks are missing: nothing to record.\n }\n}\n\n/** View the line ending at `leafId` (no update when it is already viewed). */\nfunction selectThread(session: ArbiSessionStore, leafId: string): void {\n if (session.getState().cursor !== leafId) session.setCursor(leafId)\n}\n\n/** The open conversation's viewed line, its threads, and the workspace it is in. */\nexport function useConversationData() {\n const session = useArbiSessionStore()\n const selectedWorkspaceId = useArbiSessionState((s) => s.workspaceId)\n const currentConversationId = useArbiSessionState((s) => s.conversationId)\n const parentMessageId = useArbiSessionState((s) => s.cursor)\n // A message a link opened the conversation at.\n const deepLinkMessageId = useArbiSessionState((s) => s.deepLinkMessageId)\n\n const {\n data: threadsData,\n isLoading: threadsLoading,\n error: threadsError,\n } = useConversationThreads(currentConversationId || undefined)\n\n // The deep link already handled, so a later threads read does not handle it again.\n const processedDeepLinkRef = useRef<string | null>(null)\n // The conversation viewed before, to time a switch.\n const prevConversationIdRef = useRef<string | null>(null)\n\n // Which thread is viewed: the linked message's, else the one viewed, kept on a thread that exists.\n useEffect(() => {\n if (!threadsData?.threads || threadsData.threads.length === 0 || !currentConversationId) {\n return\n }\n const threads = threadsData.threads as Thread[]\n\n if (deepLinkMessageId) {\n if (processedDeepLinkRef.current === deepLinkMessageId) return\n // A message before a sub-agent's spawn point is in the delegation's branch too: open the\n // conversation's own thread for it.\n const threadWithMessage = pickMainThread(\n threads.filter((t) => t.history.some((m) => m.external_id === deepLinkMessageId))\n )\n if (threadWithMessage) {\n const leafId = threadWithMessage.leaf_message_ext_id\n // A linked message that is not the leaf stays set: the view scrolls to it and marks it.\n if (!leafId || leafId === deepLinkMessageId) session.setDeepLinkMessageId(null)\n processedDeepLinkRef.current = deepLinkMessageId\n if (leafId) selectThread(session, leafId)\n } else {\n // The message is not there: open the main thread.\n const firstLeaf = pickMainThread(threads)?.leaf_message_ext_id\n if (firstLeaf) selectThread(session, firstLeaf)\n session.setDeepLinkMessageId(null)\n }\n return\n }\n\n // Ready for the next deep link.\n processedDeepLinkRef.current = null\n\n if (!parentMessageId) {\n // The default thread is the conversation's own, never a sub-agent's branch.\n const defaultThread = pickMainThread(threads)\n const firstThreadId = defaultThread?.leaf_message_ext_id\n if (firstThreadId) {\n selectThread(session, firstThreadId)\n // The documents and facts the conversation was last asked with are its context again.\n const history = defaultThread?.history || []\n const key = session.getState().conversationId || 'new'\n const documents = extractDocumentIdsFromMessages(history)\n // History seeds a first visit; it must not replace a stored manual selection (an empty one\n // included) when this conversation is reopened.\n if (documents.length > 0 && session.getState().conversationDocuments[key] === undefined)\n session.setConversationDocuments(key, documents)\n const factIds = extractFactIdsFromMessages(history)\n if (factIds && factIds.length > 0) session.setConversationFacts(key, factIds)\n }\n return\n }\n\n // While a turn streams, its stream handlers own the cursor: a thread read in between holds a\n // stale leaf, and following it would break the next turn's chaining.\n if (session.getState().generating[currentConversationId]?.isGenerating) return\n\n if (threads.some((t) => t.leaf_message_ext_id === parentMessageId)) return\n\n // Follow the viewed message to its thread's leaf.\n const threadContainingMessage = pickMainThread(\n threads.filter((t) => t.history.some((m) => m.external_id === parentMessageId))\n )\n if (threadContainingMessage?.leaf_message_ext_id) {\n selectThread(session, threadContainingMessage.leaf_message_ext_id)\n return\n }\n\n // The viewed message is gone (a Retry deleted the failed turn it pointed at). Open the main\n // thread, so the view and the next send agree on a thread that exists: kept, the view showed\n // the first thread while every new message replied to the deleted one and failed.\n const mainLeaf = pickMainThread(threads)?.leaf_message_ext_id\n if (mainLeaf) selectThread(session, mainLeaf)\n }, [threadsData, parentMessageId, currentConversationId, deepLinkMessageId, session])\n\n // A switch to another conversation starts here...\n useEffect(() => {\n if (!currentConversationId) return\n if (\n prevConversationIdRef.current !== null &&\n prevConversationIdRef.current !== currentConversationId\n ) {\n mark(SWITCH_START)\n }\n prevConversationIdRef.current = currentConversationId\n }, [currentConversationId])\n\n // ...and ends when its threads are there.\n useEffect(() => {\n if (!threadsData || !currentConversationId) return\n mark(CONVERSATION_SWITCH_MEASURE)\n measureSwitch()\n }, [threadsData, currentConversationId])\n\n // The viewed line, with the steps of stored answers rebuilt from their persisted stream events.\n const messageHistory = useMemo((): ChatMessage[] => {\n if (!threadsData?.threads || threadsData.threads.length === 0) return []\n const threads = threadsData.threads as Thread[]\n // Before a thread is chosen (the effect above chooses it), and when the viewed one is gone\n // (a stale cursor), the main thread shows.\n const thread =\n (parentMessageId && threads.find((t) => t.leaf_message_ext_id === parentMessageId)) ||\n pickMainThread(threads)\n const history = (thread?.history || []) as ChatMessage[]\n return history.map((message) => {\n if (message.agentSteps) return message\n const hydrated = hydrateAgentSteps(message)\n if (!hydrated) return message\n return {\n ...message,\n agentSteps: hydrated.steps,\n agentStepsTotalElapsed: hydrated.totalElapsed,\n finalContextUsage: hydrated.finalContext,\n }\n })\n }, [threadsData, parentMessageId])\n\n const threads = useMemo(() => (threadsData?.threads || []) as Thread[], [threadsData?.threads])\n const setParentMessageId = useCallback(\n (leafId: string) => selectThread(session, leafId),\n [session]\n )\n\n return {\n selectedWorkspaceId,\n currentConversationId,\n parentMessageId,\n setParentMessageId,\n messageHistory,\n threads,\n threadsLoading,\n /** Reading the open conversation failed. */\n threadsError,\n /** No message yet: a new chat, or an existing one known empty once its threads have loaded. */\n isEmptyConversation:\n !currentConversationId ||\n Boolean(threadsData && !threadsData.threads.some((thread) => thread.history.length > 0)),\n }\n}\n","import { useMemo } from 'react'\nimport {\n getSubagentBranchRecord,\n type ChatMessage as Message,\n type Thread,\n} from '@arbidocs/sdk/browser'\n\n/** A message the conversation branches after: the replies it has, and the one viewed. */\nexport interface BranchPoint {\n parentId: string\n parentMessage: Message\n branches: Array<{\n id: string\n content: string\n author: string\n threadId: string\n parentId: string\n }>\n currentBranchIndex: number\n}\n\nexport interface BranchNavigation {\n branchPoints: Map<string, BranchPoint>\n getBranchControlForMessage: (messageId: string) => BranchPoint | null\n switchBranch: (branchPoint: BranchPoint, targetIndex: number) => void\n}\n\n/**\n * Hook to analyze threads and identify branch points for navigation\n */\nexport function useBranchNavigation(\n threads: Thread[] | undefined,\n parentMessageId: string | null,\n messageHistory: Message[],\n setParentMessageId: (threadId: string) => void\n): BranchNavigation {\n const branchPoints = useMemo(() => {\n const points = new Map<string, BranchPoint>()\n\n if (!threads || threads.length <= 1) {\n return points\n }\n\n // Create a map of message ID to the threads that contain it\n const messageToThreads = new Map<string, Thread[]>()\n\n threads.forEach((thread) => {\n thread.history.forEach((message) => {\n const messageId = message.external_id\n if (!messageId) return\n\n if (!messageToThreads.has(messageId)) {\n messageToThreads.set(messageId, [])\n }\n messageToThreads.get(messageId)!.push(thread)\n })\n })\n\n // Find branch points - messages that appear in multiple threads and have different next messages\n messageToThreads.forEach((containingThreads, messageId) => {\n if (containingThreads.length <= 1) return\n\n const message = messageHistory.find((m) => m.external_id === messageId)\n if (!message) return\n\n // Get the next messages for each thread that contains this message\n const nextMessages = new Map<string, Message>()\n\n containingThreads.forEach((thread) => {\n const messageIndex = thread.history.findIndex((m) => m.external_id === messageId)\n if (messageIndex >= 0 && messageIndex < thread.history.length - 1) {\n const nextMessage = thread.history[messageIndex + 1]\n // A sub-agent's task message is a DELEGATION off this point, not a\n // reply variant — RunningSubagents (attached to the message itself)\n // is how that thread is reached, not this branch-arrow counter.\n // Excluding it here keeps \"Branch N of M\" meaning what it says:\n // alternative attempts at the same reply, never a mix of those and\n // captive sub-agent runs.\n if (nextMessage.external_id && !getSubagentBranchRecord(nextMessage)) {\n nextMessages.set(nextMessage.external_id, nextMessage)\n }\n }\n })\n\n // If there are multiple different next messages, this is a branch point\n if (nextMessages.size > 1) {\n const branches = Array.from(nextMessages.values()).map((nextMsg) => ({\n id: nextMsg.external_id!,\n content: nextMsg.content,\n author: nextMsg.role,\n threadId:\n containingThreads.find((thread) =>\n thread.history.some((m) => m.external_id === nextMsg.external_id)\n )?.leaf_message_ext_id || '',\n parentId: messageId,\n }))\n\n // Find current branch index based on selected thread\n let currentBranchIndex = 0\n if (parentMessageId) {\n // First try exact match with thread leaf ID\n let currentBranchIdx = branches.findIndex((branch) => branch.threadId === parentMessageId)\n\n // If no exact match, check if the selected thread contains any of the branch messages\n if (currentBranchIdx === -1) {\n const selectedThread = threads.find((t) => t.leaf_message_ext_id === parentMessageId)\n if (selectedThread) {\n currentBranchIdx = branches.findIndex((branch) =>\n selectedThread.history.some((msg) => msg.external_id === branch.id)\n )\n }\n }\n\n if (currentBranchIdx >= 0) {\n currentBranchIndex = currentBranchIdx\n }\n }\n\n const branchPoint: BranchPoint = {\n parentId: messageId,\n parentMessage: message,\n branches,\n currentBranchIndex,\n }\n\n // Add branch point for each branch message (the messages that come after the branch point)\n branches.forEach((branch) => {\n points.set(branch.id, branchPoint)\n })\n }\n })\n\n return points\n }, [threads, parentMessageId, messageHistory])\n\n const getBranchControlForMessage = useMemo(() => {\n return (messageId: string): BranchPoint | null => {\n return branchPoints.get(messageId) || null\n }\n }, [branchPoints])\n\n const switchBranch = useMemo(() => {\n return (branchPoint: BranchPoint, targetIndex: number) => {\n if (targetIndex < 0 || targetIndex >= branchPoint.branches.length) {\n return\n }\n\n const targetBranch = branchPoint.branches[targetIndex]\n setParentMessageId(targetBranch.threadId)\n }\n }, [setParentMessageId])\n\n return {\n branchPoints,\n getBranchControlForMessage,\n switchBranch,\n }\n}\n","/**\n * useConnectRunStream: connect a conversation view to the live stream of the run its conversation\n * shows as still running, when this client is not the one streaming it.\n *\n * There is no \"background run\" vs \"foreground run\": a run's output is one durable, reconnectable\n * event stream keyed by the response id, and the run exists independent of any viewer. This hook\n * attaches whenever an assistant message in the conversation is still `in_progress` (or `queued`)\n * but THIS client holds no local stream for it (a scheduled run, or the same account on another\n * device; see `getRunToAttach`). It replays what happened so far, then tails live frames, feeding\n * every one into the SAME state a local turn uses (the conversation cache and the session's\n * generation and control state), so it renders in the ordinary message timeline: steps, goal\n * banner, answer.\n *\n * Connect / disconnect freely: the run keeps going regardless. When the message flips to\n * `completed`, `settle` re-reads the authoritative row and this stream disconnects. Control (pause /\n * resume / message) is the reverse direction, keyed by the same response id via `interject`.\n *\n * The one thing this stream does NOT carry is token-by-token deltas (too heavy to buffer for\n * reconnect): the client that STARTED the turn keeps its inline stream for live typing; every other\n * viewer gets steps, goal and the final answer text.\n */\n\nimport { useEffect, useRef } from 'react'\nimport { useQueryClient } from '@tanstack/react-query'\nimport { getRunToAttach } from '@arbidocs/sdk/browser'\nimport { useArbi } from '../useArbi'\nimport { useArbiSessionState, useArbiSessionStore } from '../session'\nimport {\n applyOutputItemToMessage,\n clearLoadingState,\n completeQueuedUserMessageByContent,\n ensureAssistantMessageLoading,\n flushStreamingTokens,\n getInterjectionText,\n getRunStartedAt,\n getThreadsQueryKey,\n isMessageRunning,\n setMessageContent,\n updateMessageWithMetadata,\n} from './conversation-cache'\nimport { registerAttachedRun } from './turn-control'\n\n/** Wait this long before attaching again to a run whose stream ended while it still runs. */\nconst RECONNECT_DELAY_MS = 2000\n/** Attaches in a row, with no frame received in between, before the view stops trying. */\nconst MAX_RECONNECTS = 5\n\n/** The fields of a conversation's messages the attach reads. */\ninterface AttachMessage {\n external_id: string\n role: string\n status?: string | null\n}\n\n/**\n * Attach the conversation view to its running run, if it has one this client is not streaming.\n *\n * @param conversationId The open conversation, or null for none.\n * @param messages The messages on screen (the line being viewed).\n */\nexport function useConnectRunStream(\n conversationId: string | null,\n messages: readonly AttachMessage[]\n): void {\n const generation = useArbiSessionState((s) =>\n conversationId ? s.generating[conversationId] : undefined\n )\n const responseId = conversationId ? getRunToAttach(generation, messages) : null\n useAttachRun(conversationId, responseId)\n}\n\nfunction useAttachRun(conversationId: string | null, responseId: string | null): void {\n const queryClient = useQueryClient()\n const session = useArbiSessionStore()\n // Read when attaching: a renewed session (a new `arbi`) must not cut and re-open a live attach.\n const arbi = useArbi()\n const arbiRef = useRef(arbi)\n arbiRef.current = arbi\n\n useEffect(() => {\n if (!conversationId || !responseId) return\n\n // A `disposed` flag ignores a stale effect's callbacks; the AbortController actually closes its\n // connection. That matters: each open run stream holds one of the browser's few HTTP/1.1\n // connections to the origin, so a stream left running after its view went away starves every\n // later request (the page stalls on load). The StrictMode double-invoke aborts the first stream\n // and opens the second, which is the normal fetch lifecycle.\n let disposed = false\n // The current attach's connection (a re-attach after an early end opens a new one).\n let controller = new AbortController()\n let retryTimer: ReturnType<typeof setTimeout> | undefined\n let reconnects = 0\n\n // Leaving the view saves this run's start on its message timer. Reuse it: a re-attach after\n // navigating away must keep counting from the real start, not restart.\n const runStartedAt =\n session.getState().messageTimers[`${conversationId}:${responseId}`]?.startTime\n // Mark the conversation as generating (no abort controller: this client didn't start the run,\n // so there's nothing local to abort) and point the control bar at the run's answer.\n session.setConversationGenerating(conversationId, true, null)\n // Anchor the live timer at the run's own start: a reattach (e.g. after a reload) must not\n // restart \"Thinking 0s\" while the run has been going for minutes. Prefer the start this client\n // saved when it left; after a reload only the message's created_at is left.\n session.setStreamingAssistantId(\n conversationId,\n responseId,\n runStartedAt ?? getRunStartedAt(queryClient, conversationId, responseId) ?? Date.now()\n )\n\n // Settle the streaming state: stop showing the message as generating and drop the loading\n // flags so it renders normally. When `refetch`, also re-read the thread so the settled message\n // matches the server exactly: final content, status `completed` (which disconnects this\n // stream), and the persisted `stream_events`/`trace` hydrated into steps and goal banner (robust\n // even if the live replay window had already expired).\n const settle = (refetch: boolean) => {\n session.setConversationGenerating(conversationId, false, null)\n session.clearAgentControl(responseId)\n clearLoadingState(queryClient, conversationId)\n if (refetch) {\n void queryClient.invalidateQueries({ queryKey: getThreadsQueryKey(conversationId) })\n }\n }\n\n // Give the live steps / answer a row to land on (idempotent: reuses the history row if the\n // run's answer is already loaded). A refetch drops the flag, so re-add it.\n const markLoading = () => ensureAssistantMessageLoading(queryClient, conversationId, responseId)\n\n // The stream ended without a final frame. That can be a stopped run, or a connection that\n // dropped while the run goes on. Re-read the thread: a message the server still reports as\n // running is attached again, not shown as finished with no answer. Otherwise it settles.\n const endedEarly = async () => {\n // Commit the streamed text still waiting for a frame before the re-read replaces the message:\n // painted afterwards, it would be appended to the content the server stored.\n flushStreamingTokens(queryClient)\n await queryClient.invalidateQueries({ queryKey: getThreadsQueryKey(conversationId) })\n if (disposed) return\n if (\n isMessageRunning(queryClient, conversationId, responseId) &&\n reconnects < MAX_RECONNECTS\n ) {\n reconnects += 1\n markLoading()\n retryTimer = setTimeout(connect, RECONNECT_DELAY_MS)\n return\n }\n settle(false)\n // Gave up while the run still shows as running, most often because the connection is down (a\n // dropped connection leaves a local turn to this attach too). Try again once it is back: the\n // view does not attach the same run a second time on its own.\n if (isMessageRunning(queryClient, conversationId, responseId)) {\n window.removeEventListener('online', reconnectWhenOnline)\n window.addEventListener('online', reconnectWhenOnline, { once: true })\n }\n }\n\n const reconnectWhenOnline = () => {\n // A turn this client started meanwhile owns the conversation's stream: leave it be.\n if (disposed || session.getState().generating[conversationId]?.isGenerating) return\n reconnects = 0\n session.setConversationGenerating(conversationId, true, null)\n connect()\n }\n\n const connect = () => {\n markLoading()\n controller = new AbortController()\n // Whether this attach itself saw a final frame or an error (each ends the attach once).\n let ended = false\n arbiRef.current.assistant\n .attachRun(responseId, {\n signal: controller.signal,\n // The reconnect learns its conversation from the stream; we already know it, but assert\n // the match so a stray attach on a mismatched cache can't write to the wrong conversation.\n onUserMessage: (userMessage) => {\n if (disposed) return\n if (\n userMessage.conversation_ext_id &&\n userMessage.conversation_ext_id !== conversationId\n ) {\n disposed = true\n }\n },\n onOutputItemDone: (ev) => {\n if (disposed) return\n reconnects = 0\n applyOutputItemToMessage(queryClient, conversationId, responseId, ev)\n // A prompt queued on this run was steered into it: it is no longer waiting.\n const interjection = getInterjectionText(ev.item)\n if (interjection) {\n completeQueuedUserMessageByContent(queryClient, conversationId, interjection)\n session.consumeQueuedMessage(responseId, interjection)\n }\n // NON-DESTRUCTIVE reconnect. This path runs when a viewer (re)attaches to a run,\n // including a REMOUNT of the conversation mid-stream (navigate away and back). The\n // live token stream (the local ask) already wrote the streamed-so-far answer into the\n // cache, and that cache SURVIVES the remount. So on reconnect only ADD the final\n // answer, never clobber what's there: set the body ONLY from the terminal \"Answered\"\n // item, and never overwrite or clear on narration/steps.\n const item = ev.item as {\n type?: string\n arbi?: { label?: string }\n content?: Array<{ text?: string }>\n }\n if (item?.type === 'message' && item.arbi?.label === 'Answered') {\n const text = Array.isArray(item.content)\n ? item.content.map((c) => c.text ?? '').join('')\n : ''\n if (text) setMessageContent(queryClient, conversationId, responseId, text)\n }\n },\n onAgentControlState: (event) => {\n if (disposed) return\n // Server-confirmed pause/resume: overrides the optimistic click state.\n session.setAgentControlState(responseId, event.state)\n },\n // The authoritative message, and the only frame that carries the answer with its citation\n // markers applied plus the `tools.model_citations` map they resolve through. The\n // \"Answered\" item above carries the model's raw text, which predates both, so without\n // this an attacher rendered a citation-free answer. Relying on the settle(true) refetch\n // is not enough: the cleanup path settles WITHOUT a refetch, and sets `disposed` first,\n // so a viewer who leaves as the run ends never gets the reconciliation.\n onMetadata: (metadata) => {\n if (disposed) return\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { type: _type, ...messageData } = metadata\n updateMessageWithMetadata(queryClient, conversationId, responseId, messageData)\n },\n // onTextDone intentionally omitted: it fires for EVERY settled message item (narration\n // included) and, being label-blind, would overwrite the streamed body. The terminal\n // answer is applied above from the \"Answered\" item, then replaced by the authoritative\n // metadata content in onMetadata.\n onComplete: () => {\n if (disposed) return\n ended = true\n flushStreamingTokens(queryClient)\n settle(true)\n },\n onError: () => {\n if (disposed) return\n ended = true\n // A 404 = the run is no longer active here. Read the thread again to see whether it has\n // finished or is still running elsewhere.\n void endedEarly()\n },\n })\n .then(() => {\n // The stream can also just end, with no final frame: a stopped (cancelled) run's replay\n // stops without `response.completed`. Re-read the thread so the message shows its real\n // status, and attach again if the server still runs it.\n if (disposed || ended) return\n void endedEarly()\n })\n .catch(() => {\n if (disposed) return\n void endedEarly()\n })\n }\n\n connect()\n\n // Stop: close the stream for good (no re-attach, even if the server has not caught up with the\n // cancel yet), and re-read the thread so the message shows how it ended.\n const stop = () => {\n if (disposed) return\n disposed = true\n clearTimeout(retryTimer)\n window.removeEventListener('online', reconnectWhenOnline)\n controller.abort()\n settle(true)\n }\n const unregister = registerAttachedRun(conversationId, responseId, stop)\n\n return () => {\n unregister()\n // Disconnecting (run finished, or navigated away) must settle the streaming flags, not just\n // stop listening: otherwise the message is stuck as an empty streaming target. Clear without\n // a refetch here (a completing run already refetched via onComplete; a nav-away needs none).\n disposed = true\n clearTimeout(retryTimer)\n window.removeEventListener('online', reconnectWhenOnline)\n controller.abort()\n settle(false)\n }\n }, [conversationId, responseId, queryClient, session])\n}\n","/**\n * A saved workflow's run (a thread its trigger or \"Run now\" started on the server) starts\n * untitled: the server holds no workspace key to write a title, and there is no question of the\n * person's to name it after. Thread lists name it after its workflow and the day it started, and\n * the open one is titled so on the server once, so every other list shows the same name.\n */\n\nimport { useEffect, useMemo, useRef } from 'react'\nimport { useQueryClient } from '@tanstack/react-query'\nimport { arbiQueryKeys } from '../hooks'\nimport { useArbi } from '../useArbi'\nimport { useCanEditShared, useUpdateConversation, useWorkflows } from '../workforce'\n\n/** An untitled run's name: the workflow and the day it started (\"Weekly review — 28 Oct\"). */\nexport function workflowRunTitle(workflowName: string, createdAt: string): string {\n const day = new Date(createdAt).toLocaleDateString(undefined, { day: 'numeric', month: 'short' })\n return `${workflowName} — ${day}`\n}\n\n/** What a run's name is made from (a conversation list's row). */\nexport interface WorkflowRunRow {\n external_id: string\n title?: string | null\n workflow_ext_id?: string | null\n created_at?: string | null\n is_owner?: boolean\n is_shared?: boolean\n}\n\n/**\n * Names for the untitled saved-workflow runs among `conversations` (the list of `workspaceId`),\n * by id (runs of a workflow the caller cannot list keep no name). The open one (`openId`) is\n * titled with its name on the server, when the viewer may edit it (its owner, or an editor of a\n * shared one) and it is still untitled when the list is read again just before (a rename in\n * another tab wins).\n */\nexport function useWorkflowRunTitles(\n conversations: readonly WorkflowRunRow[],\n openId: string | null,\n workspaceId: string | undefined\n): Record<string, string> {\n const hasUntitledRun = conversations.some((c) => !c.title && c.workflow_ext_id && c.created_at)\n const { data: workflows } = useWorkflows({ enabled: hasUntitledRun })\n const titles = useMemo(() => {\n const names = new Map((workflows ?? []).map((w) => [w.external_id, w.name]))\n const out: Record<string, string> = {}\n for (const c of conversations) {\n const name = !c.title && c.workflow_ext_id ? names.get(c.workflow_ext_id) : undefined\n if (name && c.created_at) out[c.external_id] = workflowRunTitle(name, c.created_at)\n }\n return out\n }, [workflows, conversations])\n\n const arbi = useArbi()\n const queryClient = useQueryClient()\n const canEditShared = useCanEditShared()\n const { mutateAsync: rename } = useUpdateConversation()\n const titled = useRef(new Set<string>())\n const open = openId ? conversations.find((c) => c.external_id === openId) : undefined\n const openTitle = openId ? titles[openId] : undefined\n const mayEdit = !!open && (open.is_owner === true || (open.is_shared === true && canEditShared))\n useEffect(() => {\n if (!openId || !openTitle || !mayEdit || !workspaceId || titled.current.has(openId)) return\n titled.current.add(openId)\n void (async () => {\n // The list as the server has it now, not as cached: a title given meanwhile is kept.\n const fresh = await queryClient.fetchQuery({\n queryKey: arbiQueryKeys.conversations(workspaceId),\n queryFn: () => arbi.conversations.list({ workspaceId }),\n staleTime: 0,\n })\n if (fresh.find((c) => c.external_id === openId)?.title) return\n await rename({ conversationId: openId, patch: { title: openTitle } })\n })().catch(() => {\n // Naming is a courtesy: the list keeps showing the name either way.\n })\n }, [openId, openTitle, mayEdit, workspaceId, arbi, queryClient, rename])\n return titles\n}\n","/**\n * `useConversation`: the chat engine as one hook, the controller behind a full-page (or docked)\n * assistant. It returns what a chat surface needs and no markup; `@arbidocs/blocks/chat`'s\n * `ChatPage` takes it as its `chat` prop:\n *\n * ```tsx\n * const chat = useConversation({ workspaceId })\n * <ChatPage chat={chat} aside={<WorkflowLauncher … />} />\n * ```\n *\n * It is the same engine the ARBI app runs: the open conversation is the session's\n * (`ArbiSessionState.conversationId`, its viewed line `cursor`), the messages are the conversation\n * cache's, a turn goes through `useConversationActions` (send, branch, retry, stop, follow-ups\n * queued or steered into a running turn, comments to the people in a shared thread), and a run\n * started elsewhere is attached live (`useConnectRunStream`). So every surface gets the agent's\n * steps, the branches of an edited question, and interjections.\n *\n * A surface that must keep its own open conversation, beside another chat on the same page, mounts\n * inside its own session scope (`<ConversationScope>`).\n */\n\nimport { useCallback, useEffect, useMemo, useState } from 'react'\nimport { useQueryClient } from '@tanstack/react-query'\nimport type { AgentStepEvent, AskRequest, ChatMessage } from '@arbidocs/sdk/browser'\nimport { useArbi } from '../useArbi'\nimport { useAgentChats } from '../workforce'\nimport { useConversations } from '../hooks'\nimport { refreshDocuments, useDocuments } from '../documents/documents-data'\nimport { removeConversationFromLists } from '../conversation-list'\nimport { useArbiSessionState, useArbiSessionStore } from '../session'\nimport { toChatCitations, type ArbiChatCitation } from './citations'\nimport { getThreadsQueryKey } from './conversation-cache'\nimport {\n cachedAssistantMode,\n cachedMentionCandidates,\n isCommentToPeople,\n} from './conversation-mentions'\nimport { useAssistantName } from '../host/assistant-copy'\nimport { useConversationActions } from './useConversationActions'\nimport { useConversationData } from './useConversationData'\nimport { useBranchNavigation } from './useBranchNavigation'\nimport { useConnectRunStream } from './useConnectRunStream'\nimport type { QueuedMessage } from './run-state'\nimport { useWorkflowRunTitles, type WorkflowRunRow } from './workflow-run-titles'\n\nexport type { ArbiChatCitation, ArbiChatPassage } from './citations'\n\nexport type ArbiChatRole = 'user' | 'assistant'\nexport type ArbiChatMessageStatus = 'streaming' | 'complete' | 'error'\n\nexport interface ArbiChatMessage {\n mentions?: AskRequest['mentions']\n authorId?: string\n id: string\n role: ArbiChatRole\n /** Markdown for an assistant message, plain text for a user message. */\n content: string\n status: ArbiChatMessageStatus\n /** Why an assistant message failed. */\n error?: string\n /** Agent steps (tool calls, reasoning) the answer took. */\n stepCount?: number\n /** The answer's agent steps, live while it runs. */\n steps?: AgentStepEvent[]\n /** The sources behind `[statement](#cite-N)` marks in `content`. */\n citations?: ArbiChatCitation[]\n /** The reader stopped the answer; `content` is what had streamed. */\n stopped?: boolean\n /** The backend id of a finished assistant answer: what a follow-up chains from. */\n responseId?: string\n /**\n * A user message the server sent to start a workflow's step (its `tools.workflow_step`): the\n * step's id. A chat shows it as that step, not as the raw instruction.\n */\n workflowStep?: string\n /**\n * One of several versions of this message (an edited question, an answer asked again): which\n * one is shown (0-based) and how many there are. `switchBranch` shows another.\n */\n branch?: { index: number; count: number }\n}\n\n/** The workflow step a stored message starts (its `tools.workflow_step` marker), if any. */\nexport function workflowStepOf(tools: object | null | undefined): string | undefined {\n const marker = (tools as Record<string, unknown> | null | undefined)?.workflow_step as\n { workflow_step?: unknown } | undefined\n return typeof marker?.workflow_step === 'string' ? marker.workflow_step : undefined\n}\n\nexport interface ArbiChatThread {\n id: string\n /** The backend title, else the first question; empty until there is one. */\n title: string\n}\n\nexport interface ArbiChatDocument {\n id: string\n name: string\n isSelected: boolean\n}\n\nexport interface UseConversationOptions {\n /** Use an owned agent's independent session, history and sandbox files. */\n agentId?: string\n /** The workspace to chat in (default: the session's). */\n workspaceId?: string\n /** Assistant configuration or model id every turn uses (default: the person's last one). */\n model?: string\n /** Longest auto-title in characters (used until the backend has titled the conversation). Default 48. */\n titleLength?: number\n}\n\nexport interface ArbiConversation {\n assistantMode: 'always' | 'mentioned'\n isUpdatingAssistantMode: boolean\n isPostingComment: boolean\n setAssistantMode: (mode: 'always' | 'mentioned') => Promise<void>\n threads: ArbiChatThread[]\n /** The open conversation's id, or `new` for a chat not sent yet. */\n activeThreadId: string\n /** The viewed line of the open conversation. */\n messages: ArbiChatMessage[]\n /** An answer is running in the open conversation. */\n isRunning: boolean\n /** The last turn failed (the message list also carries the failed message). */\n error: string | null\n /** A stored conversation's messages are loading. */\n isLoadingThread: boolean\n /** The conversation list is loading. */\n isLoadingThreads: boolean\n /** Deleting a conversation or changing its mode failed. */\n historyError: string | null\n documents: ArbiChatDocument[]\n isLoadingDocuments: boolean\n isUploading: boolean\n uploadError: string | null\n /**\n * Send a question, or a comment to the people in a shared thread. While an answer runs, the\n * question waits in the running turn's queue (`queue`) or steers it.\n */\n send: (text: string, options?: { mentions?: AskRequest['mentions'] }) => Promise<void>\n /** Send `text` while the answer runs: the agent takes it into the running turn or queues it. */\n interject: (text: string) => Promise<void>\n /** Follow-ups waiting for the running answer. */\n queue: readonly QueuedMessage[]\n /** Ask `text` again in place of the message after `parentId` (an edit): a new branch. */\n branch: (parentId: string | null, text: string) => Promise<void>\n /** Show another version of a branched message (`ArbiChatMessage.branch`). */\n switchBranch: (messageId: string, index: number) => void\n /** Re-ask the question whose answer failed. */\n retry: () => Promise<void>\n /** Stop the running answer; what streamed so far stays, marked stopped. */\n stop: () => void\n selectThread: (id: string) => void\n newThread: () => void\n /** Deletes the conversation on the backend too. */\n deleteThread: (id: string) => void\n toggleDocument: (id: string) => void\n selectAllDocuments: () => void\n upload: (files: File[]) => Promise<void>\n}\n\n/** First words of a question as a title: whole words, no trailing punctuation, ellipsis when cut. */\nexport function titleFromQuestion(question: string, maxLength = 48): string {\n const flat = question.replace(/\\s+/g, ' ').trim()\n if (flat.length <= maxLength) return flat\n const cut = flat.slice(0, maxLength)\n const lastSpace = cut.lastIndexOf(' ')\n const words = lastSpace > maxLength / 2 ? cut.slice(0, lastSpace) : cut\n return `${words.replace(/[\\s,;:.\\-–—]+$/, '')}…`\n}\n\nconst FAILED_MESSAGE = 'The assistant request failed.'\nconst UNFINISHED_MESSAGE = 'The answer did not finish. Try again.'\nconst NEW = 'new'\n/** No conversation rows (a stable empty list). */\nconst NO_ROWS: readonly WorkflowRunRow[] = []\n\nconst messageOf = (e: unknown, fallback: string) => (e instanceof Error ? e.message : fallback)\n\n/** The signed-in user's id, or null before the session is known. */\nfunction signedInUserId(arbi: { user: { identity: () => { externalId: string } | null } }) {\n try {\n return arbi.user.identity()?.externalId ?? null\n } catch {\n return null\n }\n}\n\n/** A message of the conversation cache as the chat surface shows it. */\nfunction toChatMessage(m: ChatMessage, branch: ArbiChatMessage['branch']): ArbiChatMessage | null {\n if (m.role === 'system') return null\n const running = m.isLoading === true || m.status === 'in_progress' || m.status === 'queued'\n if (m.role === 'user') {\n if (!m.content.trim()) return null\n const workflowStep = workflowStepOf(m.tools)\n return {\n id: m.external_id,\n role: 'user',\n content: m.content,\n status: 'complete',\n ...(workflowStep ? { workflowStep } : {}),\n ...(m.created_by_ext_id ? { authorId: m.created_by_ext_id } : {}),\n ...(m.mentions?.length ? { mentions: m.mentions as AskRequest['mentions'] } : {}),\n ...(branch ? { branch } : {}),\n }\n }\n const failed = m.status === 'failed' || m.isError === true\n const stopped = m.status === 'cancelled'\n if (!m.content.trim() && !running && !failed && !stopped) return null\n const citations = toChatCitations({ tools: m.tools })\n const steps = m.agentSteps ?? []\n return {\n id: m.external_id,\n role: 'assistant',\n content: m.content,\n status: running ? 'streaming' : failed ? 'error' : 'complete',\n ...(stopped ? { stopped: true } : {}),\n ...(failed ? { error: m.status === 'failed' ? FAILED_MESSAGE : UNFINISHED_MESSAGE } : {}),\n ...(running || failed ? {} : { responseId: m.external_id }),\n ...(steps.length > 0 ? { steps, stepCount: steps.length } : {}),\n ...(citations.length > 0 ? { citations } : {}),\n ...(branch ? { branch } : {}),\n }\n}\n\nexport function useConversation(options: UseConversationOptions = {}): ArbiConversation {\n const { agentId, model, titleLength = 48 } = options\n const arbi = useArbi()\n const queryClient = useQueryClient()\n const session = useArbiSessionStore()\n const sessionWorkspaceId = useArbiSessionState((s) => s.workspaceId)\n const workspaceId = options.workspaceId ?? sessionWorkspaceId ?? undefined\n const conversationId = useArbiSessionState((s) => s.conversationId)\n const conversationKey = conversationId ?? NEW\n const generation = useArbiSessionState((s) => s.generating[conversationKey])\n const newConversationMode = useArbiSessionState((s) => s.newConversationAssistantMode)\n const queuedMessages = useArbiSessionState((s) => s.queuedMessages)\n const isRunning = !!generation?.isGenerating\n\n // The surface's workspace and model are the session's while it is mounted.\n useEffect(() => {\n if (workspaceId && session.getState().workspaceId !== workspaceId)\n session.setWorkspaceId(workspaceId)\n }, [session, workspaceId])\n useEffect(() => {\n if (model !== undefined) session.setChatModel(model)\n }, [session, model])\n // An agent chat not sent yet runs through the agent.\n useEffect(() => {\n if (agentId && workspaceId && !conversationId) session.setNewAgentChat({ agentId, workspaceId })\n }, [session, agentId, workspaceId, conversationId])\n\n const { data: docs = [], isLoading: isLoadingDocuments } = useDocuments(workspaceId)\n const ordinaryHistory = useConversations(workspaceId, { enabled: !agentId, live: true })\n const agentHistory = useAgentChats(agentId)\n const stored = useMemo(\n () =>\n agentId\n ? (agentHistory.data ?? [])\n .filter((chat) => chat.workspace_ext_id === workspaceId)\n .map((chat) => ({\n external_id: chat.conversation_ext_id,\n title: chat.title,\n updated_at: chat.updated_at,\n message_count: 1,\n status: null as string | null,\n assistant_mode: 'always' as 'always' | 'mentioned',\n }))\n : (ordinaryHistory.data ?? []),\n [agentId, agentHistory.data, ordinaryHistory.data, workspaceId]\n )\n const isLoadingThreads = agentId ? agentHistory.isLoading : ordinaryHistory.isLoading\n // A saved workflow's untitled run is named after its workflow (and titled so once opened).\n const runTitles = useWorkflowRunTitles(\n agentId ? NO_ROWS : (ordinaryHistory.data ?? NO_ROWS),\n conversationId,\n workspaceId\n )\n\n const data = useConversationData()\n const {\n messageHistory,\n threads: lines,\n threadsLoading,\n threadsError,\n parentMessageId,\n setParentMessageId,\n } = data\n useConnectRunStream(conversationId, messageHistory)\n const { getBranchControlForMessage, switchBranch: showBranch } = useBranchNavigation(\n lines,\n parentMessageId,\n messageHistory,\n setParentMessageId\n )\n\n const actions = useConversationActions({\n selectedWorkspaceId: workspaceId ?? null,\n parentMessageId,\n conversationKey,\n isGenerating: isRunning,\n lastFailedMessage: generation?.lastFailedMessage ?? null,\n })\n\n const [deselected, setDeselected] = useState<ReadonlySet<string>>(new Set())\n const [stagedFiles, setStagedFiles] = useState<Array<{ id: string; name: string }>>([])\n const [isPostingComment, setIsPostingComment] = useState(false)\n const [isUpdatingAssistantMode, setIsUpdatingAssistantMode] = useState(false)\n const [isUploading, setIsUploading] = useState(false)\n const [uploadError, setUploadError] = useState<string | null>(null)\n const [historyError, setHistoryError] = useState<string | null>(null)\n\n // The document selection and staged files belong to one workspace and agent.\n const scope = `${workspaceId ?? ''}:${agentId ?? ''}`\n const [currentScope, setCurrentScope] = useState(scope)\n if (currentScope !== scope) {\n setCurrentScope(scope)\n setDeselected(new Set())\n setStagedFiles([])\n setUploadError(null)\n setHistoryError(null)\n }\n // Another workspace or agent starts on a new chat.\n const [chatScope, setChatScope] = useState(scope)\n useEffect(() => {\n if (chatScope === scope) return\n setChatScope(scope)\n session.startNewConversation()\n }, [chatScope, scope, session])\n\n const assistantMode: 'always' | 'mentioned' = conversationId\n ? cachedAssistantMode(queryClient, conversationId, 'always')\n : newConversationMode\n\n const messages = useMemo(\n () =>\n messageHistory\n .map((m) => {\n const point = getBranchControlForMessage(m.external_id)\n const branch =\n point && point.branches.length > 1\n ? { index: point.currentBranchIndex, count: point.branches.length }\n : undefined\n return toChatMessage(m, branch)\n })\n .filter((m): m is ArbiChatMessage => m !== null),\n [messageHistory, getBranchControlForMessage]\n )\n\n // The list: the chat being written, then the stored conversations, newest first.\n const threads = useMemo(() => {\n const firstQuestion = messages.find((m) => m.role === 'user')?.content ?? ''\n const localTitle = firstQuestion ? titleFromQuestion(firstQuestion, titleLength) : ''\n const persisted = [...stored]\n .filter((c) => c.status != null || c.message_count > 0 || c.external_id === conversationId)\n .sort((a, b) => b.updated_at.localeCompare(a.updated_at))\n .map((c) => ({\n id: c.external_id,\n title:\n c.title ||\n runTitles[c.external_id] ||\n (c.external_id === conversationId ? localTitle : ''),\n }))\n const isListed = persisted.some((t) => t.id === conversationId)\n return [\n ...(conversationId === null\n ? [{ id: NEW, title: localTitle }]\n : isListed\n ? []\n : [{ id: conversationId, title: localTitle }]),\n ...persisted,\n ]\n }, [stored, conversationId, messages, titleLength, runTitles])\n\n const selectedIds = useMemo(\n () =>\n (agentId ? [] : docs)\n .map((d) => d.external_id)\n .filter((id): id is string => !!id && !deselected.has(id)),\n [docs, deselected, agentId]\n )\n const documents = useMemo<ArbiChatDocument[]>(\n () =>\n agentId\n ? stagedFiles.map((file) => ({ ...file, isSelected: !deselected.has(file.id) }))\n : docs\n .filter((d): d is typeof d & { external_id: string } => !!d.external_id)\n .map((d) => ({\n id: d.external_id,\n name: d.file_name ?? d.external_id,\n isSelected: !deselected.has(d.external_id),\n })),\n [docs, deselected, agentId, stagedFiles]\n )\n\n /** The question as the agent gets it: the files staged in its sandbox are named. */\n const withStagedFiles = useCallback(\n (text: string) => {\n const staged = stagedFiles.filter((file) => !deselected.has(file.id))\n if (!agentId || staged.length === 0) return text\n return (\n text +\n '\\n\\nSource files staged in your sandbox:\\n' +\n staged.map((file) => `${file.name}: ${file.id}`).join('\\n')\n )\n },\n [agentId, stagedFiles, deselected]\n )\n\n const { handleSendMessage, handleCreateBranch } = actions\n const assistantName = useAssistantName()\n const send = useCallback(\n async (text: string) => {\n const trimmed = text.trim()\n if (!trimmed || isUpdatingAssistantMode) return\n setHistoryError(null)\n // The turn is grounded on the documents selected here.\n session.setConversationDocuments(\n conversationKey,\n selectedIds.map((docId) => ({ docId, isPinned: false }))\n )\n const candidates = cachedMentionCandidates(\n queryClient,\n workspaceId,\n signedInUserId(arbi),\n assistantName\n )\n const isComment = isCommentToPeople(queryClient, conversationId, trimmed, candidates)\n session.setDraft(isComment ? trimmed : withStagedFiles(trimmed))\n if (isComment) setIsPostingComment(true)\n try {\n await handleSendMessage()\n } finally {\n if (isComment) setIsPostingComment(false)\n }\n },\n [\n isUpdatingAssistantMode,\n session,\n conversationKey,\n selectedIds,\n queryClient,\n workspaceId,\n arbi,\n conversationId,\n withStagedFiles,\n handleSendMessage,\n assistantName,\n ]\n )\n\n const branch = useCallback(\n (parentId: string | null, text: string) => handleCreateBranch(parentId, withStagedFiles(text)),\n [handleCreateBranch, withStagedFiles]\n )\n\n const switchBranch = useCallback(\n (messageId: string, index: number) => {\n const point = getBranchControlForMessage(messageId)\n if (point) showBranch(point, index)\n },\n [getBranchControlForMessage, showBranch]\n )\n\n const retry = useCallback(async () => {\n if (isRunning) return\n if (generation?.lastFailedMessage) {\n await actions.handleRetrySend()\n return\n }\n // A stored answer that failed: ask its question again in its place.\n const failedIndex = messageHistory.findLastIndex(\n (m) => m.role === 'assistant' && (m.status === 'failed' || m.isError)\n )\n const failed = messageHistory[failedIndex]\n const question = failed\n ? (messageHistory.find((m) => m.external_id === failed.parent_message_ext_id) ??\n messageHistory[failedIndex - 1])\n : undefined\n if (!question || question.role !== 'user') return\n await actions.handleRetryOrphanedMessage(\n question.content,\n question.parent_message_ext_id ?? null,\n question.external_id\n )\n }, [isRunning, generation?.lastFailedMessage, actions, messageHistory])\n\n const { handleAbortGeneration } = actions\n const stop = useCallback(() => void handleAbortGeneration(), [handleAbortGeneration])\n\n const setAssistantMode = useCallback(\n async (mode: 'always' | 'mentioned') => {\n if (isRunning || isPostingComment || isUpdatingAssistantMode) return\n if (!conversationId) {\n session.setNewConversationAssistantMode(mode)\n return\n }\n setIsUpdatingAssistantMode(true)\n setHistoryError(null)\n try {\n await arbi.conversations.setAssistantMode(conversationId, mode)\n queryClient.setQueryData<{ assistant_mode?: string }>(\n getThreadsQueryKey(conversationId),\n (old) => (old ? { ...old, assistant_mode: mode } : old)\n )\n void queryClient.invalidateQueries({ queryKey: getThreadsQueryKey(conversationId) })\n void (agentId ? agentHistory.refetch() : ordinaryHistory.refetch())\n } catch (e) {\n setHistoryError(messageOf(e, 'The assistant mode could not be changed.'))\n } finally {\n setIsUpdatingAssistantMode(false)\n }\n },\n [\n isRunning,\n isPostingComment,\n isUpdatingAssistantMode,\n conversationId,\n session,\n arbi,\n queryClient,\n agentId,\n agentHistory,\n ordinaryHistory,\n ]\n )\n\n const newThread = useCallback(() => {\n setHistoryError(null)\n session.startNewConversation()\n }, [session])\n\n const selectThread = useCallback(\n (id: string) => {\n setHistoryError(null)\n if (id === NEW) {\n session.startNewConversation()\n return\n }\n if (agentId) session.setAgentChatOwner(id, agentId)\n session.setConversationId(id)\n },\n [session, agentId]\n )\n\n const deleteThread = useCallback(\n (id: string) => {\n if (id === NEW) {\n session.startNewConversation()\n return\n }\n void (async () => {\n try {\n await arbi.conversations.delete(id)\n removeConversationFromLists(queryClient, id)\n if (session.getState().conversationId === id) session.startNewConversation()\n } catch (e) {\n setHistoryError(messageOf(e, 'The conversation could not be deleted.'))\n }\n })()\n },\n [arbi, queryClient, session]\n )\n\n const toggleDocument = useCallback((id: string) => {\n setDeselected((prev) => {\n const next = new Set(prev)\n if (next.has(id)) next.delete(id)\n else next.add(id)\n return next\n })\n }, [])\n const selectAllDocuments = useCallback(() => setDeselected(new Set()), [])\n\n const upload = useCallback(\n async (files: File[]) => {\n if (files.length === 0) return\n setIsUploading(true)\n setUploadError(null)\n try {\n const uploaded: string[] = []\n for (const file of files) {\n if (agentId) {\n const staged = await arbi.agents.stageFile(agentId, file, file.name)\n setStagedFiles((all) => [\n ...all.filter((existing) => existing.id !== staged.path),\n { id: staged.path, name: staged.name },\n ])\n } else {\n // Into the chat's own workspace, named on the request: a scoped or docked chat's\n // workspace need not be the one open, and a switch meanwhile must not move the file.\n const result = await arbi.documents.upload([file], {\n ...(workspaceId ? { workspaceExtId: workspaceId } : {}),\n })\n uploaded.push(...(result.doc_ext_ids ?? []))\n }\n }\n // New documents are not deselected, so they join the selection by default.\n if (uploaded.length) await refreshDocuments(queryClient, arbi, uploaded)\n } catch (e) {\n setUploadError(messageOf(e, 'The upload failed.'))\n } finally {\n setIsUploading(false)\n }\n },\n [arbi, queryClient, agentId, workspaceId]\n )\n\n const runningAnswer = generation?.streamingAssistantId\n const queue = (runningAnswer && queuedMessages[runningAnswer]) || []\n const last = messages[messages.length - 1]\n\n return {\n assistantMode,\n isUpdatingAssistantMode,\n isPostingComment,\n setAssistantMode,\n threads,\n activeThreadId: conversationKey,\n messages,\n isRunning,\n error: generation?.error ?? (last?.status === 'error' ? (last.error ?? null) : null),\n isLoadingThread: !!conversationId && threadsLoading && !threadsError,\n isLoadingThreads,\n historyError:\n historyError ??\n (threadsError ? messageOf(threadsError, 'The conversation could not be loaded.') : null),\n documents,\n isLoadingDocuments,\n isUploading,\n uploadError,\n send,\n interject: send,\n queue,\n branch,\n switchBranch,\n retry,\n stop,\n selectThread,\n newThread,\n deleteThread,\n toggleDocument,\n selectAllDocuments,\n upload,\n }\n}\n","/**\n * A session of its own for a chat surface: inside it, `useConversation` (and the rest of the chat\n * engine) keeps its own open conversation, line and composer, so a docked or embedded chat does\n * not switch the page's main conversation, and the page does not switch it. Everything else in the\n * host configuration (the client, the host's chat callbacks) is the enclosing host's.\n */\n\nimport { useEffect, useMemo, useState, type ReactNode } from 'react'\nimport { ArbiHost } from '../host'\nimport { createArbiSessionStore, useArbiSessionState } from '../session'\n\nexport interface ConversationScopeProps {\n /** The workspace the scoped chat is in (default: the enclosing session's). */\n workspaceId?: string | null\n /** The conversation it opens on (default: a new chat). */\n conversationId?: string | null\n children: ReactNode\n}\n\nexport function ConversationScope({\n workspaceId,\n conversationId,\n children,\n}: ConversationScopeProps) {\n const outerWorkspaceId = useArbiSessionState((s) => s.workspaceId)\n const scopeWorkspaceId = workspaceId ?? outerWorkspaceId\n const [session] = useState(() =>\n createArbiSessionStore({\n workspaceId: scopeWorkspaceId,\n conversationId: conversationId ?? null,\n })\n )\n useEffect(() => {\n session.setWorkspaceId(scopeWorkspaceId)\n }, [session, scopeWorkspaceId])\n useEffect(() => {\n if (conversationId !== undefined) session.setConversationId(conversationId)\n }, [session, conversationId])\n const config = useMemo(() => ({ session }), [session])\n return <ArbiHost config={config}>{children}</ArbiHost>\n}\n","/**\n * The workspace a conversation is in, for a write that belongs to it (a fact saved from one of its\n * answers, say): the one this client knows it is in (`conversationWorkspaceOf`), else the\n * session's workspace (a new conversation, or one not seen yet).\n */\nimport { useQueryClient } from '@tanstack/react-query'\nimport { useArbiSessionState } from '../session'\nimport { conversationWorkspaceOf } from './conversation-workspace'\n\nexport function useConversationWorkspace(conversationId: string | null | undefined): string | null {\n const queryClient = useQueryClient()\n const sessionWorkspaceId = useArbiSessionState((s) => s.workspaceId)\n return conversationWorkspaceOf(queryClient, conversationId) ?? sessionWorkspaceId\n}\n","/**\n * The conversation events of the server's WebSocket, applied to the cache: a run that ended\n * (`response_complete`), a message somebody else posted (`conversation.message_posted`), a\n * generated title (`conversation.title_updated`) and a thread bound to a document, rebound or\n * unbound by another member or device (`conversation.document_binding_changed`). The cache half\n * of what a host does on them; the\n * session half (generation, the queue box, notices) stays with the host until the engine moves.\n */\n\nimport type { QueryClient } from '@tanstack/react-query'\nimport { arbiQueryKeys } from '../hooks'\nimport { invalidateConversationLists, patchConversation } from '../conversation-list'\nimport {\n getThreadsQueryKey,\n markMessageAsFailed,\n updateUserMessageStateInCache,\n} from './conversation-cache'\n\n/** The conversation events of the server's WebSocket, as `applyConversationEvent` takes them. */\nexport type ConversationEvent =\n | {\n type: 'response_complete'\n /** The conversation the run belongs to (the host resolves it when the event lacks it). */\n conversation_ext_id?: string | null\n response_id?: string | null\n status?: string | null\n /** The follow-up this run answered: no longer waiting. */\n user_message_id?: string | null\n }\n | { type: 'conversation.message_posted'; conversation_ext_id?: string; message_ext_id?: string }\n | { type: 'conversation.title_updated'; conversation_ext_id?: string; title?: string | null }\n | { type: 'conversation.document_binding_changed'; conversation_ext_id?: string }\n\n/** Apply one conversation event of the server's WebSocket to the cache. Other messages are ignored. */\nexport async function applyConversationEvent(\n queryClient: QueryClient,\n event: { type: string; [field: string]: unknown }\n): Promise<void> {\n const e = event as ConversationEvent\n if (e.type === 'response_complete') return applyRunEnded(queryClient, e)\n if (e.type === 'conversation.message_posted') return applyMessagePosted(queryClient, e)\n if (e.type === 'conversation.title_updated' && e.conversation_ext_id) {\n // The generated title, committed after the first turn: the row inserted at the first message\n // (title null) would otherwise stay untitled until the list is read again.\n patchConversation(queryClient, e.conversation_ext_id, { title: e.title ?? null })\n }\n if (e.type === 'conversation.document_binding_changed' && e.conversation_ext_id) {\n // Ids only: the binding is read again under this reader's access (a document they cannot open\n // comes back as unavailable, never by its id).\n void queryClient.invalidateQueries({ queryKey: getThreadsQueryKey(e.conversation_ext_id) })\n void invalidateConversationLists(queryClient)\n }\n}\n\nfunction applyRunEnded(\n queryClient: QueryClient,\n e: Extract<ConversationEvent, { type: 'response_complete' }>\n): void {\n const conversationId = e.conversation_ext_id\n if (!conversationId) return\n const failed = e.status === 'failed'\n if (e.user_message_id) {\n updateUserMessageStateInCache(\n queryClient,\n conversationId,\n e.user_message_id,\n 'completed',\n false\n )\n }\n // A failed answer shows failed at once, so nothing replies to it.\n if (failed && e.response_id) markMessageAsFailed(queryClient, conversationId, e.response_id)\n // The list was patched to in progress when the turn started.\n patchConversation(queryClient, conversationId, {\n last_message_status: failed ? 'failed' : 'completed',\n })\n // The persisted last-turn speaker and time, background replies included.\n void invalidateConversationLists(queryClient)\n void queryClient.invalidateQueries({ queryKey: getThreadsQueryKey(conversationId) })\n // A completed run spent AI usage.\n if (!failed) void queryClient.invalidateQueries({ queryKey: arbiQueryKeys.userUsageToday() })\n}\n\nasync function applyMessagePosted(\n queryClient: QueryClient,\n e: Extract<ConversationEvent, { type: 'conversation.message_posted' }>\n): Promise<void> {\n if (!e.conversation_ext_id) return\n const queryKey = getThreadsQueryKey(e.conversation_ext_id)\n const refreshed = queryClient.invalidateQueries({ queryKey })\n void invalidateConversationLists(queryClient)\n await refreshed\n // A burst can arrive while an earlier refresh is in flight: check that the posted message reached\n // the cache, rather than leaving that earlier snapshot visible.\n const cached = queryClient.getQueryData<{ threads: { history: { external_id: string }[] }[] }>(\n queryKey\n )\n if (\n cached &&\n e.message_ext_id &&\n !cached.threads.some((thread) => thread.history.some((m) => m.external_id === e.message_ext_id))\n ) {\n await queryClient.refetchQueries({ queryKey, type: 'active' })\n }\n}\n","import { useCallback, useEffect, useSyncExternalStore } from 'react'\nimport { useQueryClient } from '@tanstack/react-query'\nimport { notify } from '../shell'\nimport { useConversations } from '../hooks'\nimport { useArbi } from '../useArbi'\nimport { useArbiSessionState, useArbiSessionStore } from '../session'\nimport { bindThreadDocument, migrateLegacyThreadDocuments, threadBinding } from './thread-binding'\n\n/** The workspaces whose locally kept bindings were moved to the server in this visit. */\nconst migratedWorkspaces = new Set<string>()\n\n/**\n * The open conversation's bound document, and how to bind or (null) unbind it. A saved thread's\n * binding is the server's (attach and unbind write it there); a new chat's is the session's until\n * its first turn. `unavailable`: the thread is bound to a document this person cannot open.\n */\nexport function useThreadDocument(): {\n documentId: string | null\n unavailable: boolean\n bind: (documentId: string | null) => void\n} {\n const arbi = useArbi()\n const queryClient = useQueryClient()\n const session = useArbiSessionStore()\n const conversationId = useArbiSessionState((s) => s.conversationId)\n const workspaceId = useArbiSessionState((s) => s.workspaceId)\n const newChatDocumentId = useArbiSessionState((s) => s.newChatDocumentId)\n const subscribe = useCallback(\n (onChange: () => void) => queryClient.getQueryCache().subscribe(onChange),\n [queryClient]\n )\n const savedDocumentId = useSyncExternalStore(\n subscribe,\n () => threadBinding(queryClient, conversationId).documentId,\n () => null\n )\n const unavailable = useSyncExternalStore(\n subscribe,\n () => threadBinding(queryClient, conversationId).unavailable,\n () => false\n )\n\n // Bindings kept on this device before the server held them move there once.\n // (Never from the previous workspace's list, shown while this one loads.)\n const { data: conversations, isPlaceholderData } = useConversations(workspaceId ?? undefined)\n useEffect(() => {\n if (!workspaceId || !conversations || isPlaceholderData || migratedWorkspaces.has(workspaceId))\n return\n migratedWorkspaces.add(workspaceId)\n void migrateLegacyThreadDocuments(arbi, queryClient, conversations)\n }, [arbi, queryClient, workspaceId, conversations, isPlaceholderData])\n\n const bind = useCallback(\n (documentId: string | null) => {\n const { conversationId: open } = session.getState()\n if (!open) {\n session.setNewChatDocumentId(documentId)\n return\n }\n bindThreadDocument(arbi, queryClient, open, documentId).catch(() =>\n notify.error(\n documentId\n ? 'Could not attach the document to this thread'\n : 'Could not unbind the document'\n )\n )\n },\n [arbi, queryClient, session]\n )\n return {\n documentId: conversationId ? savedDocumentId : newChatDocumentId,\n unavailable: conversationId ? unavailable : false,\n bind,\n }\n}\n","/**\n * Resolve the model a config actually runs with.\n *\n * Model selection is stored asymmetrically: in agentic mode the picked model\n * lives in `Agents.AGENT_MODEL_NAME` (and `QueryLLM.MODEL_NAME` goes stale),\n * otherwise it lives in `QueryLLM.MODEL_NAME`. Reading only QueryLLM is what\n * made the selector snap back to the stale model after a message round-trip.\n */\ninterface ConfigWithModel {\n QueryLLM?: { MODEL_NAME?: string }\n Agents?: { ENABLED?: boolean; AGENT_MODEL_NAME?: string }\n}\n\nexport function resolveConfigModel(config: ConfigWithModel): string | undefined {\n if (config.Agents?.ENABLED && config.Agents.AGENT_MODEL_NAME) {\n return config.Agents.AGENT_MODEL_NAME\n }\n return config.QueryLLM?.MODEL_NAME\n}\n","import { useMutation, useQueryClient } from '@tanstack/react-query'\nimport { useArbi } from '../useArbi'\nimport { allConversationThreads } from './conversation-cache'\n\n/**\n * Delete a message and every message after it on its branch (a failed answer, say). Which\n * conversation it was in is not known here, so every cached thread is re-read: they are small.\n */\nexport function useDeleteMessage() {\n const arbi = useArbi()\n const queryClient = useQueryClient()\n return useMutation({\n mutationFn: (messageId: string) => arbi.conversations.deleteMessage(messageId),\n onSuccess: () => queryClient.invalidateQueries(allConversationThreads),\n })\n}\n","/**\n * The open conversation's turn: whether an answer runs, the last send's failure, and the actions on\n * it (send, branch, retry, stop) from `useConversationActions`. The generation state lives in the\n * session, so it survives leaving the conversation and coming back.\n */\n\nimport { useArbiSessionState } from '../session'\nimport { useConversationActions } from './useConversationActions'\n\ninterface UseConversationTurnProps {\n selectedWorkspaceId: string | null\n parentMessageId: string | null\n}\n\nexport function useConversationTurn({\n selectedWorkspaceId,\n parentMessageId,\n}: UseConversationTurnProps) {\n const currentConversationId = useArbiSessionState((state) => state.conversationId)\n const conversationKey = currentConversationId || 'new'\n const generationState = useArbiSessionState((state) => state.generating[conversationKey])\n\n const isGenerating = generationState?.isGenerating ?? false\n const generationError = generationState?.error ?? null\n const lastFailedMessage = generationState?.lastFailedMessage ?? null\n\n const actions = useConversationActions({\n selectedWorkspaceId,\n parentMessageId,\n conversationKey,\n isGenerating,\n lastFailedMessage,\n })\n\n return {\n isGenerating,\n hasError: !!generationError,\n lastFailedMessage,\n lastErrorMessage: generationError,\n ...actions,\n }\n}\n","/**\n * The configuration new work runs with: the one chosen for the next message (`session.chatModel`),\n * else the one the replied-to message ran with (`session.cursor`), else the person's last one.\n */\n\nimport { useMemo } from 'react'\nimport { useUserSettings } from '../account/settings'\nimport { useArbiSessionState } from '../session'\nimport { useConversationData } from './useConversationData'\n\nexport function useActiveConfigId(): string | undefined {\n const chatModel = useArbiSessionState((s) => s.chatModel)\n const cursor = useArbiSessionState((s) => s.cursor)\n const { messageHistory } = useConversationData()\n const { data: userSettings } = useUserSettings()\n return useMemo(() => {\n if (chatModel) return chatModel\n const parent = cursor ? messageHistory?.find((m) => m.external_id === cursor) : undefined\n if (parent?.config_ext_id) return parent.config_ext_id\n return userSettings?.last_config ?? undefined\n }, [chatModel, cursor, messageHistory, userSettings?.last_config])\n}\n","/**\n * Hook that manages documents associated with a conversation\n *\n * Simple approach: uses the session's 'in conversation' documents\n * and performs one-time extraction from parent message when conversation/parent changes\n */\n\nimport React from 'react'\nimport type { components } from '@arbidocs/client'\nimport { useArbiSessionState } from '../session'\nimport { useDocuments } from '../documents/documents-data'\n\ntype Doc = components['schemas']['DocResponse']\n\nconst EMPTY_DOCS: Array<{ docId: string; isPinned: boolean }> = []\n\nexport function useConversationDocuments() {\n const currentConversationId = useArbiSessionState((state) => state.conversationId)\n const convKey = currentConversationId || 'new'\n const inConversationDocuments = useArbiSessionState(\n (state) => state.conversationDocuments[convKey] || EMPTY_DOCS\n )\n\n // Get all workspace documents to get full document objects\n const { data: documents = [], isLoading: isLoadingDocs } = useDocuments()\n\n // No useEffect - zustand handles change detection\n // Documents are managed through direct zustand actions:\n // - Manual: addToConversationDocuments/removeFromConversationDocuments\n // - Auto-extract: called explicitly when parentMessageId actually changes (not here)\n\n // Filter documents that are marked as 'in conversation'\n const conversationDocuments = React.useMemo(() => {\n if (inConversationDocuments.length === 0) {\n return []\n }\n\n // Make sure documents is an array\n const docArray = Array.isArray(documents) ? documents : []\n\n // Create a map for quick lookup of conversation document IDs\n const conversationDocMap = new Map(\n inConversationDocuments.map((doc) => [doc.docId, doc.isPinned])\n )\n\n // Filter documents to only include those marked as 'in conversation'\n const filteredDocs = docArray.filter((doc) => {\n if (!doc || !('external_id' in doc)) {\n return false\n }\n const docId = (doc as { external_id: string }).external_id\n if (!docId || docId === '') {\n return false\n }\n return conversationDocMap.has(docId)\n })\n\n return filteredDocs as Doc[]\n }, [documents, inConversationDocuments])\n\n return {\n data: conversationDocuments,\n isLoading: isLoadingDocs,\n isError: false,\n }\n}\n","/**\n * useDocumentAutoAdd Hook\n *\n * Automatically adds all documents to conversation context\n * while the chat is empty. Populated chats keep their chosen sources.\n */\n\nimport { useEffect, useRef } from 'react'\nimport { notify } from '../shell'\nimport { useArbiSessionState, useArbiSessionStore } from '../session'\n\n/** A document the conversation may read: only its id matters here. */\ntype Doc = { external_id: string }\n\ninterface UseDocumentAutoAddOptions {\n selectedWorkspaceId: string | null\n allWorkspaceDocuments: Doc[]\n /** Existing messages (including a saved conversation still loading) freeze auto-add. */\n hasContent?: boolean\n}\n\nexport function useDocumentAutoAdd({\n selectedWorkspaceId,\n allWorkspaceDocuments,\n hasContent = false,\n}: UseDocumentAutoAddOptions) {\n const session = useArbiSessionStore()\n const currentConversationId = useArbiSessionState((state) => state.conversationId)\n\n const convKey = currentConversationId || 'new'\n const observedRef = useRef<{ key: string; ids: Set<string> } | null>(null)\n const offeredRef = useRef(new Set<string>())\n\n useEffect(() => {\n if (!selectedWorkspaceId) return\n const docs = (allWorkspaceDocuments ?? []).filter((doc) => doc?.external_id)\n if (!docs.length) return\n\n const state = session.getState()\n const current = state.conversationDocuments[convKey]\n const autoAdd = state.conversationDocumentAutoAdd[convKey]\n const key = `${selectedWorkspaceId}:${convKey}`\n const previous = observedRef.current\n const arrivals =\n previous?.key === key ? docs.filter((doc) => !previous.ids.has(doc.external_id)) : []\n observedRef.current = { key, ids: new Set(docs.map((doc) => doc.external_id)) }\n const selected = new Set((current ?? []).map((doc) => doc.docId))\n const missing = docs.filter((doc) => !selected.has(doc.external_id))\n const legacySelection = autoAdd === undefined && current !== undefined\n\n // Old drafts have no selection provenance. Offer the missing sources; never\n // guess whether an old partial/empty selection was automatic or deliberate.\n if (hasContent || legacySelection || autoAdd === false) {\n const available = (legacySelection && !hasContent ? missing : arrivals).filter(\n (doc) => !selected.has(doc.external_id)\n )\n const offerKey = `${key}:${available\n .map((doc) => doc.external_id)\n .sort()\n .join(',')}`\n if (\n available.length &&\n (convKey !== 'new' || current !== undefined) &&\n !offeredRef.current.has(offerKey)\n ) {\n offeredRef.current.add(offerKey)\n notify.info(\n `${available.length} workspace document${available.length === 1 ? '' : 's'} available to add`,\n {\n record: false,\n workspaceId: selectedWorkspaceId,\n duration: 10000,\n action: {\n label: 'Add to chat',\n onClick: () => {\n const latest = session.getState()\n if (\n latest.workspaceId !== selectedWorkspaceId ||\n (latest.conversationId || 'new') !== convKey ||\n // The 'new' slot is reused after sending. Its immutable selection\n // object identifies the draft this offer was actually made for.\n (convKey === 'new' && latest.conversationDocuments.new !== current)\n )\n return\n const existing = latest.conversationDocuments[convKey] ?? []\n const included = new Set(existing.map((doc) => doc.docId))\n session.setConversationDocuments(convKey, [\n ...existing,\n ...available\n .filter((doc) => !included.has(doc.external_id))\n .map((doc) => ({ docId: doc.external_id, isPinned: false })),\n ])\n },\n },\n }\n )\n }\n return\n }\n if (autoAdd && !missing.length) return\n session.setConversationDocuments(\n convKey,\n [...(current ?? []), ...missing.map((doc) => ({ docId: doc.external_id, isPinned: false }))],\n true\n )\n }, [selectedWorkspaceId, convKey, allWorkspaceDocuments, hasContent, session])\n}\n","/**\n * Fires the composer's send once when a quick-access surface (the workspace\n * home's ask bar) handed over a draft that should send on arrival — the user\n * already pressed Enter there; asking for a second Enter here would turn one\n * action into two.\n *\n * `ready` defers consumption: the flag stays set (and the effect re-runs when\n * `ready` flips) so the send can wait for the page's context to assemble —\n * concretely, the workspace documents that useDocumentAutoAdd attaches to a\n * new chat. Sending before that seeding posts the question with no documents,\n * which answers from nothing. The CALL SITE must sit after useDocumentAutoAdd\n * in the component: effects run in declaration order, so that placement is\n * what guarantees the seeding effect has run by the time this one fires.\n *\n * One-shot: the flag is cleared before sending, so a failed send never\n * retries itself.\n */\n\nimport { useEffect } from 'react'\nimport { selectDraft, useArbiSessionState, useArbiSessionStore } from '../session'\n\nexport function useAutoSendDraft(sendDraft: () => void, ready: boolean = true) {\n const session = useArbiSessionStore()\n const autoSendDraft = useArbiSessionState((state) => state.autoSendDraft)\n useEffect(() => {\n if (!autoSendDraft || !ready) return\n session.setAutoSendDraft(false)\n if (selectDraft(session.getState()).trim()) {\n sendDraft()\n }\n }, [autoSendDraft, ready, sendDraft, session])\n}\n","/**\n * A question left without its answer: the answer failed on the server, or it never started (the\n * server crashed or timed out, and the person came back later). The composer then offers Retry.\n */\n\nimport type { ChatMessage as Message } from '@arbidocs/sdk/browser'\n\n/**\n * Detects if a user message is orphaned (has no following assistant response)\n *\n * A message is considered orphaned if:\n * - It's a user message\n * - It's the last message in the thread OR the next message is not an assistant message\n * - It's not currently generating (not marked as isLoading)\n *\n * @param message The message to check\n * @param index The index of the message in the message history\n * @param messageHistory The full message history\n * @param isGenerating Whether a message is currently being generated\n * @returns true if the message is orphaned\n */\nexport function isOrphanedUserMessage(\n message: Message,\n index: number,\n messageHistory: Message[],\n isGenerating: boolean\n): boolean {\n // Only user messages can be orphaned\n if (message.role !== 'user') {\n return false\n }\n\n // Don't show orphan UI if we're currently generating\n if (isGenerating) {\n return false\n }\n\n // Check if this is the last message\n const isLastMessage = index === messageHistory.length - 1\n\n if (isLastMessage) {\n return true\n }\n\n // Check if the next message is an assistant message\n // Backend only saves complete messages, so if there's an assistant message, it's complete\n const nextMessage = messageHistory[index + 1]\n const hasAssistantResponse = nextMessage?.role === 'assistant'\n\n return !hasAssistantResponse\n}\n\n/**\n * Checks if the conversation has an orphaned last message\n * This is used to show the error alert at the bottom and disable the send button\n *\n * A message is incomplete if it has isLoading=true, meaning the final metadata from\n * the SSE stream was never received (which confirms the message exists in the DB).\n *\n * @param messageHistory The full message history\n * @param isGenerating Whether a message is currently being generated\n * @returns The orphaned user message if found, null otherwise\n */\nexport function getOrphanedLastMessage(\n messageHistory: Message[],\n isGenerating: boolean,\n assistantMode: 'always' | 'mentioned' = 'always'\n): Message | null {\n // Don't show orphan UI while actively generating\n if (isGenerating || !messageHistory || messageHistory.length === 0) {\n return null\n }\n\n // Defensive: if any message in history is still streaming (isLoading=true),\n // suppress the orphan alert even when the Zustand isGenerating flag hasn't\n // caught up. Otherwise a brief flag/state race makes the red \"Response\n // Incomplete\" banner flash while the assistant is mid-reply.\n if (messageHistory.some((m) => m.isLoading === true)) {\n return null\n }\n\n const lastMessage = messageHistory[messageHistory.length - 1]\n\n // Case 1: Backend explicitly marked the response as failed\n if (lastMessage.role === 'assistant' && lastMessage.status === 'failed') {\n if (messageHistory.length >= 2) {\n const secondToLast = messageHistory[messageHistory.length - 2]\n if (secondToLast.role === 'user') {\n return secondToLast\n }\n }\n }\n\n // Case 2: User message with no assistant response — but only if it was loaded\n // from the API (not created in the current session). Messages created during\n // streaming have isLoading=true; messages from the API don't have it set.\n // This catches the case where the backend never started generating at all\n // (e.g. crash, timeout) and the user returns to the conversation later.\n if (lastMessage.role === 'user' && !lastMessage.isLoading) {\n // In a thread (`mentioned` mode) a message that did not @mention the assistant is a comment\n // between people: it was never meant to get a reply, so it is not orphaned.\n if (\n assistantMode === 'mentioned' &&\n !(lastMessage.mentions ?? []).some((m) => m.type === 'assistant')\n ) {\n return null\n }\n return lastMessage\n }\n\n return null\n}\n","import type { ChatMessage as Message } from '@arbidocs/sdk/browser'\n\n/**\n * The first turn of a brand-new chat, before the server has confirmed it.\n *\n * The conversation only gets an id when the server's `arbi.user_message` event\n * arrives, and that can take many seconds. Until then the thread has nothing to\n * show, so the question would vanish and the empty state would sit there while\n * the answer is generating. These two local-only messages stand in for the\n * question and for the streaming answer. They are never written to the cache;\n * the real thread replaces them as soon as it exists.\n */\nexport function buildPendingFirstTurn(prompt: string, userExtId: string): Message[] {\n const createdAt = new Date().toISOString()\n const question: Message = {\n external_id: 'pending-user-message',\n role: 'user',\n content: prompt,\n tokens: 0,\n status: 'completed',\n created_at: createdAt,\n created_by_ext_id: userExtId,\n conversation_ext_id: '',\n isLoading: true,\n }\n const answer: Message = {\n external_id: 'pending-assistant-message',\n role: 'assistant',\n content: '',\n tokens: 0,\n status: 'in_progress',\n created_at: createdAt,\n created_by_ext_id: '',\n conversation_ext_id: '',\n isLoading: true,\n }\n return [question, answer]\n}\n","import { useCallback } from 'react'\nimport { useQueryClient } from '@tanstack/react-query'\nimport { useArbi } from '../useArbi'\nimport { clearUserInputRequest } from './conversation-cache'\n\n/** The agent's question an answer is for: its message, in its conversation. */\nexport interface AgentQuestionRef {\n assistantMessageExtId: string\n conversationExtId: string\n}\n\n/**\n * Answer the question a running turn paused on (ask_user): the answer goes into the turn, and the\n * question leaves the cached message so it is no longer offered. Rejects when the send fails.\n */\nexport function useAnswerAgentQuestion() {\n const arbi = useArbi()\n const queryClient = useQueryClient()\n return useCallback(\n async (question: AgentQuestionRef, answer: string) => {\n await arbi.assistant.interject(question.assistantMessageExtId, answer)\n clearUserInputRequest(queryClient, question.conversationExtId, question.assistantMessageExtId)\n },\n [arbi, queryClient]\n )\n}\n","/**\n * The open conversation's settings: its title and sharing (one PATCH of the conversation, which\n * the server resolves from the conversation's own workspace), and the model its next turn runs on.\n * The views are `ConnectedConversationSettings` in `@arbidocs/blocks`.\n */\n\nimport { useCallback, useEffect, useState } from 'react'\nimport { useConfig } from '../hooks'\nimport { useUserSettings } from '../account/settings'\nimport { isFullConfig } from '../config/config-hooks'\nimport { useArbiSessionState, useArbiSessionStore } from '../session'\nimport { useArbiSession } from '../session/signed-in'\nimport { useConversationItems, useUpdateConversation } from '../workforce'\nimport { resolveConfigModel } from './config-model'\nimport { useConversationData } from './useConversationData'\n\n/** Longest title the server keeps. */\nconst TITLE_MAX = 50\n\nexport function useConversationSettings() {\n const session = useArbiSessionStore()\n const conversationId = useArbiSessionState((s) => s.conversationId)\n const chatModel = useArbiSessionState((s) => s.chatModel)\n const parentMessageId = useArbiSessionState((s) => s.cursor)\n const currentUser = useArbiSession().user\n\n const { messageHistory } = useConversationData()\n const { conversations } = useConversationItems()\n const { data: userSettings } = useUserSettings()\n\n // The config the next turn runs on: the one picked, else the parent message's, else the user's\n // last saved one, else the system default.\n const parentMessage = messageHistory?.find((m) => m.external_id === parentMessageId)\n const configToLoad =\n chatModel || parentMessage?.config_ext_id || userSettings?.last_config || 'default'\n const { data: activeConfig } = useConfig(configToLoad)\n const { refetch: refetchSystemDefaults } = useConfig('default')\n\n const conversation = conversations.find((c) => c.external_id === conversationId)\n const isOwner = !!conversation && conversation.created_by_ext_id === currentUser?.external_id\n const isShared = conversation?.is_shared ?? false\n\n const [title, setTitle] = useState('')\n useEffect(() => {\n setTitle(conversation?.title || '')\n }, [conversation?.title])\n\n // The picker shows the model of the config the next turn runs on.\n useEffect(() => {\n if (isFullConfig(activeConfig)) session.setChatModelName(resolveConfigModel(activeConfig))\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [activeConfig, configToLoad])\n\n // Rename, share and unshare are all the one PATCH; which is in flight shows in its body.\n const update = useUpdateConversation()\n const pending = update.isPending ? update.variables?.patch : undefined\n\n const saveTitle = useCallback(() => {\n const trimmed = title.trim()\n if (!conversationId || !isOwner || !trimmed || trimmed.length > TITLE_MAX) return\n // Leaving the field without a change sends nothing.\n if (trimmed === conversation?.title) return\n update.mutate({ conversationId, patch: { title: trimmed } })\n }, [conversationId, isOwner, title, conversation?.title, update])\n\n const setShared = useCallback(\n (shared: boolean) => {\n if (!conversationId || !isOwner || isShared === shared) return\n update.mutate({ conversationId, patch: { shared } })\n },\n [conversationId, isOwner, isShared, update]\n )\n const share = useCallback(() => setShared(true), [setShared])\n const unshare = useCallback(() => setShared(false), [setShared])\n\n /** Back to the system default config: the picked one is dropped. */\n const resetToDefaults = useCallback(async () => {\n try {\n const { data } = await refetchSystemDefaults()\n session.setChatModel(undefined)\n if (isFullConfig(data)) session.setChatModelName(resolveConfigModel(data))\n } catch (error) {\n console.error('Failed to reset to system defaults:', error)\n }\n }, [refetchSystemDefaults, session])\n\n return {\n /** No message yet: nothing to title or share. */\n isNewConversation: !parentMessageId,\n title,\n setTitle,\n isOwner,\n isShared,\n isSavingTitle: pending !== undefined && 'title' in pending,\n isSharing: pending !== undefined && 'shared' in pending,\n saveTitle,\n share,\n unshare,\n resetToDefaults,\n }\n}\n","/**\n * \"Ask again\" on a stopped answer: run its question again, straight away.\n *\n * - The question is sent again from where it was first asked, so the new answer replaces the\n * stopped one as a branch (as an unchanged edit would). The first question of a conversation\n * has nothing before it, so it is asked again as a follow-up to the stopped answer.\n * - While another turn is running, the question goes in the composer rather than racing it.\n */\n\nimport { useCallback, useEffect, useRef } from 'react'\nimport type { ChatMessage } from '@arbidocs/sdk/browser'\nimport { useArbiSessionStore } from '../session'\nimport { refuseChatWhenOffline } from './turn-control'\n\n/**\n * Re-run the question of a stopped answer.\n *\n * @param question The person's question the stopped answer replied to\n * @param stoppedAnswer The stopped answer itself\n */\nexport type AskAgain = (question: ChatMessage, stoppedAnswer: ChatMessage) => void\n\nexport interface UseAskAgainOptions {\n isGenerating: boolean\n /** Send `content` as ARBI's next turn after `parentMessageExtId`. */\n handleCreateBranch: (parentMessageExtId: string | null, content: string) => Promise<void>\n}\n\nexport function useAskAgain(options: UseAskAgainOptions): AskAgain {\n const session = useArbiSessionStore()\n // A stable callback (it is a context value for every message), reading the latest options.\n const optionsRef = useRef(options)\n useEffect(() => {\n optionsRef.current = options\n })\n return useCallback(\n (question: ChatMessage, stoppedAnswer: ChatMessage) => {\n const { isGenerating, handleCreateBranch } = optionsRef.current\n const content = question.content.trim()\n if (!content) return\n if (isGenerating) {\n session.setDraft(content)\n return\n }\n if (refuseChatWhenOffline()) return\n // Leave any open edit: the new turn must show.\n session.completeEditing()\n void handleCreateBranch(\n question.parent_message_ext_id ?? stoppedAnswer.external_id ?? null,\n content\n )\n },\n [session]\n )\n}\n","/**\n * useThinkingContent Hook\n *\n * Extracts thinking content from AI message responses.\n * Handles both explicit <think> tags and model-specific thinking patterns.\n * Returns parsed thinking content and response content separately.\n */\n\nimport { useMemo } from 'react'\n\ninterface ThinkingContentResult {\n /** The main response content (without thinking tags) */\n responseContent: string\n /** The extracted thinking/reasoning content */\n thinkingContent: string\n /** Whether the model is currently in thinking mode */\n isThinking: boolean\n /** Whether the message contains thinking content */\n hasThinkTag: boolean\n}\n\ninterface UseThinkingContentOptions {\n /** The raw message content */\n content: string\n /** The model name to check for model-specific behavior */\n modelName: string | null\n /** Whether the message is from the user (skip processing) */\n isUser: boolean\n /** Whether the message is currently being generated */\n isGenerating: boolean\n}\n\n/**\n * Hook to extract thinking content from AI responses.\n * Some models use explicit <think></think> tags, while others\n * (like Q235T@ARBICITY) start with thinking content implicitly.\n */\nexport function useThinkingContent({\n content,\n modelName,\n isUser,\n isGenerating,\n}: UseThinkingContentOptions): ThinkingContentResult {\n return useMemo(() => {\n // Default values for user messages or empty content\n if (isUser || !content) {\n return {\n responseContent: content || '',\n thinkingContent: '',\n isThinking: false,\n hasThinkTag: false,\n }\n }\n\n const isQ235TModel = modelName === 'Q235T@ARBICITY'\n const hasCloseThinkTag = content.includes('</think>')\n const closeThinkIndex = content.indexOf('</think>')\n\n let responseContent = content\n let thinkingContent = ''\n let isThinking = false\n let hasThinkTag = false\n\n // Determine thinking start position\n let thinkStartPos = -1\n let beforeThinkContent = ''\n\n if (isQ235TModel) {\n // Q235T@ARBICITY: No <think> tag, content starts as thinking at position 0\n hasThinkTag = true\n thinkStartPos = 0\n } else if (content.includes('<think>')) {\n // Other models: Look for explicit <think> tag\n hasThinkTag = true\n const thinkIndex = content.indexOf('<think>')\n thinkStartPos = thinkIndex + 7\n beforeThinkContent = content.substring(0, thinkIndex).trim()\n }\n\n // Process thinking content if we have thinking\n if (hasThinkTag && thinkStartPos >= 0) {\n if (hasCloseThinkTag) {\n // Complete thinking block\n thinkingContent = content.substring(thinkStartPos, closeThinkIndex).trim()\n responseContent = beforeThinkContent\n const afterThinking = content.substring(closeThinkIndex + 8).trim()\n if (afterThinking) {\n responseContent = responseContent + (responseContent ? ' ' : '') + afterThinking\n }\n } else {\n // Still thinking - only if actively generating\n thinkingContent = content.substring(thinkStartPos).trim()\n responseContent = beforeThinkContent\n // Only mark as \"thinking\" if actively generating (not aborted/stopped)\n isThinking = isGenerating && thinkingContent.length > 0\n }\n } else if (hasCloseThinkTag) {\n // Orphan `</think>` with no matching `<think>` — vLLM's qwen3 reasoning\n // parser sometimes strips the opening tag while leaving the closing one\n // (and a model may emit several closing tags). Treat everything up to\n // the LAST `</think>` as leaked reasoning and surface what follows as\n // the real answer, so users don't see raw `</think>` in their replies.\n const lastClose = content.lastIndexOf('</think>')\n hasThinkTag = true\n thinkingContent = content.substring(0, lastClose).trim()\n responseContent = content.substring(lastClose + 8).trim()\n }\n\n // Final defensive sweep: strip any stray <think>/</think> tags that\n // survived the parsing above (e.g. extra opening or closing tags from a\n // model that emitted nested or unbalanced reasoning markers).\n responseContent = responseContent.replace(/<\\/?think>/gi, '').trim()\n thinkingContent = thinkingContent.replace(/<\\/?think>/gi, '').trim()\n\n return {\n responseContent,\n thinkingContent,\n isThinking,\n hasThinkTag,\n }\n }, [content, modelName, isUser, isGenerating])\n}\n","/**\n * The time an answer has taken: counted on the client while its turn runs (separately from the\n * server's step times), and saved when it stops showing, so a finished answer keeps its time and a\n * re-attached run keeps counting from its real start.\n */\n\nimport { useEffect, useRef, useState } from 'react'\nimport { useArbiSessionState, useArbiSessionStore } from '../session'\n\nexport interface UseMessageTimerOptions {\n conversationId: string | undefined\n messageId: string | undefined\n isUser: boolean\n isGenerating: boolean\n}\n\nexport interface MessageTimerResult {\n /** Seconds. */\n elapsedTime: number\n}\n\nexport function useMessageTimer({\n conversationId,\n messageId,\n isUser,\n isGenerating,\n}: UseMessageTimerOptions): MessageTimerResult {\n const session = useArbiSessionStore()\n const convId = conversationId || 'new'\n const timerKey = `${convId}:${messageId}`\n\n const generationStartTime = useArbiSessionState((s) => s.generating[convId]?.startTime ?? null)\n const storedElapsed = useArbiSessionState((s) => s.messageTimers[timerKey]?.elapsedTime)\n\n const [elapsedTime, setElapsedTime] = useState(0)\n // The latest elapsed time, for the cleanup to save without depending on it.\n const lastElapsedRef = useRef(0)\n\n // A finished answer shows its saved time.\n useEffect(() => {\n if (!isUser && !isGenerating && storedElapsed) setElapsedTime(storedElapsed)\n }, [isUser, isGenerating, storedElapsed])\n\n // Count while the turn runs. The cleanup saves the final time through the store's current state,\n // so the saved timer is not a dependency (saving would re-run the effect, which saves again...).\n useEffect(() => {\n if (isUser || !isGenerating || !generationStartTime) return\n const startTime = generationStartTime\n const key = timerKey\n const interval = setInterval(() => {\n const elapsed = (Date.now() - startTime) / 1000\n lastElapsedRef.current = elapsed\n setElapsedTime(elapsed)\n }, 100)\n return () => {\n clearInterval(interval)\n const finalElapsed = lastElapsedRef.current || (Date.now() - startTime) / 1000\n session.setMessageTimer(key, { startTime, elapsedTime: finalElapsed })\n }\n }, [isUser, isGenerating, generationStartTime, timerKey, session])\n\n return { elapsedTime }\n}\n","/**\n * Run-control commands to a running agent turn. Choosing Pause in the turn bar's menu and typing\n * `/pause` in the composer are the same act: both send the command's text as an interjection\n * (`arbi.assistant.interject`), and the backend dispatches it. There is no dedicated control\n * endpoint; the menu is a shortcut for the slash command.\n *\n * Each action also sets an optimistic state in the session, because the loop only confirms at its\n * next boundary (`paused` / `running`) and a probe answers in the background. The\n * `arbi.agent_control_state` and `arbi.probe_answer` events then confirm or correct it.\n */\n\nimport { useCallback } from 'react'\nimport { useArbi } from '../useArbi'\nimport { useArbiSessionStore } from '../session'\nimport { AGENT_CONTROL_COMMANDS } from './turn-control'\n\nexport function useAgentRunControl(assistantMessageExtId: string | null) {\n const arbi = useArbi()\n const session = useArbiSessionStore()\n\n const send = useCallback(\n (command: string) => {\n if (!assistantMessageExtId) return\n // Fire and forget: the control events confirm or correct the optimistic state.\n void arbi.assistant.interject(assistantMessageExtId, command).catch(() => {})\n },\n [assistantMessageExtId, arbi]\n )\n\n const pause = useCallback(() => {\n if (!assistantMessageExtId) return\n session.setAgentControlState(assistantMessageExtId, 'pausing')\n send(AGENT_CONTROL_COMMANDS.pause)\n }, [assistantMessageExtId, session, send])\n\n const resume = useCallback(() => {\n if (!assistantMessageExtId) return\n session.setAgentControlState(assistantMessageExtId, 'resuming')\n send(AGENT_CONTROL_COMMANDS.resume)\n }, [assistantMessageExtId, session, send])\n\n const report = useCallback(() => {\n if (!assistantMessageExtId) return\n session.setAgentProbePending(assistantMessageExtId, true)\n send(AGENT_CONTROL_COMMANDS.report)\n }, [assistantMessageExtId, session, send])\n\n return { pause, resume, report }\n}\n","/**\n * Chat Bubble Component\n * iMessage / WhatsApp-style message bubble with read receipts and\n * consecutive-message grouping.\n *\n * Promoted from the ARBI app. To keep `@arbidocs/react` light (peers react /\n * react-dom only), the two host-owned concerns — rendering the message body\n * (the app's heavy markdown renderer) and formatting the timestamp — are\n * injected via the optional `renderMessage` / `formatTimestamp` props. Both\n * default to plain text so the component works standalone; the ARBI app shim\n * wires in `<MarkdownRenderer>` and `formatFriendlyDate` for identical output.\n */\n\nimport { memo, useState, type ReactNode } from 'react'\nimport { Trash2, Check, CheckCheck, Link } from 'lucide-react'\nimport { cn } from '../lib/utils'\n\n/** Animated typing indicator (three bouncing dots) */\nexport const TypingIndicator = memo(function TypingIndicator() {\n return (\n <div className=\"flex w-full justify-start mb-2\" data-testid=\"dm-typing-indicator\">\n <div className=\"bg-card border border-primary rounded-2xl rounded-bl-md px-4 py-2.5\">\n <div className=\"flex gap-1 items-center\">\n <span className=\"w-1.5 h-1.5 rounded-full bg-muted-foreground animate-bounce [animation-delay:0ms]\" />\n <span className=\"w-1.5 h-1.5 rounded-full bg-muted-foreground animate-bounce [animation-delay:150ms]\" />\n <span className=\"w-1.5 h-1.5 rounded-full bg-muted-foreground animate-bounce [animation-delay:300ms]\" />\n </div>\n </div>\n </div>\n )\n})\n\nexport interface ChatBubbleProps {\n message: string\n timestamp: string\n isSent: boolean\n deleted?: boolean\n read?: boolean\n onDelete?: () => void\n /**\n * Copy a shareable deep link to this exact message. Optional — the host\n * builds the URL (it knows the workspace/deployment domain, the light\n * package doesn't), this just renders the affordance and calls back.\n */\n onCopyLink?: () => void\n /** Stable DOM anchor for scroll-to-message (a notification deep link, a\n * \"jump to this message\" action). Typically the message's external id. */\n id?: string\n /** Last bubble in a same-sender run; shows the timestamp and read receipt. */\n isLastOfRun?: boolean\n /**\n * Who sent it. Rendered in the meta row on the last bubble of a run, so a\n * thread that needs attribution (a group, or a rail-less list where the peer\n * isn't in a header) gets it without a row per message.\n */\n senderName?: string\n /** Per-slot brand overrides, so a consumer pins its accent in one place. */\n classNames?: {\n /** The current user's own bubble. */\n ownBubble?: string\n /** The peer's bubble. */\n peerBubble?: string\n }\n /**\n * Render the message body. Injected by the host so the light package doesn't\n * depend on the app's markdown renderer. Defaults to plain text.\n */\n renderMessage?: (message: string) => ReactNode\n /**\n * Format the timestamp shown on the last bubble of a run. Defaults to the\n * raw string.\n */\n formatTimestamp?: (timestamp: string) => string\n /**\n * Rendered inside the bubble under the text — e.g. a message's attached\n * files. The host owns fetching and decrypting them. A message with\n * attachments and no text shows only these.\n */\n attachments?: ReactNode\n /** Marks the message row, including the deleted tombstone. */\n 'data-testid'?: string\n}\n\nexport const ChatBubble = memo(function ChatBubble({\n message,\n timestamp,\n isSent,\n deleted,\n read,\n onDelete,\n onCopyLink,\n id,\n isLastOfRun = true,\n senderName,\n classNames,\n renderMessage = (m) => m,\n formatTimestamp = (t) => t,\n attachments,\n 'data-testid': testId,\n}: ChatBubbleProps) {\n const [isHovered, setIsHovered] = useState(false)\n const [isFocused, setIsFocused] = useState(false)\n const showActions = isHovered || isFocused\n\n // No \"edited\" indicator: `updated_at` is also bumped by read-state\n // patches, so we can't tell a real content edit from a recipient\n // marking the message as read. The created_at timestamp is the only\n // honest signal we can show here.\n\n if (deleted) {\n return (\n <div\n id={id}\n data-testid={testId}\n className={`flex w-full ${isSent ? 'justify-end' : 'justify-start'} mb-2`}\n >\n <div className=\"text-sm text-muted-foreground italic px-3 py-1\">Message deleted</div>\n </div>\n )\n }\n\n // WhatsApp-style radius: round corners; the side facing the sender gets a\n // smaller corner on the *last* bubble of a run to read as a chat tail.\n const bubbleRadius = cn(\n 'rounded-2xl',\n isSent && isLastOfRun && 'rounded-br-sm',\n !isSent && isLastOfRun && 'rounded-bl-sm'\n )\n\n // Own messages sit on a soft brand tint rather than full `primary`: a\n // saturated block per message shouts on a long thread, and a light surface\n // means markdown needs no colour inversion.\n //\n // The tint is `ai-accent-soft`, NOT `accent`. Plenty of themes set `accent`\n // equal to `muted` and a hair off `background` — ARBI's differ by 3% — so an\n // accent bubble there is invisible against the thread. `ai-accent-soft` is\n // part of the AI-accent contract every consuming app defines explicitly, so\n // it is a tint by construction.\n const bubbleSurface = isSent\n ? cn('bg-ai-accent-soft text-foreground chat-bubble-sent', classNames?.ownBubble)\n : cn('border border-border bg-card text-card-foreground', classNames?.peerBubble)\n\n const copyLinkButton = onCopyLink && (\n <button\n onClick={onCopyLink}\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n className={cn(\n 'self-end p-1 transition-opacity focus:outline-none focus-visible:ring-1 focus-visible:ring-ring rounded',\n showActions ? 'opacity-100 text-foreground' : 'opacity-0 text-muted-foreground'\n )}\n aria-label=\"Copy link to this message\"\n >\n <Link className=\"w-3.5 h-3.5\" />\n </button>\n )\n\n return (\n <div\n id={id}\n data-testid={testId}\n className={cn(\n 'flex w-full items-end',\n isLastOfRun ? 'mb-2' : 'mb-0.5',\n isSent ? 'justify-end' : 'justify-start'\n )}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n >\n {/* Sent messages: copy-link + delete on the left */}\n {isSent && (copyLinkButton || onDelete) && (\n <div className=\"flex items-center gap-0.5 mr-1\">\n {copyLinkButton}\n {onDelete && (\n <button\n onClick={onDelete}\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n className={cn(\n 'self-end p-1 transition-opacity focus:outline-none focus-visible:ring-1 focus-visible:ring-ring rounded',\n showActions ? 'opacity-100 text-destructive' : 'opacity-0 text-muted-foreground'\n )}\n aria-label=\"Delete message\"\n >\n <Trash2 className=\"w-3.5 h-3.5\" />\n </button>\n )}\n </div>\n )}\n\n <div className=\"flex flex-col max-w-[80%] md:max-w-[60%]\">\n <div\n className={cn(\n 'px-3.5 py-2 break-words shadow-sm transition-shadow',\n bubbleRadius,\n bubbleSurface\n )}\n >\n {(message || !attachments) && (\n <div className=\"text-sm [&_.markdown-content]:space-y-1.5 [&_pre]:max-w-full [&_pre]:overflow-x-auto\">\n {renderMessage(message)}\n </div>\n )}\n {attachments && <div className={cn(message && 'mt-1.5')}>{attachments}</div>}\n\n {/* Sender + timestamp + read receipt, only on the last bubble of the\n run — a meta row per message is noise in a 1:1 thread. */}\n {isLastOfRun && (\n <div\n className={cn(\n 'flex items-center gap-1.5 mt-0.5',\n isSent ? 'justify-end' : 'justify-start'\n )}\n >\n {senderName && (\n <span className=\"text-xs font-medium leading-none opacity-90\">{senderName}</span>\n )}\n <span className=\"text-xs leading-none opacity-70\">{formatTimestamp(timestamp)}</span>\n {isSent &&\n (read ? (\n <CheckCheck className=\"w-3.5 h-3.5 flex-shrink-0 opacity-80\" />\n ) : (\n <Check className=\"w-3.5 h-3.5 flex-shrink-0 opacity-60\" />\n ))}\n </div>\n )}\n </div>\n </div>\n\n {/* Received messages: delete + copy-link on the right */}\n {!isSent && (onDelete || copyLinkButton) && (\n <div className=\"flex items-center gap-0.5 ml-1\">\n {onDelete && (\n <button\n onClick={onDelete}\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n className={cn(\n 'self-end p-1 transition-opacity focus:outline-none focus-visible:ring-1 focus-visible:ring-ring rounded',\n showActions ? 'opacity-100 text-destructive' : 'opacity-0 text-muted-foreground'\n )}\n aria-label=\"Delete message\"\n >\n <Trash2 className=\"w-3.5 h-3.5\" />\n </button>\n )}\n {copyLinkButton}\n </div>\n )}\n </div>\n )\n})\n","/**\n * A safety net for a host's boot gate (the loading screen shown until its saved state has loaded,\n * its single sign-on provider has initialised, a session restore has finished…). Each of those\n * waits is expected to settle on its own; if one never does, the user would sit on the loading\n * screen forever. This reports `true` once `isWaiting` has stayed true for `ms`, logging a warning\n * naming what stalled, so the gate falls through to normal routing (worst case: the sign-in page).\n *\n * The clock runs from when the wait starts and is not restarted by re-renders, so a component\n * that keeps re-rendering while stuck still times out.\n */\n\nimport { useEffect, useState } from 'react'\n\nexport const BOOT_GATE_TIMEOUT_MS = 10_000\n\nexport function useBootTimeout(\n isWaiting: boolean,\n label: string,\n ms: number = BOOT_GATE_TIMEOUT_MS\n): boolean {\n const [timedOut, setTimedOut] = useState(false)\n\n useEffect(() => {\n if (!isWaiting || timedOut) return\n const timer = setTimeout(() => {\n console.warn(`[boot] ${label} did not finish within ${ms / 1000}s; continuing without it`)\n setTimedOut(true)\n }, ms)\n return () => clearTimeout(timer)\n // label/ms are fixed per call site; keying only on the wait keeps the clock from restarting.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isWaiting, timedOut])\n\n return timedOut\n}\n","import { useMutation } from '@tanstack/react-query'\nimport type { Arbi } from '@arbidocs/sdk/browser'\nimport { useArbi } from './useArbi'\nimport { useUploadSkillFiles } from './workforce'\n\nexport interface SkillPackEntry {\n slug: string\n markdown: string\n /** Shared with the workspace by default, matching document-upload installation. */\n shared?: boolean\n}\n\nexport interface SkillPack {\n /** Stable host-owned pack identity; content and its version remain host data. */\n id: string\n version: string\n /** A hidden marker skill whose description is the pack version. Uploaded last. */\n marker: SkillPackEntry\n skills: readonly SkillPackEntry[]\n}\n\nexport interface InstallSkillPackVariables {\n /** Must already be open on this client; the hook never switches workspaces. */\n workspaceId: string\n}\n\nexport interface CreateSkillPackOptions {\n id: string\n skills: readonly SkillPackEntry[]\n /** The hidden marker skill's slug (default `<id>-version`) and its one-line body. */\n marker?: { slug?: string; note?: string }\n}\n\n/** A stable short hash of text (djb2, xor variant), base 36. */\nfunction hashText(text: string): string {\n let h = 5381\n for (let i = 0; i < text.length; i++) h = (h * 33) ^ text.charCodeAt(i)\n return (h >>> 0).toString(36)\n}\n\n/**\n * A skill pack from the host's skills: its version is a hash of all their SKILL.md texts (so any\n * change reinstalls the set), carried by a hidden marker skill that no one can invoke.\n */\nexport function createSkillPack({ id, skills, marker }: CreateSkillPackOptions): SkillPack {\n const version = hashText(skills.map((skill) => skill.markdown).join('\\n'))\n const slug = marker?.slug ?? `${id}-version`\n const note = marker?.note ?? 'The version of the skills installed here. Not for use.'\n return {\n id,\n version,\n marker: {\n slug,\n markdown: `---\\nname: ${slug}\\ndescription: ${version}\\nuser-invocable: false\\n---\\n\\n${note}\\n`,\n },\n skills,\n }\n}\n\n// A signed-out/replaced session and a different client never join another install.\nconst installs = new WeakMap<Arbi, WeakMap<AbortSignal, Map<string, Promise<void>>>>()\n\n/**\n * Install missing skills, or the complete pack when its version marker is stale. The marker is\n * written only after every skill succeeds, so a partial failure can be retried by relisting.\n * Hosts own the content, workspace-opening policy, when to install and error presentation.\n */\nexport function useInstallSkillPack(pack: SkillPack) {\n const arbi = useArbi()\n const upload = useUploadSkillFiles()\n return useMutation({\n mutationFn: ({ workspaceId }: InstallSkillPackVariables): Promise<void> => {\n const signal = arbi.getConnectionInfo()?.signal\n if (!signal) return Promise.reject(new Error('Skill installation needs a signed-in session.'))\n const checkContext = () => {\n if (\n signal.aborted ||\n arbi.getConnectionInfo()?.signal !== signal ||\n arbi.getWorkspaceId() !== workspaceId\n )\n throw new DOMException(\n 'The skill installation session or workspace changed.',\n 'AbortError'\n )\n }\n checkContext()\n let sessions = installs.get(arbi)\n if (!sessions) installs.set(arbi, (sessions = new WeakMap()))\n let pending = sessions.get(signal)\n if (!pending) sessions.set(signal, (pending = new Map()))\n const key = JSON.stringify([workspaceId, pack.id, pack.version])\n const running = pending.get(key)\n if (running) return running\n const install = (async () => {\n const listed = await arbi.assistant.listSkills({ includeHidden: true })\n checkContext()\n const present = new Set(listed.map((skill) => skill.slug))\n const current =\n listed.find((skill) => skill.slug === pack.marker.slug)?.description === pack.version\n const due = pack.skills.filter((skill) => !current || !present.has(skill.slug))\n for (const skill of [...due, ...(!current ? [pack.marker] : [])]) {\n checkContext()\n await upload.mutateAsync([\n {\n folder: `skills/${skill.slug}`,\n workspaceId,\n fileName: 'SKILL.md',\n content: new Blob([skill.markdown], { type: 'text/markdown' }),\n shared: skill.shared ?? true,\n },\n ])\n }\n })().finally(() => pending.delete(key))\n pending.set(key, install)\n return install\n },\n })\n}\n","/**\n * A host's skill pack, declared once: its skills as SKILL.md files (with one shared preamble) or\n * inline, in the host's configuration. The same object installs (`useInstallSkillPack`: one hidden\n * marker carries the version) and lists: `@arbidocs/blocks` shows the skills in every `/` menu from\n * `host.workflows.skillPacks`, run through the kit's own skill form and the chat's own send.\n *\n * const FIRM_SKILLS = defineSkillPack({\n * id: 'firm-skills',\n * label: 'Firm skills',\n * preamble: houseRules,\n * files: import.meta.glob('./skills/* /SKILL.md', {\n * query: '?raw',\n * import: 'default',\n * eager: true,\n * }),\n * })\n *\n * A SKILL.md is the line-based frontmatter the backend reads (`name` is the slug and must be its\n * folder's name), plus `title`, `icon`, `category` and `inputs` (one line of JSON) for the menu\n * and the form. The wording stays in the files: nothing here composes prose.\n */\nimport { createSkillPack, type CreateSkillPackOptions, type SkillPack } from './useInstallSkillPack'\n\n/** One form field of a pack skill (the shape of `inputs` in a SKILL.md frontmatter). */\nexport interface SkillPackField {\n /** Key in the inputs; also the `{{name}}` placeholder in the instructions. */\n name: string\n type: 'text' | 'longtext' | 'boolean' | 'select' | 'number' | 'date' | 'scope' | 'documents'\n label: string\n description?: string\n placeholder?: string\n required?: boolean\n default?: string | number | boolean\n /** `select` only. */\n options?: ReadonlyArray<{ value: string; label: string; description?: string }>\n min?: number\n max?: number\n advanced?: boolean\n}\n\n/** A skill declared inline (no file). */\nexport interface SkillPackSkillDefinition {\n /** The slug (`/name` in the menu): lowercase letters, digits and hyphens. */\n name: string\n /** Shown in the skill's form. Default: the slug. */\n title?: string\n description: string\n /** The instructions; the pack's preamble goes before them. */\n prompt: string\n inputs?: ReadonlyArray<SkillPackField>\n /** Its group within the pack (the menu sorts by it, then by title). */\n category?: string\n icon?: string\n}\n\n/** A skill of a defined pack: what the menu lists and what installs. */\nexport interface SkillPackSkill {\n slug: string\n title: string\n description: string\n icon?: string\n category?: string\n inputs: ReadonlyArray<SkillPackField>\n /** The preamble, then the skill's own instructions. */\n instructions: string\n /** The SKILL.md as installed: its frontmatter, then `instructions`. */\n markdown: string\n}\n\n/** A skill pack with what the kit lists: installable as is (`useInstallSkillPack(pack)`). */\nexport interface DefinedSkillPack extends SkillPack {\n /** The heading of its group in the `/` menu. */\n label?: string\n skills: readonly SkillPackSkill[]\n}\n\nexport interface DefineSkillPackOptions {\n /** Stable identity (also the default marker slug, `<id>-version`). */\n id: string\n /** The heading of its group in the `/` menu. Absent: the kit's built-in heading. */\n label?: string\n /** Text every skill's instructions start with (house rules). */\n preamble?: string\n /**\n * SKILL.md texts by path, as an eager raw glob:\n * `import.meta.glob(…, { query: '?raw', import: 'default', eager: true })`.\n */\n files?: Readonly<Record<string, string>>\n /** Skills declared inline. */\n skills?: ReadonlyArray<SkillPackSkillDefinition>\n marker?: CreateSkillPackOptions['marker']\n}\n\nconst FRONTMATTER = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?([\\s\\S]*)$/\nconst SLUG = /^[a-z0-9][a-z0-9-]*$/\n\nfunction readFrontmatter(block: string): Record<string, string> {\n const meta: Record<string, string> = {}\n for (const line of block.split(/\\r?\\n/)) {\n const i = line.indexOf(':')\n if (i > 0) meta[line.slice(0, i).trim().toLowerCase()] = line.slice(i + 1).trim()\n }\n return meta\n}\n\nfunction withPreamble(preamble: string | undefined, body: string): string {\n return [preamble?.trim(), body.trim()].filter(Boolean).join('\\n\\n')\n}\n\nfunction checkSlug(slug: string, where: string): void {\n if (!SLUG.test(slug)) throw new Error(`${where}: \"${slug}\" is not a skill slug`)\n}\n\nfunction fromFile(path: string, text: string, preamble: string | undefined): SkillPackSkill {\n const match = FRONTMATTER.exec(text)\n if (!match) throw new Error(`${path}: a skill needs frontmatter`)\n const meta = readFrontmatter(match[1])\n const slug = meta.name ?? ''\n checkSlug(slug, path)\n if (path.includes('/') && !path.includes(`/${slug}/`))\n throw new Error(`${path}: name must be the folder's slug`)\n let inputs: SkillPackField[] = []\n if (meta.inputs) {\n try {\n inputs = JSON.parse(meta.inputs) as SkillPackField[]\n } catch {\n throw new Error(`${path}: inputs must be one line of JSON`)\n }\n }\n const instructions = withPreamble(preamble, match[2])\n return {\n slug,\n title: meta.title || slug,\n description: meta.description ?? '',\n icon: meta.icon || undefined,\n category: meta.category || undefined,\n inputs,\n instructions,\n markdown: `---\\n${match[1]}\\n---\\n\\n${instructions}\\n`,\n }\n}\n\nconst oneLine = (text: string): string => text.replace(/\\s*\\n\\s*/g, ' ').trim()\n\nfunction fromDefinition(\n skill: SkillPackSkillDefinition,\n preamble: string | undefined\n): SkillPackSkill {\n checkSlug(skill.name, 'defineSkillPack')\n const inputs = skill.inputs ?? []\n const instructions = withPreamble(preamble, skill.prompt)\n const meta = [\n `name: ${skill.name}`,\n `description: ${oneLine(skill.description)}`,\n skill.title && `title: ${oneLine(skill.title)}`,\n skill.icon && `icon: ${skill.icon}`,\n skill.category && `category: ${oneLine(skill.category)}`,\n inputs.length > 0 && `inputs: ${JSON.stringify(inputs)}`,\n ].filter(Boolean)\n return {\n slug: skill.name,\n title: skill.title || skill.name,\n description: skill.description,\n icon: skill.icon,\n category: skill.category,\n inputs,\n instructions,\n markdown: `---\\n${meta.join('\\n')}\\n---\\n\\n${instructions}\\n`,\n }\n}\n\n/** Define a host's skill pack from SKILL.md files and/or inline skills (see the module comment). */\nexport function defineSkillPack({\n id,\n label,\n preamble,\n files = {},\n skills = [],\n marker,\n}: DefineSkillPackOptions): DefinedSkillPack {\n const all = [\n ...Object.entries(files).map(([path, text]) => fromFile(path, text, preamble)),\n ...skills.map((skill) => fromDefinition(skill, preamble)),\n ].sort((a, b) => a.slug.localeCompare(b.slug))\n const seen = new Set<string>()\n for (const skill of all) {\n if (seen.has(skill.slug)) throw new Error(`defineSkillPack: two skills are \"${skill.slug}\"`)\n seen.add(skill.slug)\n }\n return { ...createSkillPack({ id, skills: all, marker }), label, skills: all }\n}\n\n/** A request that follows one of the pack's skills: its instructions, then the request. */\nexport function skillPackPrompt(pack: DefinedSkillPack, slug: string, request = ''): string {\n const skill = pack.skills.find((s) => s.slug === slug)\n if (!skill) throw new Error(`No skill \"${slug}\" in the ${pack.id} pack`)\n return request.trim()\n ? `${skill.instructions}\\n\\n## Request\\n${request.trim()}`\n : skill.instructions\n}\n","/**\n * Whether the site is online, for every host. React Query's `onlineManager` follows three things:\n * - the browser's network;\n * - the live connection: once it has been up, a dropped socket means the server cannot be reached;\n * - the person's own \"Work offline\" choice.\n *\n * Offline, queries serve their cache and writes wait until the connection is back.\n *\n * `ArbiWebSocketProvider` runs {@link useOnlineSync}. {@link useWorkOffline} is the one \"Work\n * offline\" switch, used by the settings toggle and the account menu; the offline pill's Reconnect\n * clears it through {@link useReconnect}.\n * The choice is a transient view of the session: this session's only and never saved, as a saved\n * `true` would boot the app offline and stall the sign-in.\n */\nimport { useCallback, useEffect, useRef } from 'react'\nimport { onlineManager } from '@tanstack/react-query'\nimport { useArbiSession } from './session/signed-in'\nimport { useArbiSessionState, useArbiSessionStore } from './session/session-hooks'\nimport type { ArbiSessionStore } from './session/store'\nimport { useArbiWsStore, type ArbiWsStatus } from './websocket/store'\n\n/** The session's transient view holding the \"Work offline\" choice. */\nexport const WORK_OFFLINE_VIEW = 'app.workOffline'\n\n/** Whether the person chose \"Work offline\" (outside React). */\nexport const isWorkingOffline = (session: Pick<ArbiSessionStore, 'getState'>): boolean =>\n session.getState().views.transient[WORK_OFFLINE_VIEW] === true\n\n/** Turn \"Work offline\" on or off (outside React). */\nexport const setWorkOfflineIn = (\n session: Pick<ArbiSessionStore, 'setTransientView'>,\n on: boolean\n): void => session.setTransientView(WORK_OFFLINE_VIEW, on || undefined)\n\n/** The \"Work offline\" choice and its setter. */\nexport function useWorkOffline(): [boolean, (on: boolean) => void] {\n const session = useArbiSessionStore()\n const on = useArbiSessionState((s) => s.views.transient[WORK_OFFLINE_VIEW] === true)\n const set = useCallback((next: boolean) => setWorkOfflineIn(session, next), [session])\n return [on, set]\n}\n\n/**\n * Online or not, from the socket's status, the session, the \"Work offline\" choice and whether the\n * socket has ever connected in this tab.\n */\nexport function computeOnline(\n wsStatus: ArbiWsStatus | undefined,\n isAuthenticated: boolean,\n workOffline: boolean,\n /** Until the socket has been up once, 'disconnected' means \"not connected yet\", not \"dropped\". */\n wsEverConnected: boolean\n): boolean {\n // A deliberate \"Work offline\" choice wins over actual reachability.\n if (workOffline) return false\n const navOnline = typeof navigator === 'undefined' ? true : navigator.onLine\n // The socket is evidence only once a session should be holding it open. Before sign-in it is\n // down by design: reading that as offline would pause the sign-in request forever, and the app\n // would hang on \"Signing in…\". Right after a reload the session is back a tick before the\n // socket's handshake: reading that as offline would tell the person they are offline on a\n // working network, and stop the workspace switch restoring the workspace they reloaded on.\n // 'connecting' counts as online, to avoid flapping.\n const wsIsEvidence = isAuthenticated && wsEverConnected\n const wsOnline = !wsIsEvidence || (wsStatus !== 'disconnected' && wsStatus !== 'error')\n return navOnline && wsOnline\n}\n\n/** Drive `onlineManager` from the network, the live connection and \"Work offline\". */\nexport function useOnlineSync(): void {\n const session = useArbiSessionStore()\n const wsStatus = useArbiWsStore((s) => s.status)\n const signedIn = useArbiSession().status === 'signed-in'\n const [workOffline] = useWorkOffline()\n\n // Latches on the first 'connected' and never clears: after that, a drop is a real drop. A ref,\n // not state: the 'connected' status that sets it already renders.\n const wsEverConnected = useRef(false)\n if (wsStatus === 'connected') wsEverConnected.current = true\n const signedInRef = useRef(signedIn)\n signedInRef.current = signedIn\n\n useEffect(() => {\n onlineManager.setOnline(computeOnline(wsStatus, signedIn, workOffline, wsEverConnected.current))\n }, [wsStatus, signedIn, workOffline])\n\n useEffect(() => {\n const update = () =>\n onlineManager.setOnline(\n computeOnline(\n useArbiWsStore.getState().status,\n signedInRef.current,\n isWorkingOffline(session),\n wsEverConnected.current\n )\n )\n window.addEventListener('online', update)\n window.addEventListener('offline', update)\n return () => {\n window.removeEventListener('online', update)\n window.removeEventListener('offline', update)\n }\n }, [session])\n}\n\n/** What a reconnect did. */\nexport type ReconnectOutcome = 'resumed' | 'no-network' | 'reloading'\n\n/**\n * Reconnect, cheapest path first:\n * - offline only by choice: clear it, and the queued writes resume in place (no reload);\n * - no network: there is nothing to reconnect to yet;\n * - otherwise the socket gave up after a real drop: reload, which reopens it, renews the session\n * and replays the queue.\n */\nexport function useReconnect(): () => ReconnectOutcome {\n const session = useArbiSessionStore()\n return useCallback(() => {\n if (isWorkingOffline(session)) {\n setWorkOfflineIn(session, false)\n return 'resumed'\n }\n if (typeof navigator !== 'undefined' && navigator.onLine === false) return 'no-network'\n window.location.reload()\n return 'reloading'\n }, [session])\n}\n","/** The shared socket's reconnect policy and where it opens. */\n\nconst INITIAL_RECONNECT_DELAY_MS = 1_000\nconst MAX_RECONNECT_DELAY_MS = 30_000\n\n/** Capped exponential backoff before a fresh connect after the transport gave up. */\nexport function nextReconnectDelay(attempt: number): number {\n return Math.min(INITIAL_RECONNECT_DELAY_MS * 2 ** Math.max(0, attempt), MAX_RECONNECT_DELAY_MS)\n}\n\n/**\n * The HTTP origin to open the socket on. A same-origin deployment configures the API as `''` (or\n * a relative prefix), from which no WebSocket URL can be built: the page's origin is used then.\n */\nexport function resolveSocketBaseUrl(configured: string, origin: string | undefined): string {\n return /^https?:\\/\\//.test(configured) || !origin ? configured : origin\n}\n","/**\n * The mail client the hooks and the mail blocks talk to.\n *\n * A {@link MailClient} is a transport (`fetch` under `/v1/mail`) plus the reads the screens make.\n * {@link createMailClient} builds one from any transport; {@link arbiMailClient} builds the default\n * one from an `Arbi` (used when the host configuration has no `mail`). A host that keeps mail offline,\n * bridges connector tokens or sends secure mail passes its own reads and extras as overrides.\n */\n\nimport type { Arbi } from '@arbidocs/sdk/browser'\nimport type {\n MailAccount,\n MailAttachment,\n MailCompose,\n MailConversationPage,\n MailFolder,\n MailMessage,\n MailPage,\n MailPolicy,\n MailThread,\n} from './types'\n\n/** Fetch a path under `/v1/mail` with authentication; rejects a non-2xx response (`status` set). */\nexport type MailFetch = (path: string, init?: RequestInit) => Promise<Response>\n\n/** Which draft body to open in the Word editor (`POST /drafts/editor`). */\nexport interface MailDraftEditorRequest {\n /** A saved draft (its room, or a new one seeded from it). */\n draftId?: string\n /** A room this person already has open: a reconnect, or a new message not saved yet. */\n roomId?: string\n /** What a new message's room starts from (a reply's quote). */\n text?: string\n html?: string | null\n /** The workspace open in the app: a new draft bills its project when the person may. */\n workspaceExtId?: string | null\n}\n\n/** A project an email's AI work is billed to: the person's own, or a matter they own or collaborate in. */\nexport interface MailProject {\n external_id: string\n name: string\n personal: boolean\n}\n\n/** A collaboration session on a draft's body: a document session's fields plus the draft. */\nexport interface MailDraftEditorSession {\n room_id: string\n token: string\n expires_in: number\n websocket_path: string\n can_edit: boolean\n identity: { actorId: string; name: string; role: 'human' | 'agent' }\n filename: string\n draft_id?: string | null\n /** The project ARBI's work on this email is billed to. */\n project?: MailProject | null\n}\n\nexport interface MailClient {\n fetch: MailFetch\n getPolicy(): Promise<MailPolicy>\n listAccounts(): Promise<MailAccount[]>\n listFolders(account: MailAccount): Promise<MailFolder[]>\n listMessages(\n account: MailAccount,\n folderId: string,\n query: string,\n cursor: string | null\n ): Promise<MailPage>\n /** One page of a folder's conversations, newest first (`null` cursor: the first page). */\n listConversations(\n account: MailAccount,\n folderId: string,\n query: string,\n cursor: string | null\n ): Promise<MailConversationPage>\n /** One conversation's messages, oldest first; `folderId`: the folder it was opened from. */\n getThread(account: MailAccount, threadId: string, folderId: string): Promise<MailThread>\n getMessage(account: MailAccount, messageId: string): Promise<MailMessage>\n /** Hand this session what the server needs to read the account (keys, credentials). */\n unlock(account: MailAccount): Promise<void>\n /**\n * The encrypted payload for `/secure/send` (native mail only). Absent: secure delivery is not\n * offered.\n */\n prepareSecureMail?(\n compose: MailCompose,\n account: MailAccount,\n requestId: string\n ): Promise<unknown>\n /** The URL that connects an OAuth mail provider, returning to `returnPath`. Absent: not offered. */\n authorizeOAuth?(vendor: string, returnPath: string): Promise<string>\n /**\n * Open a native draft's body in the Word editor, unlocking its room for this session with the\n * person's key when the server asks (423). Absent: the composer keeps its plain rich-text body.\n */\n openDraftEditor?(request: MailDraftEditorRequest): Promise<MailDraftEditorSession>\n}\n\n/** A read that needs the network and has no copy on this device (shown as a notice, not an error). */\nexport class MailOfflineUnavailableError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'MailOfflineUnavailableError'\n }\n}\n\nexport function accountPath(id: string): string {\n return `/accounts/${encodeURIComponent(id)}`\n}\n\n/** A folder's conversations (`GET …/conversations`). */\nexport function conversationsPath(\n accountId: string,\n folderId: string,\n query: string,\n cursor: string | null\n): string {\n const params = new URLSearchParams({\n folder_id: folderId,\n q: query,\n ...(cursor ? { cursor } : {}),\n })\n return `${accountPath(accountId)}/conversations?${params}`\n}\n\n/** One conversation (`GET …/thread`): its id goes in the query, as it can be a Message-ID. */\nexport function threadPath(accountId: string, threadId: string, folderId: string): string {\n return `${accountPath(accountId)}/thread?${new URLSearchParams({ thread_id: threadId, folder_id: folderId })}`\n}\n\n/** A JSON mail call: the parsed body, or `undefined` for 204. */\nexport async function mailJson<T>(fetch: MailFetch, path: string, init?: RequestInit): Promise<T> {\n const response = await fetch(path, init)\n return response.status === 204 ? (undefined as T) : (response.json() as Promise<T>)\n}\n\n/** A client over `fetch`; `overrides` replace any of its reads or add the optional extras. */\nexport function createMailClient(\n fetch: MailFetch,\n overrides: Partial<MailClient> = {}\n): MailClient {\n return {\n fetch,\n getPolicy: () => mailJson(fetch, '/policy'),\n listAccounts: () => mailJson(fetch, '/accounts'),\n listFolders: (account) => mailJson(fetch, `${accountPath(account.id)}/folders`),\n listMessages: (account, folderId, query, cursor) =>\n mailJson(\n fetch,\n `${accountPath(account.id)}/messages?${new URLSearchParams({ folder_id: folderId, q: query, ...(cursor ? { cursor } : {}) })}`\n ),\n listConversations: (account, folderId, query, cursor) =>\n mailJson(fetch, conversationsPath(account.id, folderId, query, cursor)),\n getThread: (account, threadId, folderId) =>\n mailJson(fetch, threadPath(account.id, threadId, folderId)),\n getMessage: (account, messageId) =>\n mailJson(fetch, `${accountPath(account.id)}/messages/${encodeURIComponent(messageId)}`),\n unlock: async () => {},\n ...overrides,\n }\n}\n\n/**\n * The client on the `Arbi` session's mail transport (`arbi.mail`). The native inbox is unlocked\n * with the signed-in user's keys before each read (so mail that arrived since is readable too);\n * unlocking a connected account bridges its connector tokens or its sealed credentials.\n * `overrides` replace any of its reads (the default client in `useMailClient` keeps them working\n * offline with `offlineMailReads`).\n */\nexport function arbiMailClient(arbi: Arbi, overrides: Partial<MailClient> = {}): MailClient {\n return createMailClient((path, init) => arbi.mail.fetch(path, init), {\n unlock: (account) => arbi.mail.unlockAccount(account),\n ...overrides,\n })\n}\n\n/** A picked file as an attachment (its content base64-encoded). */\nexport async function fileAttachment(file: File): Promise<MailAttachment> {\n const data = await new Promise<string>((resolve, reject) => {\n const reader = new FileReader()\n reader.onload = () => resolve(String(reader.result).split(',')[1])\n reader.onerror = () => reject(new Error(`Could not read ${file.name}`))\n reader.readAsDataURL(file)\n })\n return {\n id: '',\n name: file.name,\n content_type: file.type || 'application/octet-stream',\n size: file.size,\n content_base64: data,\n }\n}\n\n/** The address suggested for a user's native inbox: given name and family name, lowercase ASCII, dot-joined. */\nexport function defaultMailAlias(\n user?: { given_name?: string | null; family_name?: string | null } | null\n): string {\n return [user?.given_name, user?.family_name]\n .filter(Boolean)\n .map((name) =>\n name!\n .normalize('NFKD')\n .replace(/[̀-ͯ]/g, '')\n .toLowerCase()\n .replace(/[^a-z0-9]/g, '')\n )\n .filter(Boolean)\n .join('.')\n .slice(0, 63)\n}\n\n/**\n * The alias to try after `alias` is taken: `grace.okoye` → `grace.okoye2`, `grace.okoye2` → `grace.okoye3`.\n * The server is the only judge of availability, so this is a guess to offer, not a promise.\n */\nexport function nextAliasSuggestion(alias: string): string {\n const number = /(\\d+)$/.exec(alias)\n if (!number) return `${alias}2`\n return `${alias.slice(0, -number[1].length)}${Number(number[1]) + 1}`\n}\n\n/** True when the claim failed because the address is already in use (HTTP 409). */\nexport function isAliasTakenError(err: Error): boolean {\n return 'status' in err && err.status === 409\n}\n\n/**\n * Shown after `alias` is taken. The suggestion is unverified, so the copy must not say it is free:\n * the server only checks availability when the user confirms the claim.\n */\nexport function aliasTakenMessage(alias: string, suggestion: string, domain: string): string {\n return `${alias}@${domain} is already taken. Try ${suggestion}@${domain}: we check it when you confirm.`\n}\n\n/** The draft a `mail_draft_ready` notification is about (its content is `{\"mail_id\": …}`). */\nexport function mailDraftIdFromContent(content: string | null | undefined): string | undefined {\n try {\n const meta = JSON.parse(content || '{}') as { mail_id?: unknown }\n return typeof meta.mail_id === 'string' && meta.mail_id ? meta.mail_id : undefined\n } catch {\n return undefined\n }\n}\n","/**\n * Conversations: how messages group into threads, the same rule as the server's, so a list read\n * from this device groups exactly as one read online (`group_conversations` in the backend).\n *\n * A message's conversation is its `thread_id`, else (it stands alone) its own id. Native mail's\n * thread id is a per-user key: an HMAC of the thread's root Message-ID (the first References entry,\n * else In-Reply-To, else its own Message-ID), as the backend's `email_threading.thread_keys`. The\n * server keys mail it stores; older mail is keyed by the owner's client ({@link nativeThreadKeys}),\n * because only the client can read its Message-IDs.\n */\n\nimport type { MailAddress, MailConversation, MailMessage } from './types'\n\n/** What groups a message into a conversation. */\nexport function mailConversationKey(message: Pick<MailMessage, 'id' | 'thread_id'>): string {\n return message.thread_id || message.id\n}\n\n/** A conversation row from its messages (newest first). */\nexport function toMailConversation(threadId: string, members: MailMessage[]): MailConversation {\n const newest = members[0]\n const senders = new Map<string, MailAddress>()\n for (const message of [...members].reverse())\n for (const address of message.sender)\n if (!senders.has(address.email.toLowerCase()))\n senders.set(address.email.toLowerCase(), address)\n return {\n thread_id: threadId,\n subject: [...members].reverse().find((m) => m.subject)?.subject ?? '',\n preview: newest.preview,\n senders: [...senders.values()],\n received_at: newest.received_at ?? null,\n message_count: members.length,\n unread_count: members.filter((m) => m.unread).length,\n flagged: members.some((m) => m.flagged),\n messages: members,\n }\n}\n\n/** Conversations of `messages` (newest first), in the order of each one's newest message. */\nexport function groupMailConversations(messages: MailMessage[]): MailConversation[] {\n const groups = new Map<string, MailMessage[]>()\n for (const message of messages) {\n const key = mailConversationKey(message)\n const members = groups.get(key)\n if (members) members.push(message)\n else groups.set(key, [message])\n }\n return [...groups].map(([key, members]) => toMailConversation(key, members))\n}\n\nconst MESSAGE_ID = /<[^<>\\s]+>/g\n\n/** Message-IDs in a header, as the backend reads them (`<…>` tokens, else whitespace-split). */\nfunction ids(header: string | string[] | null | undefined): string[] {\n if (!header || header.length === 0) return []\n const text = Array.isArray(header) ? header.join(' ') : header\n return text.match(MESSAGE_ID) ?? text.split(/\\s+/).filter(Boolean)\n}\n\n/** The thread's root Message-ID: the first References entry, else In-Reply-To, else its own. */\nexport function mailThreadRoot(\n message: Pick<MailMessage, 'message_id' | 'in_reply_to' | 'references'>\n): string | undefined {\n return ids(message.references)[0] ?? ids(message.in_reply_to)[0] ?? ids(message.message_id)[0]\n}\n\nasync function hmacKey(secret: Uint8Array, value: string): Promise<string> {\n const key = await crypto.subtle.importKey(\n 'raw',\n secret as BufferSource,\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign']\n )\n const mac = new Uint8Array(\n await crypto.subtle.sign('HMAC', key, new TextEncoder().encode(`message:${value.trim()}`))\n )\n return Array.from(mac.slice(0, 16), (b) => b.toString(16).padStart(2, '0')).join('')\n}\n\n/**\n * A native message's keys, computed with the owner's thread secret: its thread key and its own\n * Message-ID's. `undefined` when it has no Message-ID to key (it stays a conversation of its own).\n */\nexport async function nativeThreadKeys(\n secret: Uint8Array,\n message: Pick<MailMessage, 'message_id' | 'in_reply_to' | 'references'>\n): Promise<{ thread_hmac: string; message_id_hmac?: string } | undefined> {\n const root = mailThreadRoot(message)\n if (!root) return undefined\n const own = ids(message.message_id)[0]\n return {\n thread_hmac: await hmacKey(secret, root),\n ...(own && { message_id_hmac: await hmacKey(secret, own) }),\n }\n}\n","/**\n * Typed, encrypted reads and writes of mailbox data in the offline store: accounts, folders,\n * message headers (what a folder list shows), bodies (the opened message) and attachment bytes.\n *\n * Headers and bodies are separate records so a folder list decrypts only small headers; bodies are\n * decrypted when a message is opened or searched.\n */\n\nimport type { MailAccount, MailFolder, MailMessage, MailPolicy } from '../types'\nimport { blind, openBytes, openJson, sealBytes, sealJson } from './crypto'\nimport {\n deleteRecords,\n getRecord,\n hasRecord,\n putRecord,\n recordsInBucket,\n touchRecord,\n type RecordKind,\n type StoredRecord,\n} from './store'\n\nexport const keyOf = {\n accounts: () => blind('accounts'),\n policy: () => blind('policy'),\n folders: (accountId: string) => blind('folders', accountId),\n header: (accountId: string, folderId: string, messageId: string) =>\n blind('header', accountId, folderId, messageId),\n body: (accountId: string, messageId: string) => blind('body', accountId, messageId),\n attachment: (accountId: string, messageId: string, attachmentId: string) =>\n blind('attachment', accountId, messageId, attachmentId),\n}\n\nexport const bucketOf = {\n global: () => blind('bucket', 'global'),\n folder: (accountId: string, folderId: string) => blind('bucket', 'folder', accountId, folderId),\n account: (accountId: string) => blind('bucket', 'account', accountId),\n}\n\nasync function put(\n kind: RecordKind,\n key: string,\n bucket: string,\n data: Uint8Array,\n sortAt = Date.now()\n): Promise<void> {\n const now = Date.now()\n await putRecord({ key, kind, bucket, sortAt, size: data.byteLength, lastAccess: now, data })\n}\n\nasync function readJson<T>(record: StoredRecord | undefined): Promise<T | undefined> {\n if (!record) return undefined\n try {\n return await openJson<T>(record.data)\n } catch {\n // Sealed under another identity (a different account wrote it) or damaged: treat as absent.\n return undefined\n }\n}\n\nconst receivedAt = (m: MailMessage) => (m.received_at ? Date.parse(m.received_at) || 0 : 0)\n\nexport async function saveAccounts(accounts: MailAccount[]): Promise<void> {\n await put('accounts', await keyOf.accounts(), await bucketOf.global(), await sealJson(accounts))\n}\n\nexport async function loadAccounts(): Promise<MailAccount[] | undefined> {\n return readJson<MailAccount[]>(await getRecord(await keyOf.accounts()))\n}\n\nexport async function savePolicy(policy: MailPolicy): Promise<void> {\n await put('policy', await keyOf.policy(), await bucketOf.global(), await sealJson(policy))\n}\n\nexport async function loadPolicy(): Promise<MailPolicy | undefined> {\n return readJson<MailPolicy>(await getRecord(await keyOf.policy()))\n}\n\nexport async function saveFolders(accountId: string, folders: MailFolder[]): Promise<void> {\n await put(\n 'folders',\n await keyOf.folders(accountId),\n await bucketOf.account(accountId),\n await sealJson(folders)\n )\n}\n\nexport async function loadFolders(accountId: string): Promise<MailFolder[] | undefined> {\n return readJson<MailFolder[]>(await getRecord(await keyOf.folders(accountId)))\n}\n\n/** A list row: the message without its body text/html or attachment bytes. */\nexport function toHeader(message: MailMessage): MailMessage {\n return {\n ...message,\n text: '',\n html: undefined,\n delivery: undefined,\n attachments: message.attachments.map((a) => ({ ...a, content_base64: null })),\n }\n}\n\nexport interface StoredHeader {\n key: string\n sortAt: number\n message: MailMessage\n}\n\nexport async function saveHeader(\n accountId: string,\n folderId: string,\n message: MailMessage\n): Promise<void> {\n await put(\n 'header',\n await keyOf.header(accountId, folderId, message.id),\n await bucketOf.folder(accountId, folderId),\n await sealJson(toHeader(message)),\n receivedAt(message)\n )\n}\n\n/** A folder's saved headers, newest first. */\nexport async function loadHeaders(accountId: string, folderId: string): Promise<StoredHeader[]> {\n const records = await recordsInBucket(await bucketOf.folder(accountId, folderId))\n const out: StoredHeader[] = []\n for (const record of records) {\n if (record.kind !== 'header') continue\n const message = await readJson<MailMessage>(record)\n if (message) out.push({ key: record.key, sortAt: record.sortAt, message })\n }\n return out.sort((a, b) => b.sortAt - a.sortAt)\n}\n\n/** Whether a folder has ever been saved on this device (so \"empty\" means empty, not \"not saved\"). */\nexport async function hasFolder(accountId: string): Promise<boolean> {\n return hasRecord(await keyOf.folders(accountId))\n}\n\nexport async function saveBody(accountId: string, message: MailMessage): Promise<void> {\n const stripped: MailMessage = {\n ...message,\n attachments: message.attachments.map((a) => ({ ...a, content_base64: null })),\n }\n await put(\n 'body',\n await keyOf.body(accountId, message.id),\n await bucketOf.account(accountId),\n await sealJson(stripped),\n receivedAt(message)\n )\n}\n\nexport async function hasBody(accountId: string, messageId: string): Promise<boolean> {\n return hasRecord(await keyOf.body(accountId, messageId))\n}\n\nexport async function loadBody(\n accountId: string,\n messageId: string\n): Promise<MailMessage | undefined> {\n return readJson<MailMessage>(await getRecord(await keyOf.body(accountId, messageId)))\n}\n\nexport async function saveAttachment(\n accountId: string,\n messageId: string,\n attachmentId: string,\n bytes: Uint8Array,\n /** When its message was received (ms), so it leaves the device with it. */\n sortAt?: number\n): Promise<void> {\n await put(\n 'attachment',\n await keyOf.attachment(accountId, messageId, attachmentId),\n await bucketOf.account(accountId),\n await sealBytes(bytes),\n sortAt || undefined\n )\n}\n\nexport async function hasAttachment(\n accountId: string,\n messageId: string,\n attachmentId: string\n): Promise<boolean> {\n return hasRecord(await keyOf.attachment(accountId, messageId, attachmentId))\n}\n\n/** An attachment's bytes, or undefined when it wasn't saved (too large, or evicted). */\nexport async function loadAttachment(\n accountId: string,\n messageId: string,\n attachmentId: string\n): Promise<Uint8Array | undefined> {\n const key = await keyOf.attachment(accountId, messageId, attachmentId)\n const record = await getRecord(key)\n if (!record) return undefined\n try {\n const bytes = await openBytes(record.data)\n void touchRecord(key)\n return bytes\n } catch {\n return undefined\n }\n}\n\nexport async function removeKeys(keys: string[]): Promise<void> {\n await deleteRecords(keys)\n}\n\n/** Searchable text of an opened message: its text part, else its HTML without tags, and file names. */\nfunction bodyText(body: MailMessage): string {\n const html = body.text ? '' : (body.html ?? '').replace(/<[^>]*>/g, ' ')\n return `${body.text} ${html} ${body.attachments.map((a) => a.name).join(' ')}`\n}\n\nconst folded = (value: string) => value.toLocaleLowerCase().normalize('NFKD')\n\n/**\n * Search a folder on the device: every word must appear in the subject, a participant or the body\n * (the same \"all words\" feel as the server's search).\n */\nexport async function searchFolder(\n accountId: string,\n folderId: string,\n query: string\n): Promise<MailMessage[]> {\n const words = folded(query).split(/\\s+/).filter(Boolean)\n const headers = await loadHeaders(accountId, folderId)\n if (words.length === 0) return headers.map((h) => h.message)\n const out: MailMessage[] = []\n for (const { message } of headers) {\n const people = [...message.sender, ...message.to, ...message.cc]\n .map((p) => `${p.name ?? ''} ${p.email}`)\n .join(' ')\n let haystack = folded(`${message.subject} ${people} ${message.preview}`)\n if (!words.every((w) => haystack.includes(w))) {\n const body = await loadBody(accountId, message.id)\n if (body) haystack += ' ' + folded(bodyText(body))\n }\n if (words.every((w) => haystack.includes(w))) out.push(message)\n }\n return out\n}\n\n/** Whether a folder is a view over the others (Flagged), with no messages of its own to keep. */\nexport const isVirtualFolder = (folder: Pick<MailFolder, 'role'> | undefined) =>\n folder?.role === 'flagged'\n\n/**\n * Messages saved on the device across the account's folders (`include` picks the folders), each\n * once (a Gmail message is listed under every label), newest first.\n */\nexport async function loadAccountMessages(\n accountId: string,\n include: (folder: MailFolder) => boolean,\n query = ''\n): Promise<MailMessage[]> {\n const seen = new Map<string, MailMessage>()\n for (const folder of (await loadFolders(accountId)) ?? []) {\n if (isVirtualFolder(folder) || !include(folder)) continue\n for (const message of await searchFolder(accountId, folder.id, query))\n if (!seen.has(message.id)) seen.set(message.id, message)\n }\n return [...seen.values()].sort((a, b) => receivedAt(b) - receivedAt(a))\n}\n","/**\n * Whether a request failed without reaching the server at all. fetch() rejects with a TypeError\n * when the network is down or the host can't be reached (\"Failed to fetch\" in Chromium,\n * \"NetworkError when attempting to fetch resource.\" in Firefox, \"Load failed\" in Safari). A server\n * error (any HTTP status) is not one: the server answered, so its answer stands. Neither is any\n * other TypeError (a bug), which must surface rather than be taken for \"offline\".\n */\nexport function isNetworkFailure(error: unknown): boolean {\n return error instanceof TypeError && /fetch|network|load failed|internet/i.test(error.message)\n}\n\n/** The browser reports no connection. */\nexport function isBrowserOffline(): boolean {\n return typeof navigator !== 'undefined' && navigator.onLine === false\n}\n","/**\n * Changes to messages made offline (or whose request got no answer): mark read or unread, flag or\n * unflag, move or archive, send to Trash, restore and delete forever. Each is applied to the device copy at once (so\n * the lists read from this device show it), kept sealed on the device, and sent to the server once\n * the connection is back.\n *\n * One pending change per message: a second change to the same message is combined with the first\n * into the message's final state (Archive then mark unread is one PATCH; Flag then Unflag is one PATCH; Trash then Delete forever is\n * one DELETE; Trash then Restore is nothing). Some providers (IMAP, Outlook) give a message a new id\n * when it moves, so replaying the steps one by one would aim the later ones at an id that no longer\n * exists. The combined change is sent once, to the id the message had when it was first changed.\n *\n * Replay keeps the order in which messages were first changed, per account: one account that cannot\n * be reached does not hold back the others. The server's message writes are idempotent (a PATCH sets\n * a state; a repeated DELETE finds nothing), so a replay after a lost answer does no harm. Outcomes:\n * - the message is gone on the server (404, 410): dropped; nothing is left to change, and the next\n * sync removes it from the device too;\n * - refused (another 4xx): dropped, and reported with the server's reason;\n * - no answer at all: the replay stops (no connection), everything stays for the next reconnect;\n * - a server error, rate limit, timeout or an answer that isn't the mail API's (5xx, 429, 408, no\n * status: a deploy, a captive portal): that account waits, with no limit;\n * - a session the server keeps refusing after an unlock (401: an account that needs reconnecting):\n * after {@link MAX_ATTEMPTS} tries it is reported as refused, so it can't wait for ever.\n *\n * Queuing a change and replaying one run one at a time, through the same Web Lock (so across tabs\n * too; a plain in-tab chain where Web Locks don't exist). A replay reads the message's record\n * fresh, sends it and drops it in one step, so a change made meanwhile is never folded into a record\n * that is about to be dropped (or overwritten): it waits for the step, then is kept on its own.\n */\n\nimport type { MailAccount, MailMessage, MailMessageUpdate } from '../types'\nimport type { MailFileRequest } from '../filing'\nimport { blind, openJson, sealJson } from './crypto'\nimport { isNetworkFailure } from '../../offline-store/network'\nimport { deleteRecords, getRecord, putRecord, recordsInBucket } from './store'\nimport { keyOf, loadBody, loadFolders, removeKeys, saveBody, saveHeader } from './mailbox'\nimport { notifyOfflineMailChange } from './settings'\n\n/**\n * What happens to the message: a PATCH (`update`), deleting it for good (`delete`), or adding it (or\n * its whole conversation) to a workspace (`file`). A filing waits beside the message's other change,\n * never combined with it.\n */\nexport type MailChange =\n | { kind: 'update'; update: MailMessageUpdate }\n | { kind: 'delete' }\n | ({ kind: 'file' } & MailFileRequest)\n\nconst isFiling = (change: MailChange) => change.kind === 'file'\n\nexport interface PendingMailChange {\n id: string\n account: MailAccount\n /** The message's id when it was first changed (the id the server still knows it by). */\n messageId: string\n /** The folder the message was in when it was first changed. */\n folderId: string\n /** The message's final state: every change made to it since, combined. */\n change: MailChange\n createdAt: number\n /** Order first changed (a counter, not the clock). */\n seq: number\n /** Tries refused with a 401 after an unlock (an account that needs reconnecting). */\n attempts: number\n /** Trashed on the device after a move the server hasn't seen: Restore brings it back there. */\n restoreTo?: string\n /** Why the last try didn't go through. */\n error?: string\n}\n\nexport interface MailChangeSender {\n /** Make the account usable in this session (connector tokens, IMAP credentials). */\n unlock: (account: MailAccount) => Promise<void>\n /** Send the change to the server. */\n apply: (change: PendingMailChange) => Promise<void>\n}\n\n/** Tries refused with a lasting 401 before a change is given up and reported. */\nexport const MAX_ATTEMPTS = 5\n\nconst bucket = () => blind('bucket', 'changes')\nconst keyFor = (id: string) => blind('change', id)\n\nasync function write(item: PendingMailChange): Promise<void> {\n await putRecord({\n key: await keyFor(item.id),\n kind: 'change',\n bucket: await bucket(),\n sortAt: item.seq,\n size: 0,\n lastAccess: Date.now(),\n data: await sealJson(item),\n })\n}\n\nasync function drop(item: PendingMailChange): Promise<void> {\n await deleteRecords([await keyFor(item.id)])\n}\n\nasync function readHeader(\n accountId: string,\n folderId: string,\n messageId: string\n): Promise<MailMessage | undefined> {\n const record = await getRecord(await keyOf.header(accountId, folderId, messageId))\n if (!record) return undefined\n try {\n return await openJson<MailMessage>(record.data)\n } catch {\n return undefined\n }\n}\n\n/** Where `messageId` is listed on the device: each folder's copy of its header. */\nasync function deviceCopies(accountId: string, messageId: string) {\n const copies: { folderId: string; header: MailMessage }[] = []\n for (const folder of (await loadFolders(accountId)) ?? []) {\n const header = await readHeader(accountId, folder.id, messageId)\n if (header) copies.push({ folderId: folder.id, header })\n }\n return copies\n}\n\ntype DeviceChange = Pick<PendingMailChange, 'account' | 'messageId' | 'folderId' | 'change'>\n\n/**\n * Show a change in the device copy (the lists and the opened message read from it offline). Safe to\n * run again: a message already moved is not found where it was, and is left where it is.\n */\nasync function applyToDevice({ account, messageId, folderId, change }: DeviceChange) {\n // Adding to a workspace changes nothing in the mailbox.\n if (change.kind === 'file') return\n let header = await readHeader(account.id, folderId, messageId)\n let headerKey = await keyOf.header(account.id, folderId, messageId)\n if (!header) {\n // Changed from a view over the folders (Flagged): its copy is in the folder it is in.\n const [copy] = await deviceCopies(account.id, messageId)\n if (copy) {\n header = copy.header\n headerKey = await keyOf.header(account.id, copy.folderId, messageId)\n }\n }\n if (change.kind === 'delete') {\n const attachments = header?.attachments ?? []\n await removeKeys([\n headerKey,\n await keyOf.body(account.id, messageId),\n ...(await Promise.all(attachments.map((a) => keyOf.attachment(account.id, messageId, a.id)))),\n ])\n return\n }\n const { unread, flagged, folder_id: moveTo, action } = change.update\n if (unread !== undefined || flagged !== undefined) {\n const state = {\n ...(unread !== undefined && { unread }),\n ...(flagged !== undefined && { flagged }),\n }\n if (header) header = { ...header, ...state }\n // Every copy on the device shows it: a change made from the Flagged view names no folder of its\n // own, and a Gmail message is listed under each of its labels.\n for (const copy of await deviceCopies(account.id, messageId))\n await saveHeader(account.id, copy.folderId, { ...copy.header, ...state })\n const body = await loadBody(account.id, messageId)\n if (body) await saveBody(account.id, { ...body, ...state })\n }\n if (!moveTo && !action) return\n // It leaves this folder. It appears in the destination when the device knows that folder;\n // a restored message's folder is known only to the server, so it shows there after the next sync.\n if (header) await removeKeys([headerKey])\n const folders = (await loadFolders(account.id)) ?? []\n const destination =\n action === 'trash' ? folders.find((f) => f.role === 'trash')?.id : action ? undefined : moveTo\n if (header && destination && folders.some((f) => f.id === destination))\n await saveHeader(account.id, destination, header)\n}\n\ninterface Combined {\n change: MailChange\n restoreTo?: string\n}\n\n/**\n * `next` made after `pending`, as one final state; `null` when they cancel out (moved back where it\n * was, trashed and restored, or restored and trashed, with no change to read state). A message\n * moved, then trashed, then restored ends where it was moved to, as the server's restore would.\n */\nfunction combine(pending: PendingMailChange, next: MailChange): Combined | null {\n // A second filing of the message replaces the first (the last workspace chosen wins).\n if (isFiling(next) || isFiling(pending.change)) return { change: next }\n if (pending.change.kind === 'delete' || next.kind === 'delete')\n return { change: { kind: 'delete' } }\n const update: MailMessageUpdate = { ...pending.change.update }\n let restoreTo = pending.restoreTo\n if (next.update.unread !== undefined) update.unread = next.update.unread\n if (next.update.flagged !== undefined) update.flagged = next.update.flagged\n if (next.update.folder_id !== undefined || next.update.action !== undefined) {\n const before = { folder_id: update.folder_id, action: update.action }\n delete update.folder_id\n delete update.action\n restoreTo = undefined\n if (next.update.action === 'trash') {\n // Restored, then trashed again: back in the Trash, where the server has it.\n if (before.action !== 'restore') {\n update.action = 'trash'\n if (before.folder_id) restoreTo = before.folder_id\n }\n } else if (next.update.action === 'restore' && before.action === 'trash') {\n // Trashed, then restored: where it was before (a move the server hasn't seen), else nowhere.\n if (pending.restoreTo) update.folder_id = pending.restoreTo\n } else if (next.update.folder_id !== undefined) {\n if (next.update.folder_id !== pending.folderId) update.folder_id = next.update.folder_id\n } else if (next.update.action !== undefined) {\n update.action = next.update.action\n }\n }\n return Object.keys(update).length > 0 ? { change: { kind: 'update', update }, restoreTo } : null\n}\n\n/** The changes waiting for a connection, in the order their messages were first changed. */\nexport async function listMailChanges(): Promise<PendingMailChange[]> {\n const items: PendingMailChange[] = []\n for (const record of await recordsInBucket(await bucket())) {\n try {\n items.push(await openJson<PendingMailChange>(record.data))\n } catch {\n // Sealed under another identity: not this user's.\n }\n }\n return items.sort((a, b) => a.seq - b.seq)\n}\n\n/** Whether a change to this message waits on the device (a new change must combine with it). */\nexport async function hasPendingMailChange(accountId: string, messageId: string): Promise<boolean> {\n return (await listMailChanges()).some(\n (c) => c.account.id === accountId && c.messageId === messageId\n )\n}\n\nasync function queue(input: DeviceChange): Promise<void> {\n const pending = await listMailChanges()\n const existing = pending.find(\n (c) =>\n c.account.id === input.account.id &&\n c.messageId === input.messageId &&\n isFiling(c.change) === isFiling(input.change)\n )\n // Trashed, then restored before the server heard of it: it goes back where it was.\n const restoredHome =\n existing?.change.kind === 'update' &&\n existing.change.update.action === 'trash' &&\n input.change.kind === 'update' &&\n input.change.update.action === 'restore'\n const onDevice: DeviceChange =\n restoredHome && input.change.kind === 'update'\n ? {\n ...input,\n change: {\n kind: 'update',\n update: {\n unread: input.change.update.unread,\n flagged: input.change.update.flagged,\n folder_id: existing.restoreTo ?? existing.folderId,\n },\n },\n }\n : input\n // The device copy first: a change is kept only once it shows.\n await applyToDevice(onDevice)\n if (existing) {\n const combined = combine(existing, input.change)\n if (combined) await write({ ...existing, ...combined, attempts: 0, error: undefined })\n else await drop(existing)\n } else {\n await write({\n id: crypto.randomUUID(),\n ...input,\n createdAt: Date.now(),\n seq: Math.max(0, ...pending.map((c) => c.seq)) + 1,\n attempts: 0,\n })\n }\n}\n\nconst STORE_LOCK = 'arbi-mail-changes-store'\nlet chain: Promise<unknown> = Promise.resolve()\n\n/**\n * Run `fn` alone: no other queuing or replay step runs on the changes meanwhile, in this tab or\n * another (Web Locks wait their turn). Without Web Locks, one at a time in this tab.\n */\nfunction serially<T>(fn: () => Promise<T>): Promise<T> {\n if (typeof navigator !== 'undefined' && navigator.locks?.request)\n return navigator.locks.request(STORE_LOCK, fn) as Promise<T>\n const run = chain.then(fn)\n chain = run.catch(() => {})\n return run\n}\n\n/** Keep a change made offline, combined with any change to the same message still waiting. */\nexport async function queueMailChange(input: DeviceChange): Promise<void> {\n await serially(() => queue(input))\n notifyOfflineMailChange('changes')\n notifyOfflineMailChange('mailbox')\n}\n\nasync function readChange(id: string): Promise<PendingMailChange | undefined> {\n const record = await getRecord(await keyFor(id))\n if (!record) return undefined\n try {\n return await openJson<PendingMailChange>(record.data)\n } catch {\n return undefined\n }\n}\n\n/**\n * Lay the waiting changes over the device copy again, after a sync or an online read wrote the\n * server's state (where the change hasn't reached yet): a moved message must not reappear.\n */\nexport async function overlayPendingMailChanges(): Promise<void> {\n for (const change of await listMailChanges()) await applyToDevice(change)\n}\n\nexport interface ApplyChangesResult {\n applied: number\n /** Dropped because the message is no longer on the server. */\n gone: number\n /** Refused by the server, or given up after {@link MAX_ATTEMPTS} lasting 401s, with the reason. */\n refused: { change: PendingMailChange; error: string }[]\n /** Something still waits: no connection, or an account to try again later. */\n interrupted: boolean\n}\n\ntype Outcome =\n 'applied' | 'gone' | 'offline' | { wait: string; counts?: boolean } | { refused: string }\n\nconst reason = (error: unknown, fallback: string) =>\n error instanceof Error && error.message ? error.message : fallback\n\ntype Wait = { wait: string; counts: boolean }\n\nfunction classify(error: unknown): Exclude<Outcome, { wait: string }> | Wait {\n if (isNetworkFailure(error)) return 'offline'\n const status = (error as { status?: number } | null)?.status\n if (status === 404 || status === 410) return 'gone'\n // Only a session refused even after an unlock counts towards giving up.\n if (status === 401)\n return { wait: reason(error, 'Reconnect this mailbox to apply the change'), counts: true }\n if (status === undefined || status === 408 || status === 429 || status >= 500)\n return { wait: reason(error, 'The mail server could not apply the change'), counts: false }\n return { refused: reason(error, 'The server refused this change') }\n}\n\nasync function attempt(item: PendingMailChange, sender: MailChangeSender): Promise<Outcome> {\n try {\n await sender.apply(item)\n return 'applied'\n } catch (error) {\n if ((error as { status?: number }).status !== 401) return classify(error)\n // The account isn't unlocked for this session yet: unlock once and send again.\n try {\n await sender.unlock(item.account)\n await sender.apply(item)\n return 'applied'\n } catch (retryError) {\n return classify(retryError)\n }\n }\n}\n\n/** Send the waiting changes to the server, in order per account. */\nexport async function applyMailChangesOnce(\n sender: MailChangeSender,\n isOnline: () => boolean\n): Promise<ApplyChangesResult> {\n const result: ApplyChangesResult = { applied: 0, gone: 0, refused: [], interrupted: false }\n // Accounts with a change that has to wait: their later changes wait behind it.\n const waiting = new Set<string>()\n for (const listed of await listMailChanges()) {\n if (!isOnline()) {\n result.interrupted = true\n break\n }\n if (waiting.has(listed.account.id)) continue\n // Read, send and settle in one step: a change made meanwhile waits, and is then kept.\n const outcome = await serially(async (): Promise<Outcome | null> => {\n const item = await readChange(listed.id)\n if (!item) return null\n const sent = await attempt(item, sender)\n if (sent === 'offline') return sent\n if (typeof sent === 'object' && 'wait' in sent) {\n const attempts = item.attempts + (sent.counts ? 1 : 0)\n if (attempts < MAX_ATTEMPTS) {\n // Not announced: it is the same change, still waiting.\n await write({ ...item, attempts, error: sent.wait })\n return sent\n }\n await drop(item)\n result.refused.push({ change: item, error: sent.wait })\n return { refused: sent.wait }\n }\n await drop(item)\n if (sent === 'applied') result.applied++\n else if (sent === 'gone') result.gone++\n else result.refused.push({ change: item, error: sent.refused })\n return sent\n })\n if (outcome === 'offline') {\n result.interrupted = true\n break\n }\n if (outcome && typeof outcome === 'object' && 'wait' in outcome) {\n waiting.add(listed.account.id)\n result.interrupted = true\n }\n }\n if (result.applied + result.gone + result.refused.length > 0) notifyOfflineMailChange('changes')\n return result\n}\n","/**\n * Adding mail to a workspace: this message, or the whole conversation (its future replies too, until\n * the rule is stopped). It becomes a document only the person who added it can see.\n *\n * One mechanism for every mailbox (the mailbox-sync tables). ARBI mail that arrives in a filed\n * folder or conversation while you are away waits; it is filed the next time you open the\n * workspace, with your session (the connectors' auto-sync trigger, `useConnectorAutoSync`). A\n * connected account's new messages in a filed conversation are added by this app while it lists\n * them (`useConnectedMailFiling`): only while the app is open and syncing.\n */\n\nimport { useCallback, useEffect, useRef } from 'react'\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'\nimport { logger } from '@arbidocs/client'\nimport { mail as mailOps } from '@arbidocs/sdk/browser'\nimport { useArbiHost } from '../host/config'\nimport { inWorkspace, primeOnArbi, type WorkspacePrimer } from '../queued-writes'\nimport { mailQueryKeys } from '../query-keys'\nimport type { MailFetch } from './client'\nimport { useMailOnline } from './hooks'\nimport { useMailClient } from './useMailClient'\nimport { mailConversationKey } from './threads'\nimport type {\n MailAccount,\n MailFiled,\n MailFilingState,\n MailMessage,\n NativeMailFiling,\n} from './types'\n\n/** What to add: one message, or (with `threadId`) a conversation, its `messageIds` now and its replies. */\nexport interface MailFileRequest {\n workspaceExtId: string\n threadId?: string\n messageIds?: string[]\n}\n\n/** Nothing to deposit: the host keeps the workspace's key on the session itself. */\nconst NO_PRIMER: WorkspacePrimer = () => undefined\n\n/**\n * Send a filing to the server in its workspace (its key deposited on the session first, without\n * switching to it); resolves with where the message went. Used online and when a filing made\n * offline is replayed.\n */\nexport async function sendMailFile(\n fetch: MailFetch,\n prime: WorkspacePrimer,\n account: Pick<MailAccount, 'id'>,\n messageId: string,\n request: MailFileRequest\n): Promise<MailFiled | undefined> {\n const { threadId } = request\n return inWorkspace(prime, request.workspaceExtId, async () => {\n if (!threadId) return mailOps.fileMessage(fetch, messageId, request.workspaceExtId, account.id)\n const { filed } = await mailOps.fileConversation(fetch, {\n accountId: account.id,\n threadId,\n messageIds: request.messageIds?.length ? request.messageIds : [messageId],\n workspaceExtId: request.workspaceExtId,\n })\n return filed.find((f) => f.message_id === messageId) ?? filed[0]\n })\n}\n\n/** The workspace primer of the host's session (none without one). */\nexport function useMailWorkspacePrimer(): WorkspacePrimer {\n const { arbi } = useArbiHost()\n return arbi ? primeOnArbi(arbi) : NO_PRIMER\n}\n\n/** Which of these messages are in a workspace, and which of these conversations add replies to one. */\nexport function useMailFiling(\n account: MailAccount | undefined,\n messageIds: string[],\n threadIds: string[],\n options: { enabled?: boolean } = {}\n) {\n const { client } = useMailClient()\n const isOnline = useMailOnline()\n return useQuery<MailFilingState>({\n queryKey: mailQueryKeys.filing(account?.id, messageIds, threadIds),\n queryFn: () =>\n mailOps.getFilingState(client.fetch, { accountId: account!.id, messageIds, threadIds }),\n enabled:\n !!account &&\n isOnline &&\n (messageIds.length > 0 || threadIds.length > 0) &&\n (options.enabled ?? true),\n retry: false,\n })\n}\n\n/** Stop adding a conversation's replies to its workspace (what was added stays). */\nexport function useStopMailFilingRule() {\n const { client } = useMailClient()\n const queryClient = useQueryClient()\n return useMutation({\n mutationFn: ({ ruleId, threadId }: { ruleId: string; threadId: string }) =>\n mailOps.stopFilingConversation(client.fetch, ruleId, threadId),\n onSuccess: () => queryClient.invalidateQueries({ queryKey: mailQueryKeys.allFiling() }),\n })\n}\n\n/** Where the ARBI mailbox files mail: per workspace, its folders and conversations. */\nexport function useNativeMailFiling(options: { enabled?: boolean } = {}) {\n const { client, enabled } = useMailClient()\n return useQuery<NativeMailFiling[]>({\n queryKey: mailQueryKeys.nativeFiling(),\n queryFn: () => mailOps.listNativeFiling(client.fetch),\n enabled: enabled && (options.enabled ?? true),\n retry: false,\n })\n}\n\n/** File the ARBI mailbox's folders into a workspace, ongoing (the import panel's sync dialog). */\nexport function useSetNativeMailFiling() {\n const { client } = useMailClient()\n const prime = useMailWorkspacePrimer()\n const queryClient = useQueryClient()\n return useMutation({\n mutationFn: (input: {\n workspaceExtId: string\n folders: ('inbox' | 'sent' | 'archive')[]\n backfillWindow?: number\n }) =>\n inWorkspace(prime, input.workspaceExtId, () => mailOps.setNativeFiling(client.fetch, input)),\n onSuccess: () => queryClient.invalidateQueries({ queryKey: mailQueryKeys.allFiling() }),\n })\n}\n\n/**\n * File the ARBI mail waiting for a workspace now, with this session (it is also filed whenever the\n * workspace is opened, by the connectors' auto-sync trigger).\n */\nexport function useFileWaitingNativeMail() {\n const { arbi } = useArbiHost()\n const queryClient = useQueryClient()\n return useMutation({\n mutationFn: (workspaceExtId: string) => {\n if (!arbi) throw new Error('Filing needs a signed-in session')\n return arbi.mail.fileWaiting(workspaceExtId)\n },\n onSuccess: () => queryClient.invalidateQueries({ queryKey: mailQueryKeys.allFiling() }),\n })\n}\n\n/**\n * A connected account's new messages in a filed conversation, added by this app as it lists them\n * (ARBI does not store that mail, so the server can't). Each message is tried once per page life.\n */\nexport function useConnectedMailFiling(\n account: MailAccount | undefined,\n messages: MailMessage[] | undefined\n): void {\n const { client, enabled } = useMailClient()\n const isOnline = useMailOnline()\n const prime = useMailWorkspacePrimer()\n const queryClient = useQueryClient()\n const tried = useRef(new Set<string>())\n const run = useCallback(\n async (connected: MailAccount, listed: MailMessage[]) => {\n const fresh = listed.filter((m) => m.thread_id && !tried.current.has(m.id))\n if (!fresh.length) return\n for (const m of fresh) tried.current.add(m.id)\n const threadIds = [...new Set(fresh.map(mailConversationKey))]\n const state = await mailOps.getFilingState(client.fetch, {\n accountId: connected.id,\n messageIds: fresh.map((m) => m.id),\n threadIds,\n })\n const filed = new Set(state.filed.map((f) => f.message_id))\n const rules = new Map(state.rules.map((r) => [r.thread_id, r]))\n let added = 0\n for (const message of fresh) {\n const rule = rules.get(mailConversationKey(message))\n if (!rule || filed.has(message.id)) continue\n try {\n await sendMailFile(client.fetch, prime, connected, message.id, {\n workspaceExtId: rule.workspace_ext_id,\n threadId: mailConversationKey(message),\n messageIds: [message.id],\n })\n added++\n } catch (error) {\n // One that can't be added now must not keep the others out.\n logger.warn('[mail] could not add a message to its conversation’s workspace', error)\n }\n }\n if (added) await queryClient.invalidateQueries({ queryKey: mailQueryKeys.allFiling() })\n },\n [client, prime, queryClient]\n )\n useEffect(() => {\n if (!enabled || !isOnline || !account || account.provider === 'native' || !messages?.length)\n return\n run(account, messages).catch((error) =>\n logger.warn('[mail] could not add new mail to its conversation’s workspace', error)\n )\n }, [account, messages, enabled, isOnline, run])\n}\n","/**\n * Drafts saved while offline. They are kept (encrypted) on this device and uploaded to the account's\n * server Drafts as soon as the connection is back; once the server has a draft, the local copy is\n * removed and the server draft is the one shown. Editing a server draft offline keeps its\n * `draft_id`, so the upload replaces it instead of adding a second draft.\n */\n\nimport type { MailCompose } from '../types'\nimport { blind, openJson, sealJson } from './crypto'\nimport { isNetworkFailure } from '../../offline-store/network'\nimport { deleteRecords, putRecord, recordsOfKind } from './store'\nimport { notifyOfflineMailChange } from './settings'\n\nexport interface LocalDraft {\n id: string\n accountId: string\n compose: MailCompose\n updatedAt: number\n /** Set when the server refused the upload (e.g. too large); otherwise it waits for a connection. */\n error?: string\n}\n\nconst keyFor = (id: string) => blind('draft', id)\n\nexport async function saveLocalDraft(\n accountId: string,\n compose: MailCompose,\n id: string = crypto.randomUUID()\n): Promise<LocalDraft> {\n const draft: LocalDraft = { id, accountId, compose, updatedAt: Date.now() }\n await putRecord({\n key: await keyFor(id),\n kind: 'draft',\n bucket: await blind('bucket', 'drafts', accountId),\n sortAt: draft.updatedAt,\n size: 0,\n lastAccess: draft.updatedAt,\n data: await sealJson(draft),\n })\n notifyOfflineMailChange('drafts')\n return draft\n}\n\nexport async function listLocalDrafts(accountId?: string): Promise<LocalDraft[]> {\n const drafts: LocalDraft[] = []\n for (const record of await recordsOfKind('draft')) {\n try {\n const draft = await openJson<LocalDraft>(record.data)\n if (!accountId || draft.accountId === accountId) drafts.push(draft)\n } catch {\n // Another identity's record: ignore.\n }\n }\n return drafts.sort((a, b) => b.updatedAt - a.updatedAt)\n}\n\nexport async function deleteLocalDraft(id: string): Promise<void> {\n await deleteRecords([await keyFor(id)])\n notifyOfflineMailChange('drafts')\n}\n\n/**\n * Upload every local draft. `save` posts one draft to the server and resolves with its id. Stops at\n * the first network failure (the rest wait for the next reconnect); a refusal is recorded on the\n * draft so the user sees why it is still only on this device.\n */\nexport async function syncLocalDrafts(\n save: (draft: LocalDraft) => Promise<{ id: string }>\n): Promise<number> {\n let uploaded = 0\n for (const draft of await listLocalDrafts()) {\n if (draft.error) continue\n try {\n await save(draft)\n await deleteLocalDraft(draft.id)\n uploaded++\n } catch (error) {\n const status = (error as { status?: number }).status\n // No answer, a session to unlock, or a server hiccup: keep it and try on the next reconnect.\n if (isNetworkFailure(error) || status === undefined || status === 401 || status >= 500) break\n await putRecord({\n key: await keyFor(draft.id),\n kind: 'draft',\n bucket: await blind('bucket', 'drafts', draft.accountId),\n sortAt: draft.updatedAt,\n size: 0,\n lastAccess: Date.now(),\n data: await sealJson({\n ...draft,\n error: error instanceof Error ? error.message : 'The server refused this draft',\n }),\n })\n notifyOfflineMailChange('drafts')\n }\n }\n return uploaded\n}\n","/**\n * The mail Outbox: messages the user pressed Send on while offline (or whose send could not reach\n * the server), kept encrypted on this device and sent in order once the connection is back.\n *\n * Exactly-once: every message keeps the `request_id` it was given when the user pressed Send, for\n * its whole life in the Outbox. The send endpoints deduplicate on it (Redis reservation plus a\n * durable record per request_id), so a replay after a lost response, a reload mid-send, or two open\n * tabs flushing at once returns the first result instead of sending again. A secure message is\n * prepared (encrypted, recipient keys generated) once and that exact payload is stored and replayed,\n * because the server fingerprints the ciphertext.\n *\n * Outcomes:\n * - network down / session not ready: the message goes back to \"queued\" and the flush stops, to\n * resume in order on the next reconnect;\n * - refused (4xx): \"failed\" with the server's reason; Retry resends the same request_id;\n * - unknown outcome (409 already attempted, 5xx, unconfirmed relay): \"failed\" and marked\n * `inDoubt` — the message may have gone out, so the UI says to check Sent; Retry is still safe\n * (same request_id), it reports \"sent\" if the first attempt completed.\n */\n\nimport type { MailAccount, MailCompose } from '../types'\nimport { blind, openJson, sealJson } from './crypto'\nimport { isNetworkFailure } from '../../offline-store/network'\nimport { deleteRecords, putRecord, recordsInBucket } from './store'\nimport { notifyOfflineMailChange } from './settings'\n\ntype OutboxStatus = 'queued' | 'sending' | 'sent' | 'failed'\n\nexport interface OutboxItem {\n id: string\n /** The idempotency key sent with every attempt. Never changes for this item. */\n requestId: string\n account: MailAccount\n compose: MailCompose\n secure: boolean\n /** The encrypted secure-delivery request, prepared on the first attempt and replayed as is. */\n securePayload?: unknown\n status: OutboxStatus\n error?: string\n /** The server may already have sent it (unknown outcome). */\n inDoubt?: boolean\n attempts: number\n createdAt: number\n sentAt?: number\n /** Enqueue order. */\n seq: number\n}\n\nexport interface OutboxSender {\n /** Prepare the secure payload for an item (only for secure items, once). */\n prepareSecure: (item: OutboxItem) => Promise<unknown>\n /** Make the account usable in this session before sending (connector tokens, IMAP credentials). */\n unlock: (account: MailAccount) => Promise<void>\n /** POST the message; resolves with the server's message id. */\n send: (item: OutboxItem) => Promise<{ id?: string }>\n}\n\nconst bucket = () => blind('bucket', 'outbox')\nconst keyFor = (id: string) => blind('outbox', id)\n\n/** Problems that make a message unsendable from the Outbox, reported when the user presses Send. */\nfunction outboxProblem(compose: MailCompose): string | null {\n const missing = compose.attachments.find((a) => a.content_base64 == null)\n if (missing)\n return `${missing.name} isn't saved on this device, so it can't be sent offline. Remove it or send once you're back online.`\n return null\n}\n\nlet seqCounter = 0\n\nasync function write(item: OutboxItem): Promise<void> {\n await putRecord({\n key: await keyFor(item.id),\n kind: 'outbox',\n bucket: await bucket(),\n sortAt: item.seq,\n size: 0,\n lastAccess: Date.now(),\n data: await sealJson(item),\n })\n}\n\nexport async function listOutbox(): Promise<OutboxItem[]> {\n const records = await recordsInBucket(await bucket())\n const items: OutboxItem[] = []\n for (const record of records) {\n try {\n items.push(await openJson<OutboxItem>(record.data))\n } catch {\n // Sealed under a different identity: not this user's mail; ignore.\n }\n }\n return items.sort((a, b) => a.seq - b.seq)\n}\n\nexport async function enqueueOutbox(input: {\n account: MailAccount\n compose: MailCompose\n requestId: string\n secure: boolean\n securePayload?: unknown\n}): Promise<OutboxItem> {\n const problem = outboxProblem(input.compose)\n if (problem) throw new Error(problem)\n const now = Date.now()\n // Monotonic even when two messages are queued in the same millisecond.\n seqCounter = Math.max(seqCounter + 1, now * 1000)\n const item: OutboxItem = {\n id: crypto.randomUUID(),\n requestId: input.requestId,\n account: input.account,\n compose: input.compose,\n secure: input.secure,\n securePayload: input.securePayload,\n status: 'queued',\n attempts: 0,\n createdAt: now,\n seq: seqCounter,\n }\n await write(item)\n notifyOfflineMailChange('outbox')\n return item\n}\n\nasync function update(item: OutboxItem, patch: Partial<OutboxItem>): Promise<OutboxItem> {\n const next = { ...item, ...patch }\n await write(next)\n notifyOfflineMailChange('outbox')\n return next\n}\n\nexport async function deleteOutboxItem(id: string): Promise<void> {\n await deleteRecords([await keyFor(id)])\n notifyOfflineMailChange('outbox')\n}\n\n/** Put a failed message back in the queue (same request_id, so it can't go out twice). */\nexport async function retryOutboxItem(id: string): Promise<void> {\n const item = (await listOutbox()).find((i) => i.id === id)\n if (item && item.status === 'failed')\n await update(item, { status: 'queued', error: undefined, inDoubt: item.inDoubt })\n}\n\ntype Outcome =\n | { kind: 'sent'; serverId?: string }\n | { kind: 'offline' }\n | { kind: 'failed'; error: string; inDoubt: boolean }\n\nconst IN_DOUBT_MESSAGE =\n \"The mail server didn't confirm this message. It may already have been sent: check Sent before sending it again.\"\n\nfunction classify(error: unknown): Outcome {\n // No answer at all: wait for the connection (the request may have arrived; the replay is safe).\n if (isNetworkFailure(error)) return { kind: 'offline' }\n const status = (error as { status?: number } | null)?.status\n const detail = error instanceof Error ? error.message : 'The message could not be sent'\n // Refused before any request left this device (e.g. the session must be signed in again).\n if (status === undefined) return { kind: 'failed', error: detail, inDoubt: false }\n if (status === 409) return { kind: 'failed', error: IN_DOUBT_MESSAGE, inDoubt: true }\n if (status >= 500) return { kind: 'failed', error: IN_DOUBT_MESSAGE, inDoubt: true }\n return { kind: 'failed', error: detail, inDoubt: false }\n}\n\n/** Prepare a secure message's encrypted request once, persisted before it is ever sent. */\nasync function prepared(item: OutboxItem, sender: OutboxSender): Promise<OutboxItem> {\n if (!item.secure || item.securePayload !== undefined) return item\n // Persist before the request: a replay must carry this exact ciphertext (the server\n // fingerprints it), so it is never prepared a second time.\n return update(item, { securePayload: await sender.prepareSecure(item) })\n}\n\nasync function attempt(item: OutboxItem, sender: OutboxSender): Promise<Outcome> {\n try {\n const result = await sender.send(item)\n return { kind: 'sent', serverId: result?.id }\n } catch (error) {\n const outcome = classify(error)\n // A session that hasn't been unlocked for this account yet: unlock once and replay.\n if ((error as { status?: number }).status === 401) {\n try {\n await sender.unlock(item.account)\n const result = await sender.send(item)\n return { kind: 'sent', serverId: result?.id }\n } catch (retryError) {\n return classify(retryError)\n }\n }\n return outcome\n }\n}\n\nexport interface FlushResult {\n sent: number\n failed: number\n /** Stopped early because the connection dropped; the rest stays queued. */\n interrupted: boolean\n}\n\n/**\n * Send every queued message in order. Messages left \"sending\" by a closed tab are replayed with\n * their request_id. Stops (keeping order) when the network goes away; a failed message does not\n * hold back the ones after it.\n */\nexport async function flushOutboxOnce(\n sender: OutboxSender,\n isOnline: () => boolean\n): Promise<FlushResult> {\n const result: FlushResult = { sent: 0, failed: 0, interrupted: false }\n const unlocked = new Set<string>()\n for (;;) {\n if (!isOnline()) {\n result.interrupted = true\n break\n }\n const next = (await listOutbox()).find((i) => i.status === 'queued' || i.status === 'sending')\n if (!next) break\n let item = await update(next, { status: 'sending', attempts: next.attempts + 1 })\n try {\n item = await prepared(item, sender)\n } catch (error) {\n // Local preparation failed (nothing was sent): a refusal the user can fix and retry.\n const message = error instanceof Error ? error.message : 'Could not encrypt the message'\n await update(item, { status: 'failed', error: message })\n result.failed++\n continue\n }\n if (!unlocked.has(item.account.id)) {\n // Connected accounts need this session's tokens; a failure here surfaces as the send's 401.\n await sender.unlock(item.account).catch(() => {})\n unlocked.add(item.account.id)\n }\n const outcome = await attempt(item, sender)\n if (outcome.kind === 'sent') {\n item = await update(item, {\n status: 'sent',\n sentAt: Date.now(),\n error: undefined,\n inDoubt: false,\n })\n result.sent++\n } else if (outcome.kind === 'offline') {\n await update(item, { status: 'queued' })\n result.interrupted = true\n break\n } else {\n await update(item, {\n status: 'failed',\n error: outcome.error,\n inDoubt: item.inDoubt || outcome.inDoubt,\n })\n result.failed++\n }\n }\n return result\n}\n\n/** Drop sent messages older than `olderThanMs` from the Outbox view. */\nexport async function purgeSentOutbox(olderThanMs = 0): Promise<void> {\n const cutoff = Date.now() - olderThanMs\n const done = (await listOutbox()).filter((i) => i.status === 'sent' && (i.sentAt ?? 0) <= cutoff)\n if (done.length === 0) return\n await deleteRecords(await Promise.all(done.map((i) => keyFor(i.id))))\n notifyOfflineMailChange('outbox')\n}\n","/**\n * Mailbox sync: copies the user's mail (native inbox and connected accounts, through the same list/\n * get endpoints the Mail page uses) into the encrypted offline store, incrementally.\n *\n * For each account → folder, list pages newest first within the chosen scope. Headers are always\n * refreshed (cheap: read/unread and moves show up); a body and its attachments are fetched only for\n * a message not saved yet. A quick pass stops at the first page that holds nothing new; a full pass\n * (hourly, or \"Sync now\") walks the whole scope and drops what was deleted or moved on the server.\n *\n * Space: attachments of one message are saved up to the per-message cap; the whole store is held\n * under the quota, evicting the least recently opened attachments first, then the oldest bodies.\n * A message whose body isn't saved still lists offline and says so when opened.\n *\n * Window: only mail received within the chosen window is kept (`trimOfflineMailbox`, after every\n * pass and as soon as the setting changes, offline too). A longer window than the last full pass\n * covered makes the next pass a full one, which fetches the older mail.\n */\n\nimport type { MailAccount, MailFolder, MailMessage, MailPolicy } from '../types'\nimport { logger } from '@arbidocs/client'\nimport {\n bucketOf,\n hasAttachment,\n hasBody,\n isVirtualFolder,\n keyOf,\n loadAccounts,\n loadFolders,\n loadHeaders,\n removeKeys,\n saveAccounts,\n saveAttachment,\n saveBody,\n saveFolders,\n saveHeader,\n savePolicy,\n toHeader,\n} from './mailbox'\nimport { allRecordSizes, getMeta, recordsInBucket, recordsOfKind, setMeta } from './store'\nimport { overlayPendingMailChanges } from './changes'\nimport {\n notifyOfflineMailChange,\n offlineWindowStart,\n SCOPE_DAYS,\n type OfflineMailSettings,\n} from './settings'\n\nexport interface MailTransport {\n policy: () => Promise<MailPolicy>\n accounts: () => Promise<MailAccount[]>\n unlock: (account: MailAccount) => Promise<void>\n folders: (account: MailAccount) => Promise<MailFolder[]>\n messages: (\n account: MailAccount,\n folderId: string,\n cursor: string | null\n ) => Promise<{ messages: MailMessage[]; next_cursor?: string | null }>\n message: (account: MailAccount, messageId: string) => Promise<MailMessage>\n attachment: (account: MailAccount, messageId: string, attachmentId: string) => Promise<Uint8Array>\n}\n\nexport interface OfflineMailStatus {\n lastSyncedAt?: number\n lastFullSyncAt?: number\n messages: number\n bytes: number\n /** Why the last sync didn't finish, in plain words. */\n error?: string\n /** Accounts that could not be synced (e.g. need reconnecting), by email. */\n skipped: string[]\n /** The window (days) the last full pass covered; a longer one needs another full pass. */\n windowDays?: number\n}\n\nconst STATUS_KEY = 'status'\nconst FULL_SYNC_EVERY_MS = 60 * 60 * 1000\n/** Safety stop per folder per pass. */\nconst MAX_PAGES = 200\n\nexport async function getOfflineMailStatus(): Promise<OfflineMailStatus> {\n return (await getMeta<OfflineMailStatus>(STATUS_KEY)) ?? { messages: 0, bytes: 0, skipped: [] }\n}\n\nconst MB = 1024 * 1024\nconst time = (m: MailMessage) => (m.received_at ? Date.parse(m.received_at) || 0 : 0)\nconst sameHeader = (a: MailMessage, b: MailMessage) =>\n JSON.stringify(toHeader(a)) === JSON.stringify(toHeader(b))\n\nclass Budget {\n constructor(\n public used: number,\n private readonly quota: number\n ) {}\n get full() {\n return this.used >= this.quota\n }\n take(bytes: number) {\n this.used += bytes\n }\n}\n\nasync function saveMessageContent(\n transport: MailTransport,\n account: MailAccount,\n header: MailMessage,\n settings: OfflineMailSettings,\n budget: Budget\n): Promise<void> {\n const message = await transport.message(account, header.id)\n await saveBody(account.id, message)\n budget.take((message.text?.length ?? 0) + (message.html?.length ?? 0))\n let attachmentBytes = 0\n for (const attachment of message.attachments) {\n if (budget.full) return\n if (attachmentBytes + attachment.size > settings.attachmentCapMb * MB) continue\n if (await hasAttachment(account.id, message.id, attachment.id)) continue\n const bytes = attachment.content_base64\n ? Uint8Array.from(atob(attachment.content_base64), (c) => c.charCodeAt(0))\n : await transport.attachment(account, message.id, attachment.id)\n await saveAttachment(account.id, message.id, attachment.id, bytes, time(message))\n attachmentBytes += bytes.byteLength\n budget.take(bytes.byteLength)\n }\n}\n\nasync function syncFolder(\n transport: MailTransport,\n account: MailAccount,\n folder: MailFolder,\n settings: OfflineMailSettings,\n windowStart: number,\n full: boolean,\n budget: Budget\n): Promise<void> {\n const saved = new Map(\n (await loadHeaders(account.id, folder.id)).map((h) => [h.message.id, h] as const)\n )\n const seen = new Set<string>()\n let oldestSeen = Infinity\n let cursor: string | null = null\n let reachedEnd = false\n for (let page = 0; page < MAX_PAGES; page++) {\n const result = await transport.messages(account, folder.id, cursor)\n let anythingNew = false\n let outOfScope = false\n for (const message of result.messages) {\n const at = time(message)\n if (at && at < windowStart) {\n outOfScope = true\n break\n }\n seen.add(message.id)\n if (at) oldestSeen = Math.min(oldestSeen, at)\n const previous = saved.get(message.id)?.message\n if (!previous || !sameHeader(previous, message)) {\n await saveHeader(account.id, folder.id, message)\n anythingNew = true\n }\n if (!budget.full && !(await hasBody(account.id, message.id))) {\n try {\n await saveMessageContent(transport, account, message, settings, budget)\n anythingNew = true\n } catch (error) {\n // One unreadable message must not stop the folder; it lists, and says it isn't saved.\n logger.warn('[offline-mail] could not save a message body', error)\n }\n }\n }\n cursor = result.next_cursor ?? null\n if (outOfScope || !cursor) {\n reachedEnd = true\n break\n }\n if (!full && !anythingNew) break\n }\n // Drop what the server no longer has here: everything unseen in the range this pass covered\n // (the whole folder when it reached the end of the scope).\n const stale = [...saved.values()].filter(\n (h) => !seen.has(h.message.id) && (reachedEnd || h.sortAt >= oldestSeen)\n )\n await removeKeys(stale.map((h) => h.key))\n}\n\n/** Remove bodies/attachments no header points to any more, and folders/accounts that went away. */\nasync function collectGarbage(accounts: MailAccount[]): Promise<void> {\n for (const account of accounts) {\n const folders = (await loadFolders(account.id)) ?? []\n const expected = new Set<string>([await keyOf.folders(account.id)])\n for (const folder of folders) {\n for (const { message } of await loadHeaders(account.id, folder.id)) {\n expected.add(await keyOf.body(account.id, message.id))\n for (const attachment of message.attachments)\n expected.add(await keyOf.attachment(account.id, message.id, attachment.id))\n }\n }\n const orphans = (await recordsInBucket(await bucketOf.account(account.id)))\n .filter((r) => (r.kind === 'body' || r.kind === 'attachment') && !expected.has(r.key))\n .map((r) => r.key)\n await removeKeys(orphans)\n }\n}\n\nasync function forgetAccount(accountId: string): Promise<void> {\n for (const folder of (await loadFolders(accountId)) ?? []) {\n const records = await recordsInBucket(await bucketOf.folder(accountId, folder.id))\n await removeKeys(records.map((r) => r.key))\n }\n const records = await recordsInBucket(await bucketOf.account(accountId))\n await removeKeys(records.filter((r) => r.kind !== 'draft').map((r) => r.key))\n}\n\n/** Hold the store under the quota: least recently opened attachments first, then oldest bodies. */\nexport async function enforceQuota(quotaBytes: number): Promise<number> {\n let used = (await allRecordSizes()).reduce((n, r) => n + r.size, 0)\n if (used <= quotaBytes) return used\n for (const kind of ['attachment', 'body'] as const) {\n const records = (await recordsOfKind(kind)).sort((a, b) =>\n kind === 'attachment' ? a.lastAccess - b.lastAccess : a.sortAt - b.sortAt\n )\n const evict: string[] = []\n for (const record of records) {\n if (used <= quotaBytes) break\n evict.push(record.key)\n used -= record.size\n }\n await removeKeys(evict)\n if (used <= quotaBytes) break\n }\n return used\n}\n\nconst CONTENT_KINDS = ['header', 'body', 'attachment'] as const\n\n/**\n * Hold the device copy to the chosen window, with no network: mail received before it goes (its\n * list row, body and attachments; an undated message stays). Off: every folder and message goes,\n * and only the accounts, drafts and the Outbox stay. Returns the status with the new totals.\n */\nexport async function trimOfflineMailbox(\n settings: OfflineMailSettings,\n now = Date.now()\n): Promise<OfflineMailStatus> {\n const windowStart = offlineWindowStart(settings, now)\n const kinds = settings.enabled ? CONTENT_KINDS : ([...CONTENT_KINDS, 'folders'] as const)\n for (const kind of kinds) {\n const records = await recordsOfKind(kind)\n const old = settings.enabled\n ? records.filter((r) => r.sortAt > 0 && r.sortAt < windowStart)\n : records\n await removeKeys(old.map((r) => r.key))\n }\n const previous = await getOfflineMailStatus()\n const status: OfflineMailStatus = {\n ...previous,\n messages: (await recordsOfKind('header')).length,\n bytes: (await allRecordSizes()).reduce((n, r) => n + r.size, 0),\n // A shorter window no longer covers what the last full pass fetched: growing it again (even\n // before the next hourly full pass) makes the next pass a full one.\n windowDays:\n settings.enabled && previous.windowDays !== undefined\n ? Math.min(previous.windowDays, SCOPE_DAYS[settings.scope])\n : undefined,\n // Off: nothing is saved, so turning it back on starts with a full pass.\n ...(!settings.enabled && { lastSyncedAt: undefined, lastFullSyncAt: undefined }),\n }\n await setMeta(STATUS_KEY, status)\n notifyOfflineMailChange('status')\n return status\n}\n\n/**\n * One sync pass. Never throws: the outcome is recorded in the status (and announced), because it\n * runs in the background and a failure must show up as \"couldn't sync\", not vanish.\n *\n * `latest` reads the settings again at the end: a window shortened (or Off chosen) while the pass\n * ran is what the device copy is trimmed to, not the settings the pass started with.\n */\nexport async function syncMailbox(\n transport: MailTransport,\n settings: OfflineMailSettings,\n options: { full?: boolean; now?: number; latest?: () => OfflineMailSettings } = {}\n): Promise<OfflineMailStatus> {\n const now = options.now ?? Date.now()\n const previous = await getOfflineMailStatus()\n const days = SCOPE_DAYS[settings.scope]\n const full =\n options.full ||\n !previous.lastFullSyncAt ||\n now - previous.lastFullSyncAt > FULL_SYNC_EVERY_MS ||\n (previous.windowDays ?? 0) < days\n const windowStart = offlineWindowStart(settings, now)\n const quota = settings.quotaMb * MB\n const skipped: string[] = []\n let error: string | undefined\n try {\n await savePolicy(await transport.policy())\n const accounts = await transport.accounts()\n const before = (await loadAccounts()) ?? []\n await saveAccounts(accounts)\n for (const gone of before.filter((b) => !accounts.some((a) => a.id === b.id)))\n await forgetAccount(gone.id)\n const budget = new Budget(\n (await allRecordSizes()).reduce((n, r) => n + r.size, 0),\n quota\n )\n for (const account of accounts) {\n if (account.needs_reconsent) {\n skipped.push(account.email)\n continue\n }\n try {\n await transport.unlock(account)\n const folders = await transport.folders(account)\n const oldFolders = (await loadFolders(account.id)) ?? []\n await saveFolders(account.id, folders)\n for (const gone of oldFolders.filter((o) => !folders.some((f) => f.id === o.id))) {\n const records = await recordsInBucket(await bucketOf.folder(account.id, gone.id))\n await removeKeys(records.map((r) => r.key))\n }\n // Flagged is a view over the other folders: its messages are saved where they are.\n for (const folder of folders.filter((f) => !isVirtualFolder(f)))\n await syncFolder(transport, account, folder, settings, windowStart, full, budget)\n notifyOfflineMailChange('mailbox')\n } catch (accountError) {\n // Network loss mid-sync: stop; everything saved so far stays and the next pass continues.\n if ((accountError as { status?: number }).status === undefined) throw accountError\n logger.warn('[offline-mail] account sync failed', accountError)\n skipped.push(account.email)\n }\n }\n if (full) await collectGarbage(accounts)\n } catch (syncError) {\n error =\n (syncError as { status?: number }).status === undefined\n ? 'The connection dropped during sync. It will continue when you are back online.'\n : syncError instanceof Error\n ? syncError.message\n : 'Sync failed'\n }\n // Changes made offline that the server hasn't applied yet: the pass wrote the server's state.\n await overlayPendingMailChanges().catch((overlayError) =>\n logger.warn('[offline-mail] could not lay pending changes over the device copy', overlayError)\n )\n // Mail that aged out of the window since the last pass, under the settings as they are now.\n const current = options.latest?.() ?? settings\n const trimmed = await trimOfflineMailbox(current, now)\n // Off was chosen while this pass ran: nothing stays, and nothing counts as synced.\n if (!current.enabled) return trimmed\n const bytes = await enforceQuota(current.quotaMb * MB)\n const messages = (await recordsOfKind('header')).length\n const fullDone = !error && full\n const status: OfflineMailStatus = {\n lastSyncedAt: error ? previous.lastSyncedAt : now,\n lastFullSyncAt: fullDone ? now : previous.lastFullSyncAt,\n windowDays: fullDone ? Math.min(days, SCOPE_DAYS[current.scope]) : trimmed.windowDays,\n messages,\n bytes,\n error,\n skipped,\n }\n await setMeta(STATUS_KEY, status)\n notifyOfflineMailChange('status')\n return status\n}\n","/**\n * The offline mailbox's connection to the real API (the session's `arbi.mail`), and the runners\n * that the app-wide runtime (`useOfflineMailRuntime`) and the mailbox call: flush the Outbox, apply\n * the changes made offline, upload offline drafts, sync.\n *\n * Each runner holds a Web Lock, so with several tabs open exactly one does the work at a time (the\n * send endpoints are idempotent anyway; the lock just avoids duplicate traffic).\n */\n\nimport { sendMailFile } from '../filing'\nimport { primeOnArbi } from '../../queued-writes'\nimport { onlineManager, type QueryClient } from '@tanstack/react-query'\nimport type { Arbi } from '@arbidocs/sdk/browser'\nimport { logger } from '@arbidocs/client'\nimport { notify } from '../../notifications/notify-store'\nimport { accountPath, mailJson } from '../client'\nimport { mailQueryKeys } from '../hooks'\nimport type { MailAccount, MailCompose, MailFolder, MailMessage, MailPolicy } from '../types'\nimport { syncLocalDrafts } from './drafts'\nimport { applyMailChangesOnce, type MailChangeSender } from './changes'\nimport { flushOutboxOnce, listOutbox, purgeSentOutbox, type OutboxSender } from './outbox'\nimport { getOfflineMailSettings, notifyOfflineMailChange } from './settings'\nimport { requestPersistentStorage } from '../../documents/offline-documents'\nimport { syncMailbox, type MailTransport } from './sync'\n\n/** What a runner works with: the signed-in session's `Arbi` and the query cache it refreshes. */\nexport interface OfflineMailContext {\n arbi: Arbi\n queryClient: QueryClient\n /** Show the Outbox (\"Open Outbox\" on a notice that a message could not be sent). */\n openOutbox?: () => void\n}\n\n/** The folder role of the device Outbox. */\nexport const OUTBOX_FOLDER = 'outbox'\n\n/**\n * The user the session is signed in as (the offline settings are theirs): the loaded profile's,\n * as `useOfflineMailSettings` reads it. Until it is loaded (a restored tab) there is none, so the\n * defaults apply and nothing is cached yet.\n */\nexport function sessionUser(arbi: Arbi): string | null {\n return arbi.session?.getState().user?.external_id ?? null\n}\n\n/** The session holds a server session key: the keys a background mail request needs. */\nfunction hasLiveSession(arbi: Arbi): boolean {\n return !!arbi.session?.getState().serverSessionKey\n}\n\n/** Whether this tab has what a background mail request needs: a connection and an unlocked session. */\nfunction canReachMail(arbi: Arbi): boolean {\n return onlineManager.isOnline() && hasLiveSession(arbi)\n}\n\nconst unlocked = { nativeUnlocked: true }\n\nfunction mailCall<T>(arbi: Arbi, path: string, init: RequestInit = {}): Promise<T> {\n return mailJson<T>((p, i) => arbi.mail.fetch(p, i, unlocked), path, init)\n}\n\nfunction liveTransport(arbi: Arbi): MailTransport {\n const unlock = async (account: MailAccount) => {\n if (!hasLiveSession(arbi))\n throw Object.assign(new Error('Sign in to unlock your mailbox'), { status: 401 })\n await arbi.mail.unlockAccount(account)\n }\n return {\n policy: () => mailCall<MailPolicy>(arbi, '/policy'),\n accounts: () => mailCall<MailAccount[]>(arbi, '/accounts'),\n unlock,\n folders: (account) => mailCall<MailFolder[]>(arbi, `${accountPath(account.id)}/folders`),\n messages: (account, folderId, cursor) =>\n mailCall(\n arbi,\n `${accountPath(account.id)}/messages?${new URLSearchParams({\n folder_id: folderId,\n q: '',\n limit: '100',\n ...(cursor ? { cursor } : {}),\n })}`\n ),\n message: async (account, messageId) => {\n const path = `${accountPath(account.id)}/messages/${encodeURIComponent(messageId)}`\n try {\n return await mailCall<MailMessage>(arbi, path)\n } catch (error) {\n // Mail that arrived after this pass unlocked the inbox has a key the session doesn't hold yet.\n if ((error as { status?: number }).status !== 401 || account.provider !== 'native')\n throw error\n if (hasLiveSession(arbi)) await arbi.mail.unlockNative()\n return mailCall<MailMessage>(arbi, path)\n }\n },\n attachment: async (account, messageId, attachmentId) => {\n const response = await arbi.mail.fetch(\n `${accountPath(account.id)}/messages/${encodeURIComponent(messageId)}/attachments/${encodeURIComponent(attachmentId)}`,\n {},\n unlocked\n )\n return new Uint8Array(await response.arrayBuffer())\n },\n }\n}\n\nfunction liveSender(arbi: Arbi): OutboxSender {\n const transport = liveTransport(arbi)\n return {\n prepareSecure: async (item) => {\n if (item.account.provider !== 'native')\n throw new Error('Choose your native inbox to send securely')\n return arbi.secureMail.prepare(item.compose, item.account, item.requestId)\n },\n unlock: async (account) => {\n // The native send path needs no session keys; connected accounts need this session's tokens.\n if (account.provider !== 'native') await transport.unlock(account)\n },\n send: (item) =>\n item.secure\n ? mailJson<{ id?: string }>((p, i) => arbi.mail.fetch(p, i), '/secure/send', {\n method: 'POST',\n body: JSON.stringify(item.securePayload),\n })\n : mailJson<{ id?: string }>(\n (p, i) => arbi.mail.fetch(p, i),\n `${accountPath(item.account.id)}/send`,\n {\n method: 'POST',\n body: JSON.stringify({ ...item.compose, request_id: item.requestId }),\n }\n ),\n }\n}\n\nfunction liveChangeSender(arbi: Arbi): MailChangeSender {\n return {\n unlock: (account) => liveTransport(arbi).unlock(account),\n apply: async ({ account, messageId, change }) => {\n if (change.kind === 'file') {\n const { kind: _, ...request } = change\n await sendMailFile(\n (p, i) => arbi.mail.fetch(p, i),\n primeOnArbi(arbi),\n account,\n messageId,\n request\n )\n return\n }\n await mailJson(\n (p, i) => arbi.mail.fetch(p, i),\n `${accountPath(account.id)}/messages/${encodeURIComponent(messageId)}`,\n change.kind === 'delete'\n ? { method: 'DELETE' }\n : { method: 'PATCH', body: JSON.stringify(change.update) }\n )\n },\n }\n}\n\nconst localLocks = new Set<string>()\n\n/** Run `fn` unless another tab (or this one) already is; returns whether it ran. */\nasync function exclusive(name: string, fn: () => Promise<void>): Promise<boolean> {\n if (typeof navigator !== 'undefined' && navigator.locks?.request) {\n return navigator.locks.request(name, { ifAvailable: true }, async (lock) => {\n if (!lock) return false\n await fn()\n return true\n })\n }\n if (localLocks.has(name)) return false\n localLocks.add(name)\n try {\n await fn()\n return true\n } finally {\n localLocks.delete(name)\n }\n}\n\nlet retryTimer: ReturnType<typeof setTimeout> | null = null\n\n/** One Outbox pass: send what waits, in order, and tell the user how it went. */\nasync function sendOutbox({ arbi, queryClient, openOutbox }: OfflineMailContext): Promise<void> {\n const result = await flushOutboxOnce(liveSender(arbi), () => onlineManager.isOnline())\n if (result.sent > 0) void queryClient.invalidateQueries({ queryKey: mailQueryKeys.all() })\n const remaining = (await listOutbox()).filter((i) => i.status !== 'sent')\n if (result.failed > 0) {\n notify.error(\n result.failed === 1\n ? \"A message in your Outbox couldn't be sent\"\n : `${result.failed} messages in your Outbox couldn't be sent`,\n {\n description: 'Open the Outbox to see why, then retry, edit or delete it.',\n ...(openOutbox && { action: { label: 'Open Outbox', onClick: openOutbox } }),\n }\n )\n } else if (result.sent > 0 && remaining.length === 0) {\n notify.success(\n result.sent === 1 ? 'Your Outbox message was sent' : `${result.sent} Outbox messages sent`\n )\n }\n // Sent rows stay visible briefly as \"Sent\", then leave the Outbox.\n setTimeout(() => void purgeSentOutbox(30_000), 31_000)\n}\n\n/** One pass over the changes made offline: apply them, and say which could not be applied. */\nasync function applyChanges({ arbi, queryClient }: OfflineMailContext): Promise<void> {\n const result = await applyMailChangesOnce(liveChangeSender(arbi), () => onlineManager.isOnline())\n if (result.applied + result.gone + result.refused.length > 0)\n void queryClient.invalidateQueries({ queryKey: mailQueryKeys.all() })\n if (result.gone > 0)\n notify.info(\n result.gone === 1\n ? 'A message you changed offline was already gone from the server'\n : `${result.gone} messages you changed offline were already gone from the server`\n )\n if (result.refused.length > 0)\n notify.error(\n result.refused.length === 1\n ? \"A change you made offline couldn't be applied\"\n : `${result.refused.length} changes you made offline couldn't be applied`,\n { description: result.refused[0].error }\n )\n}\n\n/**\n * Send what waits on this device: the Outbox first, then the changes made offline (read, moved,\n * trashed, deleted), under one lock so neither overtakes the other, and nothing goes out twice\n * from two tabs. When another tab holds the lock, try again shortly: it may have missed something\n * queued here just now.\n */\nexport async function flushOutbox(context: OfflineMailContext): Promise<void> {\n if (!canReachMail(context.arbi)) return\n const ran = await exclusive('arbi-mail-outbox', async () => {\n await sendOutbox(context)\n await applyChanges(context)\n })\n if (!ran) {\n if (retryTimer) clearTimeout(retryTimer)\n retryTimer = setTimeout(() => void flushOutbox(context), 3_000)\n }\n}\n\n/** Upload the drafts written offline to the account's server Drafts. */\nexport async function uploadOfflineDrafts({\n arbi,\n queryClient,\n}: OfflineMailContext): Promise<void> {\n if (!canReachMail(arbi)) return\n await exclusive('arbi-mail-drafts', async () => {\n const uploaded = await syncLocalDrafts(({ accountId, compose }) =>\n mailJson<{ id: string }>(\n (p, i) => arbi.mail.fetch(p, i),\n `${accountPath(accountId)}/drafts`,\n {\n method: 'POST',\n body: JSON.stringify(compose satisfies MailCompose),\n }\n )\n )\n if (uploaded > 0) {\n void queryClient.invalidateQueries({ queryKey: mailQueryKeys.allMessages() })\n notify.success(\n uploaded === 1\n ? 'Your offline draft was saved to Drafts'\n : `${uploaded} offline drafts were saved to Drafts`\n )\n }\n })\n}\n\nlet syncing = false\nexport function isMailSyncRunning(): boolean {\n return syncing\n}\n\n/** One sync pass of the offline mailbox, when the user turned it on for this device. */\nexport async function syncOfflineMailbox(\n { arbi }: Pick<OfflineMailContext, 'arbi'>,\n options: { full?: boolean } = {}\n): Promise<void> {\n const latest = () => getOfflineMailSettings(sessionUser(arbi))\n const settings = latest()\n if (!settings.enabled || !canReachMail(arbi)) return\n // Keeping mail (the default too, not only when it is switched on): ask the browser not to evict it.\n void requestPersistentStorage()\n await exclusive('arbi-mail-sync', async () => {\n syncing = true\n notifyOfflineMailChange('status')\n try {\n await syncMailbox(liveTransport(arbi), latest(), { ...options, latest })\n } catch (error) {\n logger.error('[offline-mail] sync failed', error)\n } finally {\n syncing = false\n notifyOfflineMailChange('status')\n }\n })\n}\n","/**\n * Mail reads that keep working offline.\n *\n * Online, each read goes to the server as before; the result is also written to the encrypted\n * offline store — accounts and policy always (tiny, and needed to compose and queue mail offline),\n * folders and messages only while mail is kept on this device, and only messages received within\n * the chosen window (the last 7 days by default), so browsing older mail online does not grow it.\n * Offline (or when the request can't reach the server), the same read is answered from the store,\n * and when the store has nothing for it the error says so plainly instead of loading forever.\n *\n * The Mail queries use networkMode 'always' with these functions, so they run offline instead of\n * pausing (a paused query would show its loading state indefinitely).\n */\n\nimport { onlineManager } from '@tanstack/react-query'\nimport type { Arbi } from '@arbidocs/sdk/browser'\nimport { logger } from '@arbidocs/client'\nimport {\n accountPath,\n conversationsPath,\n mailJson,\n MailOfflineUnavailableError,\n threadPath,\n type MailClient,\n} from '../client'\nimport type {\n MailAccount,\n MailConversationPage,\n MailFolder,\n MailMessage,\n MailPage,\n MailPolicy,\n MailThread,\n} from '../types'\nimport { mailConversationKey, groupMailConversations } from '../threads'\nimport {\n hasFolder,\n isVirtualFolder,\n loadAccountMessages,\n loadAccounts,\n loadBody,\n loadFolders,\n loadPolicy,\n saveAccounts,\n saveBody,\n saveFolders,\n saveHeader,\n savePolicy,\n searchFolder,\n} from './mailbox'\nimport { getOfflineMailSettings, inOfflineWindow } from './settings'\nimport { overlayPendingMailChanges } from './changes'\nimport { isNetworkFailure } from '../../offline-store/network'\nimport { sessionUser } from './live'\n\nconst NOT_SAVED_HINT =\n 'Choose how much mail to keep on this device in Mail settings to read it without a connection.'\n\nasync function onlineFirst<T>(\n online: () => Promise<T>,\n offline: () => Promise<T | undefined>,\n unavailable: string\n): Promise<T> {\n if (onlineManager.isOnline()) {\n try {\n return await online()\n } catch (error) {\n if (!isNetworkFailure(error)) throw error\n }\n }\n const saved = await offline().catch(() => undefined)\n if (saved !== undefined) return saved\n throw new MailOfflineUnavailableError(unavailable)\n}\n\nexport interface OfflineMailReadsOptions {\n /**\n * Whether this device keeps mail at all (e.g. the person uses Mail): when it doesn't, reads are\n * never written to the device. Default: it does.\n */\n keepsMail?: () => boolean\n}\n\ntype MailReads = Pick<\n MailClient,\n | 'getPolicy'\n | 'listAccounts'\n | 'listFolders'\n | 'listMessages'\n | 'listConversations'\n | 'getThread'\n | 'getMessage'\n>\n\n/**\n * A folder's messages saved on the device, newest first. Flagged is every folder's flagged mail but\n * the Trash's, as the server lists it.\n */\nasync function deviceMessages(account: MailAccount, folderId: string, query: string) {\n if (!isVirtualFolder(await savedFolder(account.id, folderId)))\n return searchFolder(account.id, folderId, query)\n // As each server lists it: IMAP's Flagged is the Inbox's flagged mail (SEARCH FLAGGED there).\n const inView = (f: MailFolder) =>\n account.provider === 'imap' ? f.role === 'inbox' : f.role !== 'trash'\n const all = await loadAccountMessages(account.id, inView, query)\n return all.filter((m) => m.flagged)\n}\n\n/** The saved folder `folderId` (its role says whether it is the Trash, or a view like Flagged). */\nasync function savedFolder(accountId: string, folderId: string) {\n return ((await loadFolders(accountId)) ?? []).find((f) => f.id === folderId)\n}\n\n/**\n * The mail client's reads, kept working offline, on the session `getArbi()` returns (read per call,\n * so a renewed session is used). Pass them to `createMailClient` as overrides.\n */\nexport function offlineMailReads(\n getArbi: () => Arbi,\n { keepsMail = () => true }: OfflineMailReadsOptions = {}\n): MailReads {\n const call = <T>(path: string) => mailJson<T>((p, i) => getArbi().mail.fetch(p, i), path)\n const settings = () => getOfflineMailSettings(sessionUser(getArbi()))\n const storeEnabled = () => settings().enabled\n const keeps = (message: MailMessage) => inOfflineWindow(settings(), message.received_at)\n /** Write-through that never fails the read it piggybacks on. */\n const remember = (write: () => Promise<void>): void => {\n // Only for people who use Mail: everyone else never gets an offline mail store on their device.\n if (!keepsMail()) return\n write().catch((error) => logger.warn('[offline-mail] could not save for offline use', error))\n }\n return {\n getPolicy: () =>\n onlineFirst(\n async () => {\n const policy = await call<MailPolicy>('/policy')\n // Mail switched off on the deployment: nothing goes on the device.\n if (policy.enabled) remember(() => savePolicy(policy))\n return policy\n },\n loadPolicy,\n \"You're offline. Mail opens here once you've used it online on this device.\"\n ),\n listAccounts: () =>\n onlineFirst(\n async () => {\n const accounts = await call<MailAccount[]>('/accounts')\n remember(() => saveAccounts(accounts))\n return accounts\n },\n loadAccounts,\n \"You're offline. Your mail accounts appear here once you've opened Mail online on this device.\"\n ),\n listFolders: (account) =>\n onlineFirst(\n async () => {\n const folders = await call<MailFolder[]>(`${accountPath(account.id)}/folders`)\n if (storeEnabled()) remember(() => saveFolders(account.id, folders))\n return folders\n },\n () => loadFolders(account.id),\n `You're offline and this mailbox isn't saved on this device. ${NOT_SAVED_HINT}`\n ),\n listMessages: (account, folderId, query, cursor) =>\n onlineFirst<MailPage>(\n async () => {\n const page = await call<MailPage>(\n `${accountPath(account.id)}/messages?${new URLSearchParams({ folder_id: folderId, q: query, ...(cursor ? { cursor } : {}) })}`\n )\n // Search results are a subset; only the unfiltered folder list is a faithful copy.\n if (storeEnabled() && !query)\n remember(async () => {\n if (isVirtualFolder(await savedFolder(account.id, folderId))) return\n for (const message of page.messages)\n if (keeps(message)) await saveHeader(account.id, folderId, message)\n // A change still waiting must not be undone by the server's state just written.\n await overlayPendingMailChanges()\n })\n return page\n },\n async () => {\n if (!(await hasFolder(account.id))) return undefined\n return { messages: await deviceMessages(account, folderId, query), fromDevice: true }\n },\n `You're offline and this folder isn't saved on this device. ${NOT_SAVED_HINT}`\n ),\n listConversations: (account, folderId, query, cursor) =>\n onlineFirst<MailConversationPage>(\n async () => {\n const page = await call<MailConversationPage>(\n conversationsPath(account.id, folderId, query, cursor)\n )\n // As the message list: only an unfiltered real folder is a faithful copy of its rows.\n if (storeEnabled() && !query)\n remember(async () => {\n if (isVirtualFolder(await savedFolder(account.id, folderId))) return\n for (const conversation of page.conversations)\n for (const message of conversation.messages)\n if (keeps(message)) await saveHeader(account.id, folderId, message)\n await overlayPendingMailChanges()\n })\n return page\n },\n async () => {\n if (!(await hasFolder(account.id))) return undefined\n const messages = await deviceMessages(account, folderId, query)\n return { conversations: groupMailConversations(messages), fromDevice: true }\n },\n `You're offline and this folder isn't saved on this device. ${NOT_SAVED_HINT}`\n ),\n getThread: (account, threadId, folderId) =>\n onlineFirst<MailThread>(\n () => call<MailThread>(threadPath(account.id, threadId, folderId)),\n async () => {\n if (!(await hasFolder(account.id))) return undefined\n // Across folders but the Trash, unless it is the Trash being read: as the server does.\n const trash = (await savedFolder(account.id, folderId))?.role === 'trash'\n const messages = (\n await loadAccountMessages(account.id, (f) => (f.role === 'trash') === trash)\n ).filter((m) => mailConversationKey(m) === threadId)\n if (!messages.length) return undefined\n return { thread_id: threadId, messages: messages.reverse(), fromDevice: true }\n },\n \"You're offline and this conversation isn't saved on this device.\"\n ),\n getMessage: (account, messageId) =>\n onlineFirst(\n async () => {\n const message = await call<MailMessage>(\n `${accountPath(account.id)}/messages/${encodeURIComponent(messageId)}`\n )\n if (keeps(message)) remember(() => saveBody(account.id, message))\n return message\n },\n () => loadBody(account.id, messageId),\n storeEnabled()\n ? \"You're offline and this message hasn't been saved on this device yet.\"\n : `You're offline. ${NOT_SAVED_HINT}`\n ),\n }\n}\n","import { useMemo } from 'react'\nimport { useArbiHost } from '../host/config'\nimport { arbiMailClient, createMailClient, type MailClient } from './client'\nimport { offlineMailReads } from './offline/reads'\n\nexport interface MailClientContextValue {\n client: MailClient\n /** Mail reads run only while this is true (signed in). */\n enabled: boolean\n /**\n * Identifies the server session the mailbox is unlocked for: unlocking runs again when it\n * changes. `null`: no session yet, so nothing is unlocked.\n */\n sessionKey: string | null\n}\n\nconst NO_MAIL: MailClientContextValue = {\n client: createMailClient(() =>\n Promise.reject(new Error('Mail needs an <ArbiHost> with `mail` or an `arbi`'))\n ),\n enabled: false,\n sessionKey: null,\n}\n\nconst ALWAYS = () => ({ enabled: true, sessionKey: 'session' })\n\n/**\n * The mail client in scope: the host configuration's `mail`, else one on its `arbi` session\n * (`arbiMailClient`) whose reads keep working offline from the mail kept on this device\n * (`offlineMailReads`).\n */\nexport function useMailClient(): MailClientContextValue {\n const { mail, arbi } = useArbiHost()\n const fallback = useMemo(\n () =>\n arbi\n ? arbiMailClient(\n arbi,\n offlineMailReads(() => arbi)\n )\n : null,\n [arbi]\n )\n // The host's status hook is fixed for its configuration's life.\n const useStatus = mail ? (mail.useStatus ?? ALWAYS) : ALWAYS\n const { enabled, sessionKey } = useStatus()\n const client = mail?.client\n const provided = useMemo(\n () => (client ? { client, enabled, sessionKey } : null),\n [client, enabled, sessionKey]\n )\n if (provided) return provided\n // Neither: mail stays off (reads disabled, writes refused) rather than breaking the screen.\n if (!arbi || !fallback) return NO_MAIL\n let identity: string | null = null\n try {\n identity = arbi.isLoggedIn ? (arbi.user.identity()?.externalId ?? 'session') : null\n } catch {\n identity = null\n }\n return { client: fallback, enabled: identity !== null, sessionKey: identity }\n}\n","/**\n * Mail hooks: the policy, accounts, folders and messages of the mail client in scope\n * (`useMailClient`), unlocking an account for this session, and the account writes.\n *\n * Reads use `networkMode: 'always'`, so a host whose client answers from the device keeps working\n * offline instead of pausing on a loading state. Every key starts with `['arbi', 'mail']`\n * ({@link mailQueryKeys}), so invalidating that refreshes everything mail.\n */\n\nimport { useCallback, useEffect, useMemo, useRef, useSyncExternalStore } from 'react'\nimport { onlineManager, useMutation, useQuery, useQueryClient } from '@tanstack/react-query'\nimport { accountPath, mailJson } from './client'\nimport { useMailClient } from './useMailClient'\nimport { useArbi } from '../useArbi'\nimport type { MailProject } from './client'\nimport type {\n MailAccount,\n MailAttachment,\n MailCompose,\n MailConversationPage,\n MailDeliveryStatus,\n MailMessage,\n MailThread,\n} from './types'\n\nexport { mailQueryKeys } from '../query-keys'\nimport { mailQueryKeys } from '../query-keys'\n\n/** Whether the app is online (React Query's `onlineManager`). */\nexport function useMailOnline(): boolean {\n return useSyncExternalStore(\n (onChange) => onlineManager.subscribe(onChange),\n () => onlineManager.isOnline(),\n () => true\n )\n}\n\n/** What the deployment allows: native mail, OAuth providers, mail servers, the attachment limit. */\nexport function useMailPolicy(options: { enabled?: boolean } = {}) {\n const { client, enabled } = useMailClient()\n return useQuery({\n queryKey: mailQueryKeys.policy(),\n queryFn: () => client.getPolicy(),\n networkMode: 'always',\n enabled: enabled && (options.enabled ?? true),\n staleTime: 60_000,\n retry: false,\n })\n}\n\nexport function useMailAccounts(options: { enabled?: boolean } = {}) {\n const { client, enabled } = useMailClient()\n return useQuery({\n queryKey: mailQueryKeys.accounts(),\n queryFn: () => client.listAccounts(),\n networkMode: 'always',\n enabled: enabled && (options.enabled ?? true),\n retry: false,\n })\n}\n\n/**\n * Unlock `account` for this session. It waits for a connection (offline, a host that keeps mail on\n * the device reads from there and queues sends), then runs once per session.\n */\nexport function useMailUnlock(account: MailAccount | undefined) {\n const { client, enabled, sessionKey } = useMailClient()\n const isOnline = useMailOnline()\n return useQuery({\n queryKey: mailQueryKeys.unlock(account?.id, sessionKey),\n queryFn: async () => {\n if (!account) throw new Error('Sign in to unlock your mailbox')\n await client.unlock(account)\n return true\n },\n enabled: enabled && !!account && sessionKey !== null && !account.needs_reconsent && isOnline,\n staleTime: Infinity,\n retry: false,\n })\n}\n\nexport function useMailFolders(account: MailAccount | undefined, options: { enabled?: boolean }) {\n const { client } = useMailClient()\n return useQuery({\n queryKey: mailQueryKeys.folders(account?.id),\n queryFn: () => client.listFolders(account!),\n networkMode: 'always',\n enabled: !!account && (options.enabled ?? true),\n retry: false,\n })\n}\n\n/** One page of a folder, filtered by `query`, from `cursor` (`null`: the first page). */\nexport function useMailMessages(\n account: MailAccount | undefined,\n folderId: string | undefined,\n query: string,\n cursor: string | null,\n options: { enabled?: boolean; refetchInterval?: number } = {}\n) {\n const { client } = useMailClient()\n return useQuery({\n queryKey: mailQueryKeys.messages(account?.id, folderId, query, cursor),\n queryFn: () => client.listMessages(account!, folderId!, query, cursor),\n networkMode: 'always',\n enabled: !!account && !!folderId && (options.enabled ?? true),\n retry: false,\n refetchInterval: options.refetchInterval,\n })\n}\n\n/**\n * One page of a folder's conversations, filtered by `query`, from `cursor` (`null`: the first page).\n * Offline, a host whose client keeps mail on the device groups its copy the same way.\n */\nexport function useMailConversations(\n account: MailAccount | undefined,\n folderId: string | undefined,\n query: string,\n cursor: string | null,\n options: { enabled?: boolean; refetchInterval?: number } = {}\n) {\n const { client } = useMailClient()\n return useQuery({\n queryKey: mailQueryKeys.conversations(account?.id, folderId, query, cursor),\n queryFn: () => client.listConversations(account!, folderId!, query, cursor),\n networkMode: 'always',\n enabled: !!account && !!folderId && (options.enabled ?? true),\n retry: false,\n refetchInterval: options.refetchInterval,\n })\n}\n\n/** One conversation's messages, oldest first, opened from `folderId`. */\nexport function useMailThread(\n account: MailAccount | undefined,\n threadId: string | null | undefined,\n folderId: string | undefined,\n options: { enabled?: boolean } = {}\n) {\n const { client } = useMailClient()\n return useQuery({\n queryKey: mailQueryKeys.thread(account?.id, threadId, folderId),\n queryFn: () => client.getThread(account!, threadId!, folderId ?? ''),\n networkMode: 'always',\n enabled: !!account && !!threadId && (options.enabled ?? true),\n retry: false,\n })\n}\n\nexport function useMailMessage(\n account: MailAccount | undefined,\n messageId: string | null | undefined,\n options: { enabled?: boolean } = {}\n) {\n const { client } = useMailClient()\n return useQuery({\n queryKey: mailQueryKeys.message(account?.id, messageId),\n queryFn: () => client.getMessage(account!, messageId!),\n networkMode: 'always',\n enabled: !!account && !!messageId && (options.enabled ?? true),\n retry: false,\n })\n}\n\n/**\n * Read a message in full when an action needs it (replying, forwarding, printing): the cached read\n * when it was opened, else one read now.\n */\nexport function useReadMailMessage() {\n const { client } = useMailClient()\n const queryClient = useQueryClient()\n return useCallback(\n (account: MailAccount, messageId: string) =>\n queryClient.ensureQueryData({\n queryKey: mailQueryKeys.message(account.id, messageId),\n queryFn: () => client.getMessage(account, messageId),\n networkMode: 'always',\n }),\n [client, queryClient]\n )\n}\n\nfunction decodeBase64Text(b64: string): string {\n const bytes = Uint8Array.from(atob(b64), (c) => c.charCodeAt(0))\n return new TextDecoder().decode(bytes)\n}\n\n/**\n * A text attachment's content (an invitation's `.ics`, say): inline when the message carries it,\n * else downloaded once. Off while `attachment` is missing or `enabled` is false.\n */\nexport function useMailAttachmentText(\n accountId: string,\n messageId: string,\n attachment: MailAttachment | undefined,\n options: { enabled?: boolean } = {}\n) {\n const { client } = useMailClient()\n return useQuery({\n queryKey: mailQueryKeys.attachmentText(accountId, messageId, attachment?.id ?? ''),\n queryFn: async () => {\n const a = attachment as MailAttachment\n if (a.content_base64) return decodeBase64Text(a.content_base64)\n const path = `${accountPath(accountId)}/messages/${encodeURIComponent(messageId)}/attachments/${encodeURIComponent(a.id)}`\n return (await client.fetch(path)).text()\n },\n enabled: !!attachment && (options.enabled ?? true),\n staleTime: Infinity,\n retry: false,\n })\n}\n\n/** Claim `alias@<deployment domain>` as the user's native inbox, then refresh everything mail. */\nexport function useClaimNativeAlias(onClaimed?: (alias: string) => void) {\n const { client } = useMailClient()\n const queryClient = useQueryClient()\n return useMutation({\n mutationFn: (alias: string) =>\n mailJson(client.fetch, '/native/alias', { method: 'POST', body: JSON.stringify({ alias }) }),\n onSuccess: async (_data, alias) => {\n await queryClient.invalidateQueries({ queryKey: mailQueryKeys.all() })\n onClaimed?.(alias)\n },\n })\n}\n\n/**\n * Claim a secure message from its link (`id` and the link's key) into the user's native inbox\n * (`arbi.secureMail.claim` over the mail client in scope), then refresh everything mail. `claim`\n * resolves to the message's id there.\n *\n * The link's key is never a mutation variable: variables stay in the query client's mutation\n * cache, which a host may inspect or persist. Only the id is; the key is handed to the request\n * beside it and dropped once it is sent. Offline, the claim fails at once rather than waiting\n * for the network (`networkMode: 'always'`).\n */\nexport function useClaimSecureMail(): {\n claim: (id: string, fragmentKey: string) => Promise<{ id: string }>\n isPending: boolean\n} {\n const arbi = useArbi()\n const { client } = useMailClient()\n const queryClient = useQueryClient()\n const keys = useRef(new Map<string, string>())\n const mutation = useMutation({\n mutationFn: (id: string) => {\n const fragmentKey = keys.current.get(id)\n keys.current.delete(id)\n if (!fragmentKey) return Promise.reject(new Error('Open the original link from your email'))\n return arbi.secureMail.claim(id, fragmentKey, client.fetch)\n },\n networkMode: 'always',\n gcTime: 0,\n onSuccess: () => queryClient.invalidateQueries({ queryKey: mailQueryKeys.all() }),\n })\n const { mutateAsync } = mutation\n const claim = useCallback(\n (id: string, fragmentKey: string) => {\n keys.current.set(id, fragmentKey)\n return mutateAsync(id)\n },\n [mutateAsync]\n )\n return { claim, isPending: mutation.isPending }\n}\n\n/** Connect a mailbox on one of the deployment's approved mail servers. */\nexport function useConnectMailAccount() {\n const { client } = useMailClient()\n const queryClient = useQueryClient()\n return useMutation({\n mutationFn: (input: { profileId: string; email: string; username: string; password: string }) =>\n mailJson(client.fetch, '/accounts', {\n method: 'POST',\n body: JSON.stringify({\n profile_id: input.profileId,\n email: input.email,\n username: input.username || input.email,\n password: input.password,\n }),\n }),\n onSuccess: () => queryClient.invalidateQueries({ queryKey: mailQueryKeys.accounts() }),\n })\n}\n\nexport function useDisconnectMailAccount() {\n const { client } = useMailClient()\n const queryClient = useQueryClient()\n return useMutation({\n mutationFn: (accountId: string) =>\n mailJson(client.fetch, accountPath(accountId), { method: 'DELETE' }),\n onSuccess: () => queryClient.invalidateQueries({ queryKey: mailQueryKeys.all() }),\n })\n}\n\n/** Refresh mail reads after a write the hooks below don't cover. */\nexport function useMailCache() {\n const queryClient = useQueryClient()\n return useMemo(() => {\n const refreshAll = () => queryClient.invalidateQueries({ queryKey: mailQueryKeys.all() })\n return {\n refreshAll,\n refreshFolders: () => queryClient.invalidateQueries({ queryKey: mailQueryKeys.allFolders() }),\n /**\n * Show a flag change at once in every conversation list and thread read (the server's state\n * follows on the next refresh).\n */\n showFlag: (accountId: string, messageIds: string[], flagged: boolean, threadId?: string) => {\n const ids = new Set(messageIds)\n const patch = (message: MailMessage) =>\n ids.has(message.id) ? { ...message, flagged } : message\n queryClient.setQueriesData<MailConversationPage>(\n { queryKey: mailQueryKeys.allConversations() },\n (page) =>\n page && {\n ...page,\n conversations: page.conversations.map((c) => {\n const whole = threadId !== undefined && c.thread_id === threadId\n if (!whole && !c.messages.some((m) => ids.has(m.id))) return c\n const messages = c.messages.map(patch)\n // A row may carry only the newest message: a change to the whole thread sets its flag.\n return {\n ...c,\n messages,\n flagged: whole ? flagged : messages.some((m) => m.flagged),\n }\n }),\n }\n )\n queryClient.setQueriesData<MailThread>(\n { queryKey: mailQueryKeys.accountThreads(accountId) },\n (thread) => thread && { ...thread, messages: thread.messages.map(patch) }\n )\n },\n }\n }, [queryClient])\n}\n\n/** Where a message goes when the server can't be reached: kept on the device (a host option). */\nexport interface MailDeviceFallback {\n /** Keep it on the device; called offline, or when the request got no answer. */\n keep: (compose: MailCompose) => Promise<void>\n /** The request got no answer (no connection), as opposed to the server refusing it. */\n isNetworkFailure: (error: unknown) => boolean\n}\n\nasync function withFallback<T>(\n compose: MailCompose,\n fallback: MailDeviceFallback | undefined,\n online: () => Promise<T>\n): Promise<T | { onDevice: true }> {\n if (fallback && !onlineManager.isOnline()) {\n await fallback.keep(compose)\n return { onDevice: true }\n }\n try {\n return await online()\n } catch (error) {\n if (!fallback?.isNetworkFailure(error)) throw error\n await fallback.keep(compose)\n return { onDevice: true }\n }\n}\n\n/**\n * Save a draft to the account's Drafts. With `fallback`, offline (or with no answer) it is kept on\n * the device instead (`{ onDevice: true }`).\n */\nexport function useSaveMailDraft(fallback?: MailDeviceFallback) {\n const { client } = useMailClient()\n const queryClient = useQueryClient()\n return useMutation({\n // networkMode 'always': offline the save runs (to the device) instead of pausing on \"Saving…\".\n networkMode: 'always',\n mutationFn: ({ accountId, compose }: { accountId: string; compose: MailCompose }) =>\n withFallback(compose, fallback, () =>\n mailJson<{ id: string }>(client.fetch, `${accountPath(accountId)}/drafts`, {\n method: 'POST',\n body: JSON.stringify(compose),\n })\n ),\n onSuccess: (result) => {\n if (!('onDevice' in result))\n void queryClient.invalidateQueries({ queryKey: mailQueryKeys.allMessages() })\n },\n })\n}\n\n/**\n * Send a message. `requestId` makes it idempotent: sending the same request again never sends twice.\n * `secure` sends it by secure delivery instead (resolves with the prepared payload). With\n * `fallback`, offline (or with no answer) it waits on the device (`{ onDevice: true }`).\n */\nexport function useSendMail(fallback?: MailDeviceFallback) {\n const { client } = useMailClient()\n const queryClient = useQueryClient()\n return useMutation({\n networkMode: 'always',\n retry: false,\n mutationFn: ({\n accountId,\n compose,\n requestId,\n secure,\n }: {\n accountId: string\n compose: MailCompose\n requestId: string\n secure?: () => Promise<unknown>\n }) =>\n withFallback(compose, fallback, async () =>\n secure\n ? mailJson<unknown>(client.fetch, '/secure/send', {\n method: 'POST',\n body: JSON.stringify(await secure()),\n })\n : mailJson<unknown>(client.fetch, `${accountPath(accountId)}/send`, {\n method: 'POST',\n body: JSON.stringify({ ...compose, request_id: requestId }),\n })\n ),\n onSuccess: (result) => {\n if (!(result && typeof result === 'object' && 'onDevice' in result))\n void queryClient.invalidateQueries({ queryKey: mailQueryKeys.all() })\n },\n })\n}\n\n/**\n * A native draft's Word room (opened with `MailClient.openDraftEditor`): save it as the draft, send\n * it, or read its body. The server makes the draft's text and HTML from the room; `state` is the\n * editor's latest state, so the last keystrokes are included.\n */\nexport function useMailDraftEditor() {\n const { client } = useMailClient()\n const queryClient = useQueryClient()\n return useMemo(() => {\n const call = <T>(roomId: string, path: string, payload: object) =>\n mailJson<T>(client.fetch, `/drafts/editor/${encodeURIComponent(roomId)}${path}`, {\n method: 'POST',\n body: JSON.stringify(payload),\n })\n return {\n /** Save as the draft: suggestions still waiting stay out of it. */\n save: async (roomId: string, compose: MailCompose, state?: string | null) => {\n const saved = await call<{ id: string }>(roomId, '/save', { compose, state })\n void queryClient.invalidateQueries({ queryKey: mailQueryKeys.allMessages() })\n return saved\n },\n /** Send (refused, `status` 409, while suggestions wait). */\n send: async (\n roomId: string,\n compose: MailCompose & { request_id: string },\n state?: string | null\n ) => {\n const sent = await call<{\n id: string\n status: string\n delivery_status?: MailDeliveryStatus | null\n }>(roomId, '/send', { compose, state })\n void queryClient.invalidateQueries({ queryKey: mailQueryKeys.all() })\n return sent\n },\n /** The body as text and HTML (`final`: refused while suggestions wait). */\n body: (roomId: string, final: boolean, state?: string | null) =>\n call<{ text: string; html: string }>(roomId, '/body', { final, state }),\n /** Bill ARBI's work on this email to another project the person may bill (null: their own). */\n setProject: (roomId: string, projectExtId: string | null) =>\n mailJson<MailProject>(\n client.fetch,\n `/drafts/editor/${encodeURIComponent(roomId)}/project`,\n { method: 'PUT', body: JSON.stringify({ project_ext_id: projectExtId }) }\n ),\n }\n }, [client, queryClient])\n}\n\n/** The projects an email's AI work can be billed to: the person's own first, then their matters. */\nexport function useMailProjects(options: { enabled?: boolean } = {}) {\n const { client } = useMailClient()\n return useQuery({\n queryKey: mailQueryKeys.projects(),\n queryFn: () => mailJson<MailProject[]>(client.fetch, '/drafts/editor/projects'),\n enabled: options.enabled ?? true,\n staleTime: 60_000,\n })\n}\n\n/** A saved draft prepared for editing by `prepare` (e.g. with its attachments' content). */\nexport function useMailDraftCompose(\n account: MailAccount | undefined,\n draftId: string | undefined,\n prepare: (account: MailAccount, draftId: string) => Promise<MailCompose>,\n options: { enabled?: boolean } = {}\n) {\n return useQuery({\n queryKey: mailQueryKeys.draftCompose(account?.id, draftId),\n queryFn: () => prepare(account!, draftId!),\n networkMode: 'always',\n enabled: !!account && !!draftId && (options.enabled ?? true),\n retry: false,\n staleTime: Infinity,\n })\n}\n\n/** Fired on `window` when a saved draft now lives under a new id (saving a native draft replaces it). */\nexport const MAIL_DRAFT_REPLACED_EVENT = 'arbi:mail-draft-replaced'\n\ninterface MailDraftReplaced {\n oldId: string\n newId: string\n}\n\n/** Announce that draft `oldId` is now `newId`: the host calls it on the server's `mail.draft_replaced`. */\nexport function announceMailDraftReplaced(oldId: string, newId: string): void {\n window.dispatchEvent(\n new CustomEvent<MailDraftReplaced>(MAIL_DRAFT_REPLACED_EVENT, { detail: { oldId, newId } })\n )\n}\n\n/** Call `onReplaced(newId)` when draft `draftId` is saved again elsewhere (by ARBI, or in another tab). */\nexport function useMailDraftReplaced(\n draftId: string | null | undefined,\n onReplaced: (newId: string) => void\n): void {\n const latest = useRef(onReplaced)\n useEffect(() => {\n latest.current = onReplaced\n })\n useEffect(() => {\n if (!draftId) return\n const listener = (event: Event) => {\n const { oldId, newId } = (event as CustomEvent<MailDraftReplaced>).detail\n if (oldId === draftId) latest.current(newId)\n }\n window.addEventListener(MAIL_DRAFT_REPLACED_EVENT, listener)\n return () => window.removeEventListener(MAIL_DRAFT_REPLACED_EVENT, listener)\n }, [draftId])\n}\n","/**\n * The live updates every site applies from the server's WebSocket, cache side only: a message\n * somebody else posted, a generated title, a thread's document binding, a mail draft saved under a\n * new id, and a changed skill. `ArbiWebSocketProvider` applies them itself; a host with its own\n * socket routes these messages here, so there is one implementation.\n */\n\nimport type { QueryClient } from '@tanstack/react-query'\nimport { applyConversationEvent } from '../chat/conversation-events'\nimport { announceMailDraftReplaced } from '../mail/hooks'\nimport { arbiQueryKeys, mailQueryKeys } from '../query-keys'\n\n/** The message types `applyLiveUpdate` handles. */\nexport const LIVE_UPDATE_TYPES = [\n 'conversation.message_posted',\n 'conversation.title_updated',\n 'conversation.document_binding_changed',\n 'mail.draft_replaced',\n 'skills_updated',\n] as const\n\n/**\n * Apply one server message to the cache. Resolves `true` when it was one of `LIVE_UPDATE_TYPES`,\n * `false` (nothing done) for any other.\n */\nexport async function applyLiveUpdate(\n queryClient: QueryClient,\n message: { type: string; [field: string]: unknown }\n): Promise<boolean> {\n switch (message.type) {\n case 'conversation.message_posted':\n case 'conversation.title_updated':\n case 'conversation.document_binding_changed':\n await applyConversationEvent(queryClient, message)\n return true\n case 'mail.draft_replaced': {\n // A native draft saved again under a new id (by ARBI in a private chat, or in another tab):\n // the Mail lists refresh and an open composer showing the old id follows it.\n const oldId = message.old_id as string | undefined\n const newId = message.new_id as string | undefined\n if (!oldId || !newId) return true\n void queryClient.invalidateQueries({ queryKey: mailQueryKeys.allMessages() })\n void queryClient.invalidateQueries({ queryKey: mailQueryKeys.allFolders() })\n announceMailDraftReplaced(oldId, newId)\n return true\n }\n case 'skills_updated':\n // A skill changed server-side (saved by an agent, deleted, published): the cached\n // marketplace list is never re-read on its own.\n void queryClient.invalidateQueries({ queryKey: arbiQueryKeys.skills() })\n return true\n default:\n return false\n }\n}\n","/**\n * A run that finished on the server (`response_complete` on the WebSocket), applied by every site:\n * the session side and the cache side of `applyConversationEvent`. `ArbiWebSocketProvider` applies\n * it itself.\n *\n * The run is matched to the conversation whose answer is streaming under its id, else the\n * conversation the event names (a run the server started: a queued follow-up, a background task).\n * That conversation stops generating, the follow-up it answered leaves the queue box, the documents\n * a background run saved are read again (it has no foreground stream to bring them), and the thread,\n * its follow-up, the list and the usage follow. A run that failed because the project's AI usage is\n * used up is reported to `onQuotaExceeded` (the chat host's, as a failed stream is).\n */\nimport type { QueryClient } from '@tanstack/react-query'\nimport type { Arbi, QuotaExceeded } from '@arbidocs/sdk/browser'\nimport { logger, type WsResponseCompleteMessage } from '@arbidocs/client'\nimport type { ArbiSessionStore } from '../session/store'\nimport { refreshDocuments } from '../documents/documents-data'\nimport { applyConversationEvent } from './conversation-events'\nimport { cachedQuotaUsedUp } from './turn-control'\n\nexport function applyRunFinished(\n queryClient: QueryClient,\n arbi: Arbi,\n session: Pick<\n ArbiSessionStore,\n 'getState' | 'setConversationGenerating' | 'removeQueuedMessageByServerId'\n >,\n message: WsResponseCompleteMessage,\n onQuotaExceeded?: (quota: QuotaExceeded) => void\n): void {\n const { generating } = session.getState()\n const streaming = Object.entries(generating).find(\n ([, generation]) => generation.streamingAssistantId === message.response_id\n )?.[0]\n const conversationId = streaming ?? message.conversation_ext_id ?? null\n if (!conversationId) return\n\n session.setConversationGenerating(conversationId, false, null)\n if (message.doc_ext_ids?.length) {\n refreshDocuments(queryClient, arbi, message.doc_ext_ids).catch((error) =>\n logger.error('[WebSocket] Failed to refresh task outputs:', error)\n )\n }\n if (message.user_message_id) session.removeQueuedMessageByServerId(message.user_message_id)\n void applyConversationEvent(queryClient, { ...message, conversation_ext_id: conversationId })\n if (message.status === 'failed') {\n const quota = cachedQuotaUsedUp(queryClient, session.getState().workspaceId)\n if (quota) onQuotaExceeded?.(quota)\n }\n}\n","/**\n * A persisted notification arriving live (the server pushes each row as it is created, and again\n * when it is read on another device), applied to the cache: every loaded list takes it at once\n * (a new row in front, a read receipt flips `read`), then is read again from the server; new mail\n * or an agent's draft also refreshes the Mail views. `ArbiWebSocketProvider` applies it to every\n * row; the arrival toast is the blocks' (`useNotificationToasts`).\n */\n\nimport type { QueryClient } from '@tanstack/react-query'\nimport type { components } from '@arbidocs/client'\nimport { arbiQueryKeys, mailQueryKeys } from '../query-keys'\n\ntype NotificationResponse = components['schemas']['NotificationResponse']\n\n/** A persisted notification row has an id and the person it is addressed to. */\nexport function isNotificationRow(message: unknown): message is NotificationResponse {\n const m = message as { external_id?: unknown; recipient?: unknown } | null\n return (\n typeof m?.external_id === 'string' && typeof m.recipient === 'object' && m.recipient !== null\n )\n}\n\n/** Notification types that mean the Mail views changed for their recipient. */\nconst MAIL_TYPES = new Set(['native_mail_received', 'mail_draft_ready'])\n\n/** Apply one live notification row to the cache (`me`: the signed-in user's id). */\nexport function applyNotificationRow(\n queryClient: QueryClient,\n row: NotificationResponse,\n me: string | null | undefined\n): void {\n if (MAIL_TYPES.has(row.type) && row.recipient.external_id === me)\n void queryClient.invalidateQueries({ queryKey: mailQueryKeys.all() })\n queryClient.setQueriesData<NotificationResponse[]>(\n { queryKey: arbiQueryKeys.allNotifications() },\n (old) => {\n if (!Array.isArray(old)) return old\n const index = old.findIndex((n) => n.external_id === row.external_id)\n if (index < 0) return [row, ...old]\n if (!row.read || old[index].read) return old\n const next = [...old]\n next[index] = { ...old[index], read: true }\n return next\n }\n )\n void queryClient.invalidateQueries({ queryKey: arbiQueryKeys.allNotifications() })\n}\n","/**\n * Context for the shared WebSocket — the subscribe registry the provider fills\n * and the hooks read. Kept separate from the provider component so both can be\n * imported without tripping react-refresh's component-only-export rule.\n */\n\nimport { createContext, useContext } from 'react'\nimport type { WebSocketServerMessage } from '@arbidocs/client'\n\nexport type ArbiWsSubscriber = (msg: WebSocketServerMessage) => void\n\nexport interface ArbiWsContextValue {\n subscribe: (fn: ArbiWsSubscriber) => () => void\n}\n\nexport const ArbiWsContext = createContext<ArbiWsContextValue | null>(null)\n\nexport function useArbiWsContext(): ArbiWsContextValue {\n const ctx = useContext(ArbiWsContext)\n if (!ctx) {\n throw new Error('useArbiWebSocket hooks must be used within an <ArbiWebSocketProvider>')\n }\n return ctx\n}\n","/**\n * ArbiWebSocketProvider — one shared, reconnecting WebSocket for the whole app.\n *\n * Opens a single authenticated socket (via the SDK transport's\n * `connectWithReconnect`, which handles auth, backoff, and live-token refresh),\n * feeds the canonical WS store, applies what every site applies (tasks, presence,\n * chats, calls, notification rows, finished runs, conversation, mail-draft and skill\n * events), then hands each message to the host's own `handlers` for its type and\n * fans it out to subscribers registered by the `useArbiWebSocket` /\n * `useArbiWsMessage` hooks.\n *\n * Mount it inside an `<ArbiHost>` with an `arbi` (it reads the Arbi instance for the base\n * URL + live access token). Gate it with `enabled` so it connects only once the\n * app is authenticated against a live backend.\n */\n\nimport { useEffect, useMemo, useRef, type ReactNode } from 'react'\nimport { useQueryClient } from '@tanstack/react-query'\nimport { connectWithReconnect, type ReconnectableWsConnection } from '@arbidocs/sdk/browser'\nimport {\n isMessageType,\n type WebSocketServerMessage,\n type WsTaskUpdateMessage,\n type WsBatchCompleteMessage,\n type WsPresenceUpdateMessage,\n type WsAuthResultMessage,\n type WsResponseCompleteMessage,\n logger,\n} from '@arbidocs/client'\nimport { useArbi } from '../useArbi'\nimport { finishEntityExtraction } from '../entity-extraction'\nimport { useArbiWsStore } from './store'\nimport { nextReconnectDelay, resolveSocketBaseUrl } from './reconnect'\nimport { applyLiveUpdate } from './live-updates'\nimport { applyRunFinished } from '../chat/run-finished'\nimport { useArbiSessionStore } from '../session/session-hooks'\nimport { applyChatEvent } from '../directmessages/chat-cache'\nimport { applyCallEvent } from '../calls/events'\nimport { applyNotificationRow, isNotificationRow } from '../notifications/live'\nimport { applyTaskEvent } from '../documents/processing-live'\nimport { refreshDocuments } from '../documents/documents-data'\nimport { arbiQueryKeys } from '../query-keys'\nimport { useFeature } from '../host/features'\nimport { useOnlineSync } from '../connectivity'\nimport { useArbiHost } from '../host/config'\nimport { ArbiWsContext, type ArbiWsContextValue, type ArbiWsSubscriber } from './context'\n\n/** A host's own handling of server messages, by message type (e.g. `remote_control`). */\nexport type ArbiWsHandlers = Partial<Record<string, (message: WebSocketServerMessage) => void>>\n\nexport interface ArbiWebSocketProviderProps {\n /**\n * Open the socket only when the app is authenticated against a live backend.\n * Defaults to `true`; pass the connection status so demo/logged-out sessions\n * don't try to connect.\n */\n enabled?: boolean\n /** Called each time the server accepts the socket's auth (e.g. to show the unread count). */\n onAuthenticated?: (message: WsAuthResultMessage) => void\n /**\n * The host's own handling of message types the provider does not apply (e.g. `remote_control`),\n * each called after the provider's own and before the subscribers. Read on each message, so a\n * new object never reopens the socket.\n */\n handlers?: ArbiWsHandlers\n children: ReactNode\n}\n\n/** The signed-in person's id on `arbi`, or null when nobody is signed in. */\nfunction signedInId(arbi: ReturnType<typeof useArbi>): string | null {\n return arbi.isLoggedIn ? (arbi.user.identity()?.externalId ?? null) : null\n}\n\n/** The close code of a server-side single-session eviction (a newer session of the same user). */\nconst EVICTED_CLOSE_CODE = 1008\n\nexport function ArbiWebSocketProvider({\n enabled = true,\n onAuthenticated,\n handlers,\n children,\n}: ArbiWebSocketProviderProps) {\n // The latest `Arbi`, read on each use: a host renews its instance (another server session, an\n // opened workspace) without that reopening the socket; the token is read afresh on each connect.\n const arbi = useArbi()\n const arbiRef = useRef(arbi)\n arbiRef.current = arbi\n const queryClient = useQueryClient()\n const subscribersRef = useRef<Set<ArbiWsSubscriber>>(new Set())\n const setStatus = useArbiWsStore((s) => s.setStatus)\n const applyTaskUpdate = useArbiWsStore((s) => s.applyTaskUpdate)\n const applyPresence = useArbiWsStore((s) => s.applyPresence)\n const reset = useArbiWsStore((s) => s.reset)\n const setEvicted = useArbiWsStore((s) => s.setEvicted)\n const onAuthenticatedRef = useRef(onAuthenticated)\n onAuthenticatedRef.current = onAuthenticated\n const handlersRef = useRef(handlers)\n handlersRef.current = handlers\n const session = useArbiSessionStore()\n const sessionRef = useRef(session)\n sessionRef.current = session\n const host = useArbiHost()\n const hostRef = useRef(host)\n hostRef.current = host\n // Calls ring only a person whose `calls` feature is on (ARBI: Settings → Experimental); unlisted, on.\n const acceptRings = useFeature('calls')\n const acceptRingsRef = useRef(acceptRings)\n acceptRingsRef.current = acceptRings\n // Online or not follows this connection too (and the network, and \"Work offline\").\n useOnlineSync()\n\n // Stable subscribe API — the subscriber set lives in a ref, so registering a\n // handler never re-opens the socket.\n const context = useMemo<ArbiWsContextValue>(\n () => ({\n subscribe: (fn) => {\n subscribersRef.current.add(fn)\n return () => {\n subscribersRef.current.delete(fn)\n }\n },\n }),\n []\n )\n\n useEffect(() => {\n if (!enabled) {\n reset()\n return\n }\n\n let conn: ReconnectableWsConnection | null = null\n let cancelled = false\n // Taken over by another connection of this session (the server says so, then closes):\n // reconnecting would take it back, and the two would evict each other in turn.\n let evicted = false\n\n const me = () => signedInId(arbiRef.current)\n\n // What every site applies, before the host's own subscribers hear the message.\n const onMessage = (msg: WebSocketServerMessage) => {\n const type = msg.type as string\n if (type === 'connection_closed') {\n evicted = true\n setEvicted(true)\n } else if (isMessageType<WsTaskUpdateMessage>(msg, 'task_update')) {\n // The live processing row, then the documents list (an upload's row, a finished re-read).\n if (applyTaskUpdate(msg)) applyTaskEvent(queryClient, arbiRef.current, msg, me())\n } else if (isMessageType<WsPresenceUpdateMessage>(msg, 'presence_update')) applyPresence(msg)\n else if (isMessageType<WsResponseCompleteMessage>(msg, 'response_complete'))\n // A run finished: its conversation stops generating, its follow-up leaves the queue, the\n // documents it saved are read again, the thread follows, and a run failed for the AI usage\n // says so the chat host's way.\n applyRunFinished(queryClient, arbiRef.current, sessionRef.current, msg, (quota) =>\n hostRef.current.chat?.onQuotaExceeded?.(quota)\n )\n else if (type === 'error')\n logger.error('[WebSocket] Server error:', (msg as { message?: unknown }).message)\n else if (isMessageType<WsBatchCompleteMessage>(msg, 'batch_complete')) {\n // An upload or an extraction finished: its documents are read again, and the tags (an\n // upload may create sender labels; an extraction creates people and organisations and\n // links facts). AI fields (`doctag_generate`) are the AI review's (blocks).\n if (msg.batch_type === 'entity_extract') {\n finishEntityExtraction(msg.doc_ext_ids ?? [])\n void queryClient.invalidateQueries({ queryKey: arbiQueryKeys.allFacts() })\n }\n if (msg.batch_type === 'upload' || msg.batch_type === 'entity_extract') {\n if (msg.doc_ext_ids?.length)\n void refreshDocuments(queryClient, arbiRef.current, msg.doc_ext_ids)\n void queryClient.invalidateQueries({ queryKey: arbiQueryKeys.allTags() })\n }\n } else if (type.startsWith('chat.') || type === 'agent_dm_status')\n // Chats (direct messages, agent DM progress).\n void applyChatEvent(arbiRef.current, queryClient, msg)\n else if (type.startsWith('call.'))\n applyCallEvent(queryClient, msg, { me: me(), acceptRings: acceptRingsRef.current })\n else if (isNotificationRow(msg)) applyNotificationRow(queryClient, msg, me())\n // Conversation, mail-draft and skill events.\n else void applyLiveUpdate(queryClient, msg as unknown as { type: string })\n\n // The host's own handler for this type, then the subscribers. A throwing handler must not\n // kill the stream.\n try {\n handlersRef.current?.[type]?.(msg)\n } catch (error) {\n logger.error(`[WebSocket] The host's ${type} handler failed:`, error)\n }\n for (const fn of subscribersRef.current) {\n try {\n fn(msg)\n } catch {\n /* swallow — one bad handler can't break the socket */\n }\n }\n }\n\n let retryTimer: ReturnType<typeof setTimeout> | null = null\n let attempt = 0\n\n // The socket is best-effort and never gives up: after the transport's own retries (or a failed\n // connect) a fresh one is opened after a capped backoff, offline meanwhile. It never ends the\n // session; that is the HTTP layer's job.\n const scheduleRestart = () => {\n if (cancelled || evicted || retryTimer) return\n setStatus('disconnected')\n const delay = nextReconnectDelay(attempt)\n attempt += 1\n retryTimer = setTimeout(() => {\n retryTimer = null\n void start()\n }, delay)\n }\n\n const start = async () => {\n if (cancelled) return\n const info = arbiRef.current.getConnectionInfo()\n if (!info) {\n // Not signed in on this client yet: try again shortly.\n scheduleRestart()\n return\n }\n conn?.close()\n conn = null\n setStatus('connecting')\n try {\n const c = await connectWithReconnect({\n baseUrl: resolveSocketBaseUrl(\n info.baseUrl,\n typeof window === 'undefined' ? undefined : window.location.origin\n ),\n accessToken: info.accessToken,\n // Resolve the freshest token on every (re)connect so rotation is picked up.\n getAccessToken: () => arbiRef.current.getConnectionInfo()?.accessToken ?? null,\n // A reconnect refused for its token re-logs in silently first.\n refreshAuth: () => arbiRef.current.refreshAccess(),\n onAuthenticated: (message) => onAuthenticatedRef.current?.(message),\n // The session's: a sign-out closes the socket before the server revokes the token.\n signal: info.signal,\n onMessage,\n onReconnecting: () => setStatus('reconnecting'),\n onReconnected: () => {\n attempt = 0\n setStatus('connected')\n },\n // Evicted (a newer session of the same user, or the server took this connection over for a\n // newer one of this session): reconnecting would be evicted again, or evict that one.\n shouldReconnect: (code) => {\n if (code !== EVICTED_CLOSE_CODE && !evicted) return true\n evicted = true\n setEvicted(true)\n setStatus('disconnected')\n return false\n },\n onReconnectFailed: scheduleRestart,\n onClose: () => {\n if (!cancelled) setStatus(evicted ? 'disconnected' : 'reconnecting')\n },\n })\n if (cancelled) {\n c.close()\n return\n }\n conn = c\n attempt = 0\n setStatus('connected')\n } catch {\n // Stopped by a sign-out: the session is gone, nothing to reopen.\n if (!info.signal.aborted) scheduleRestart()\n }\n }\n setEvicted(false)\n void start()\n\n return () => {\n cancelled = true\n if (retryTimer) clearTimeout(retryTimer)\n conn?.close()\n reset()\n }\n }, [enabled, queryClient, setStatus, setEvicted, applyTaskUpdate, applyPresence, reset])\n\n return <ArbiWsContext.Provider value={context}>{children}</ArbiWsContext.Provider>\n}\n","/**\n * Typed subscription + selector hooks for the shared WebSocket.\n *\n * All message typing flows from the OpenAPI-derived `WebSocketServerMessage`\n * union — handlers are narrowed by the discriminant `type`, exactly like the\n * rest of the SDK.\n */\n\nimport { useEffect, useRef } from 'react'\nimport { isMessageType, type WebSocketServerMessage } from '@arbidocs/client'\nimport { useArbiWsContext } from './context'\nimport { useArbiWsStore, type ArbiWsStatus } from './store'\n\n/**\n * Subscribe to every server message. The handler is kept in a ref, so passing a\n * new inline function each render does not resubscribe.\n */\nexport function useArbiWebSocket(onMessage: (msg: WebSocketServerMessage) => void): void {\n const { subscribe } = useArbiWsContext()\n const handlerRef = useRef(onMessage)\n handlerRef.current = onMessage\n useEffect(() => subscribe((msg) => handlerRef.current(msg)), [subscribe])\n}\n\n/**\n * Subscribe to a single message type, fully narrowed to that variant.\n *\n * @example\n * useArbiWsMessage<WsBatchCompleteMessage>('batch_complete', (msg) => {\n * // msg.batch_type, msg.doc_ext_ids are typed\n * })\n */\nexport function useArbiWsMessage<T extends WebSocketServerMessage>(\n type: T['type'],\n handler: (msg: T) => void\n): void {\n const { subscribe } = useArbiWsContext()\n const handlerRef = useRef(handler)\n handlerRef.current = handler\n useEffect(\n () =>\n subscribe((msg) => {\n if (isMessageType<T>(msg, type)) handlerRef.current(msg)\n }),\n [subscribe, type]\n )\n}\n\n/** Live connection status of the shared socket. */\nexport function useArbiWsStatus(): ArbiWsStatus {\n return useArbiWsStore((s) => s.status)\n}\n","/**\n * Pure workspace adapters: an SDK `WorkspaceResponse` (or the host's own copy of it) to the view\n * models the shell and the workspaces gallery show. No React state, no SDK calls, so a host that\n * has no `arbi` in its host can use them too.\n */\n\nimport type { ReactNode } from 'react'\n\n/** Workspace visibility: public = common, several members = shared, else private. */\nexport type ShellWorkspaceKind = 'private' | 'shared' | 'common'\n\n/** One face on a workspace card. */\nexport interface ShellWorkspaceMember {\n name: string\n picture?: string | null\n}\n\n/**\n * The fields of an SDK workspace the adapters read. Every field but the id and the name is\n * optional, so the SDK's `WorkspaceResponse` and a host's own copy of it are both assignable.\n */\nexport interface ShellWorkspaceSource {\n external_id: string\n name: string\n description?: string | null\n is_public?: boolean\n project_name?: string | null\n updated_at?: string\n shared_document_count?: number\n private_document_count?: number\n users?: ReadonlyArray<{\n user?: {\n given_name?: string | null\n family_name?: string | null\n email?: string | null\n picture?: string | null\n }\n /** Set when the member is an agent: agents are not people and are left off the faces. */\n agent_ext_id?: string | null\n }>\n}\n\n/**\n * A workspace as the shell and the gallery see it. Structurally a superset of blocks'\n * `ShellWorkspace` and `WorkspaceSummary`, so it is passed to both unchanged.\n */\nexport interface ShellWorkspaceItem {\n id: string\n name: string\n kind: ShellWorkspaceKind\n description?: string | null\n projectName?: string | null\n /** A rendered project pill; the host supplies it (see `decorate`). */\n projectLine?: ReactNode\n /** Shared plus private documents. */\n docCount: number\n /** People in the workspace (agents excluded). */\n memberCount: number\n members: ShellWorkspaceMember[]\n /** ISO timestamp. */\n updatedAt?: string\n}\n\n/** A workspace offered in the switcher menu. */\nexport interface ShellRecentWorkspaceItem extends ShellWorkspaceItem {\n /** Pre-formatted \"last seen\" text, when the host supplies `formatLastSeen`. */\n lastSeen?: string\n}\n\n/** Public, several members: shared. Otherwise private. */\nexport function getWorkspaceKind(\n workspace: Pick<ShellWorkspaceSource, 'is_public' | 'users'>\n): ShellWorkspaceKind {\n if (workspace.is_public) return 'common'\n if ((workspace.users?.length ?? 0) > 1) return 'shared'\n return 'private'\n}\n\nfunction memberName(user: NonNullable<ShellWorkspaceSource['users']>[number]['user']): string {\n const full = [user?.given_name, user?.family_name].filter(Boolean).join(' ').trim()\n return full || user?.email || ''\n}\n\n/** Adapt one SDK workspace to the shell and gallery view model. */\nexport function toShellWorkspace(workspace: ShellWorkspaceSource): ShellWorkspaceItem {\n const people = (workspace.users ?? []).filter((u) => !u.agent_ext_id)\n return {\n id: workspace.external_id,\n name: workspace.name,\n kind: getWorkspaceKind(workspace),\n description: workspace.description,\n projectName: workspace.project_name,\n docCount: (workspace.shared_document_count ?? 0) + (workspace.private_document_count ?? 0),\n memberCount: people.length,\n members: people.map((u) => ({ name: memberName(u.user), picture: u.user?.picture })),\n updatedAt: workspace.updated_at,\n }\n}\n\n/** The moment a workspace was last opened here, else last updated; 0 when neither is known. */\nfunction recency(\n workspace: ShellWorkspaceItem,\n lastOpened: Readonly<Record<string, number>> | undefined\n): number {\n const opened = lastOpened?.[workspace.id]\n if (opened !== undefined) return opened\n const updated = Date.parse(workspace.updatedAt ?? '')\n return Number.isNaN(updated) ? 0 : updated\n}\n\n/**\n * The workspace the app is in. Order: the host's selection if it is in the list; else the first\n * workspace of a live list; else the seed's active one; else the first workspace.\n */\nexport function resolveActiveWorkspace(\n items: readonly ShellWorkspaceItem[],\n selectedId: string | null | undefined,\n options: { isSeed?: boolean; seedActiveId?: string } = {}\n): ShellWorkspaceItem | undefined {\n const selected = selectedId ? items.find((w) => w.id === selectedId) : undefined\n if (selected) return selected\n if (options.isSeed && options.seedActiveId) {\n const seeded = items.find((w) => w.id === options.seedActiveId)\n if (seeded) return seeded\n }\n return items[0]\n}\n\n/** The other workspaces for the quick-switch menu, most recently opened first, capped. */\nexport function pickRecentWorkspaces(\n items: readonly ShellWorkspaceItem[],\n activeId: string | undefined,\n options: {\n limit?: number\n lastOpened?: Readonly<Record<string, number>>\n formatLastSeen?: (timestamp: number) => string\n } = {}\n): ShellRecentWorkspaceItem[] {\n const { limit = 4, lastOpened, formatLastSeen } = options\n return items\n .filter((w) => w.id !== activeId)\n .map((w) => ({ w, at: recency(w, lastOpened) }))\n .sort((a, b) => b.at - a.at)\n .slice(0, limit)\n .map(({ w, at }) => (formatLastSeen ? { ...w, lastSeen: formatLastSeen(at) } : w))\n}\n","/**\n * `useShellWorkspaces`: the user's workspaces as the shell's switcher and the workspaces gallery\n * show them, the one the app is in, and `open(workspace)`.\n *\n * Source-agnostic on purpose: the host hands in the list and the selection mechanism it already\n * has (ARBI-frontend its React Query hook and workspace store, a connected app `useWorkspaces`\n * plus the connection's `setWorkspace`).\n */\n\nimport { useCallback, useMemo, useRef, useState } from 'react'\nimport {\n pickRecentWorkspaces,\n resolveActiveWorkspace,\n toShellWorkspace,\n type ShellRecentWorkspaceItem,\n type ShellWorkspaceItem,\n type ShellWorkspaceSource,\n} from './shell-workspaces'\n\n/** Workspaces to show while the account has none (a demo); the host owns the data. */\nexport interface ShellWorkspaceSeed {\n workspaces: readonly ShellWorkspaceItem[]\n /** The seed workspace that counts as the current one when nothing is selected. */\n activeId?: string\n}\n\nexport interface UseShellWorkspacesOptions<S extends ShellWorkspaceSource = ShellWorkspaceSource> {\n /** The account's workspaces (SDK shape). `undefined` while loading. */\n workspaces: readonly S[] | undefined\n isLoading?: boolean\n /** The list query's error, passed through as `error`. */\n loadError?: unknown\n /** The workspace the host says the app is in (the connection's selection). */\n selectedId?: string | null\n /**\n * Make the workspace the app's current one: open it on the server and record the selection.\n * Throw (reject) to report failure. Called for EVERY open, including the current workspace, so\n * a click on the current card still re-opens it and then navigates.\n */\n select: (workspace: ShellWorkspaceItem) => Promise<unknown> | unknown\n /** After a successful select: navigate, toast, close a menu. The \"switch, then navigate\" hook. */\n onOpened?: (workspace: ShellWorkspaceItem) => void\n /** When select rejects. The active workspace is unchanged. Without it the error is in `error`. */\n onOpenError?: (error: unknown, workspace: ShellWorkspaceItem) => void\n /** Demo list for an account that has no workspaces (never while loading). */\n seed?: ShellWorkspaceSeed\n /** Host decoration per workspace, e.g. a rendered project pill. Merged over the adapter. */\n decorate?: (item: ShellWorkspaceItem, source: S) => Partial<ShellWorkspaceItem>\n /** How many recent workspaces the switcher offers. Default 4. */\n recentLimit?: number\n /** `workspace id -> epoch ms` last opened here; orders `recent`, falling back to `updatedAt`. */\n lastOpened?: Readonly<Record<string, number>>\n /** Format a recency timestamp into `recent[].lastSeen`. */\n formatLastSeen?: (timestamp: number) => string\n}\n\nexport interface UseShellWorkspacesResult {\n /** All workspaces: the account's, or the seed when it has none. */\n items: ShellWorkspaceItem[]\n /** The single current workspace; undefined only when there are no workspaces at all. */\n active: ShellWorkspaceItem | undefined\n /** The other workspaces, most recently opened first, for the quick-switch menu. */\n recent: ShellRecentWorkspaceItem[]\n /** The account's own workspaces: false while `items` is the seed. */\n isLive: boolean\n isLoading: boolean\n /** The list query's error or the last failed open; cleared by the next open. */\n error: unknown\n /** Id of the workspace being opened, else null (for a spinner on its card). */\n openingId: string | null\n /** Select the workspace (always, even the current one), then `onOpened`. False if select threw. */\n open: (workspace: Pick<ShellWorkspaceItem, 'id'> | string) => Promise<boolean>\n}\n\nexport function useShellWorkspaces<S extends ShellWorkspaceSource = ShellWorkspaceSource>(\n options: UseShellWorkspacesOptions<S>\n): UseShellWorkspacesResult {\n const {\n workspaces,\n isLoading = false,\n loadError,\n selectedId,\n seed,\n decorate,\n recentLimit,\n lastOpened,\n formatLastSeen,\n } = options\n\n const live = useMemo(\n () =>\n (workspaces ?? []).map((source) => {\n const item = toShellWorkspace(source)\n return decorate ? { ...item, ...decorate(item, source) } : item\n }),\n [workspaces, decorate]\n )\n const isLive = live.length > 0\n const isSeed = !isLive && !isLoading && !!seed\n const items = useMemo(\n () => (isLive ? live : isSeed ? [...seed.workspaces] : []),\n [isLive, live, isSeed, seed]\n )\n const active = useMemo(\n () => resolveActiveWorkspace(items, selectedId, { isSeed, seedActiveId: seed?.activeId }),\n [items, selectedId, isSeed, seed?.activeId]\n )\n const recent = useMemo(\n () =>\n pickRecentWorkspaces(items, active?.id, { limit: recentLimit, lastOpened, formatLastSeen }),\n [items, active?.id, recentLimit, lastOpened, formatLastSeen]\n )\n\n const [openingId, setOpeningId] = useState<string | null>(null)\n const [openError, setOpenError] = useState<unknown>(undefined)\n // Latest callbacks without re-creating `open` on every render.\n const callbacks = useRef({\n select: options.select,\n onOpened: options.onOpened,\n onOpenError: options.onOpenError,\n })\n callbacks.current = {\n select: options.select,\n onOpened: options.onOpened,\n onOpenError: options.onOpenError,\n }\n const itemsRef = useRef(items)\n itemsRef.current = items\n\n const open = useCallback(async (target: Pick<ShellWorkspaceItem, 'id'> | string) => {\n const id = typeof target === 'string' ? target : target.id\n const workspace = itemsRef.current.find((w) => w.id === id)\n if (!workspace) return false\n setOpenError(undefined)\n setOpeningId(id)\n try {\n await callbacks.current.select(workspace)\n } catch (err) {\n setOpenError(err)\n setOpeningId(null)\n callbacks.current.onOpenError?.(err, workspace)\n return false\n }\n setOpeningId(null)\n callbacks.current.onOpened?.(workspace)\n return true\n }, [])\n\n return {\n items,\n active,\n recent,\n isLive,\n isLoading,\n error: openError ?? loadError ?? null,\n openingId,\n open,\n }\n}\n","/**\n * Switching the workspace the app is in: the one coordinator for \"the user is now in workspace X\".\n *\n * The server keeps the active workspace in the session, so every workspace-scoped GET reads the\n * workspace currently open for the session. A naive switch (set the id, `/open` in the background)\n * races every observer that refetches when the id changes: those requests reach a server still in\n * the previous workspace and seed the cache with its data. `switchWorkspace` keeps the order:\n *\n * 1. leave the workspace: its session state (`leaveWorkspace`) and its cached queries go, so\n * nothing shows or refetches the old workspace's data;\n * 2. the selection is cleared, so queries gated on it stop during the round trip;\n * 3. `arbi.selectWorkspace(target)`: the server session is now in the target;\n * 4. the conversations and tags `/open` returned seed their lists, then the selection is\n * committed (`workspaceId`, `workspaceStatus: 'open'`).\n *\n * Concurrent switches (A, then B, then C in quick succession): only the last one commits, and the\n * SDK runs the opens one at a time with the latest request winning, so the server session ends in\n * the last one too. `settled` waits out the switches in flight.\n *\n * A sign-out (`arbi.onSigningOut`, before the server revokes the token) overtakes every switch and\n * open in flight and cancels the queries in flight: the SDK has already stopped new requests and\n * aborts the ones in flight, so none comes back 401 or is reported as a failure.\n */\n\nimport { useEffect, useMemo, useRef } from 'react'\nimport { onlineManager, useQueryClient, type QueryClient } from '@tanstack/react-query'\nimport {\n ArbiWorkspaceSupersededError,\n type Arbi,\n type WorkspaceOpenResponse,\n} from '@arbidocs/sdk/browser'\nimport { isAbortError } from '@arbidocs/client'\nimport { useArbi } from '../useArbi'\nimport { arbiQueryKeys, useWorkspaces } from '../hooks'\nimport { useArbiSessionState, useArbiSessionStore, type ArbiSessionStore } from '../session'\nimport { notify } from '../notifications/notify-store'\nimport { getEntityLabel } from '../entities/registry'\n\n/**\n * What depends on the session's open workspace: dropped on a switch, so nothing of the workspace\n * left shows in the next, and a return reads it afresh.\n */\nconst WORKSPACE_SCOPED_PACKAGE_KEYS = [\n arbiQueryKeys.allDocuments(),\n arbiQueryKeys.allSimilarDocuments(),\n arbiQueryKeys.allWorkspaceUsers(),\n arbiQueryKeys.documentSignatures(),\n arbiQueryKeys.signatureRequests(),\n arbiQueryKeys.databases(),\n]\n\n/** Cancel (so nothing in flight lands afterwards) and drop every workspace-scoped query. */\nfunction drainWorkspaceQueries(queryClient: QueryClient): void {\n for (const queryKey of WORKSPACE_SCOPED_PACKAGE_KEYS) {\n void queryClient.cancelQueries({ queryKey })\n queryClient.removeQueries({ queryKey })\n }\n}\n\n/** The conversations and tags `/open` returned seed their lists (patched in place from then on). */\nfunction seedOpenedWorkspace(\n queryClient: QueryClient,\n workspaceId: string,\n opened: WorkspaceOpenResponse\n): void {\n if (opened.conversations)\n queryClient.setQueryData(arbiQueryKeys.conversations(workspaceId), opened.conversations)\n if (opened.tags) queryClient.setQueryData(arbiQueryKeys.tags(workspaceId), opened.tags)\n}\n\n/** The server refused to open an archived workspace (423 `workspace_archived`). */\nexport function isWorkspaceArchivedError(error: unknown): boolean {\n const body = (error as { apiError?: unknown } | null | undefined)?.apiError ?? error\n const detail = (body as { detail?: unknown } | null | undefined)?.detail\n return (\n !!detail &&\n typeof detail === 'object' &&\n (detail as { code?: unknown }).code === 'workspace_archived'\n )\n}\n\n/** What to tell someone who tried to open an archived workspace. */\nexport const archivedWorkspaceMessage = (name: string) =>\n `\"${name}\" is archived. Its owner can unarchive it from the workspace list.`\n\ninterface ListedWorkspace {\n external_id: string\n name: string\n archive?: unknown\n}\n\nconst listedWorkspace = (queryClient: QueryClient, workspaceId: string) =>\n queryClient\n .getQueryData<ListedWorkspace[]>(arbiQueryKeys.workspaces())\n ?.find((w) => w.external_id === workspaceId)\n\n// One sequence for every hook instance, so a newer switch anywhere wins.\nlet switchEpoch = 0\n// The switches not yet settled (opened, refused or overtaken).\nconst switching = new Set<Promise<boolean>>()\n\n/** Exported for tests. */\nexport const resetSwitchEpochForTests = () => {\n switchEpoch = 0\n switching.clear()\n}\n\n/** How long a switch waits for the signed-in session to reach its `Arbi` (see `signedIn`). */\nconst SIGNED_IN_WAIT_MS = 10_000\nconst SIGNED_IN_POLL_MS = 50\n\n/**\n * Wait until the `Arbi` in scope holds the login. Right after a sign-in (or a reload) the session\n * is signed in before the host's `Arbi` has its keys (a host reads them from the device and then\n * renews its `Arbi`): an open asked for in that window would fail with \"Not logged in\". Resolves\n * at once when it holds them, or when the session is not signed in at all (nothing to wait for).\n */\nasync function signedIn(arbi: () => Arbi, timeoutMs = SIGNED_IN_WAIT_MS): Promise<void> {\n const deadline = Date.now() + timeoutMs\n while (\n !arbi().isLoggedIn &&\n arbi().session?.getState().signedIn === true &&\n Date.now() < deadline\n ) {\n await new Promise((resolve) => setTimeout(resolve, SIGNED_IN_POLL_MS))\n }\n}\n\n/** Resolves once no workspace switch is in flight (including any started while waiting). */\nasync function switchesSettled(): Promise<void> {\n while (switching.size > 0) await Promise.allSettled([...switching])\n}\n\nexport interface SwitchWorkspaceTarget {\n id: string\n /** For the notices; default: the name in the workspace list. */\n name?: string\n}\n\nexport interface UseSwitchWorkspaceResult {\n /**\n * Make `target` the workspace the app is in. True once it is open (at once when it already\n * is); false when it could not be (archived, offline, refused: the user was told), or when a\n * newer switch overtook it.\n */\n switchWorkspace: (target: SwitchWorkspaceTarget) => Promise<boolean>\n /** Leave the workspace for none (after deleting or leaving it), with the same clean-up. */\n clearWorkspace: () => void\n /**\n * Open the selected workspace on the server session as it is, without leaving anything or a\n * notice: after a sign-in or a reload (a new server session), or to re-assert it before a write.\n * False when there is none, it could not be opened, or a switch overtook it.\n */\n openSelectedWorkspace: () => Promise<boolean>\n /**\n * Resolves once no switch is in flight: the selection is then committed (or back to where it\n * was), so reading it says which workspace the session is in.\n */\n settled: () => Promise<void>\n}\n\n/** What a workspace switch runs on. */\nexport interface WorkspaceSwitchContext {\n /** The `Arbi` on the signed-in session, as of the switch. */\n arbi: () => Arbi\n session: ArbiSessionStore\n queryClient: QueryClient\n}\n\n/**\n * The workspace switch over a host's session, for code that runs outside `<ArbiHost>` (a host's\n * own environment, built before its host). Inside, use `useSwitchWorkspace`.\n */\nexport function createWorkspaceSwitch({\n arbi,\n session,\n queryClient,\n}: WorkspaceSwitchContext): UseSwitchWorkspaceResult {\n const switchWorkspace = (target: SwitchWorkspaceTarget): Promise<boolean> => {\n const run = runSwitch(target)\n switching.add(run)\n void run.finally(() => switching.delete(run))\n return run\n }\n\n const runSwitch = async (target: SwitchWorkspaceTarget): Promise<boolean> => {\n const { workspaceId: previousId, workspaceStatus } = session.getState()\n const isSame = previousId === target.id\n if (isSame && workspaceStatus === 'open') return true\n\n const listed = listedWorkspace(queryClient, target.id)\n const name = target.name || listed?.name || ''\n const noun = getEntityLabel('WORKSPACE')\n // An archived workspace cannot be opened: say so before leaving the current one.\n if (listed?.archive) {\n notify.info(archivedWorkspaceMessage(name))\n return false\n }\n // Offline, the user stays in the workspace they are in: another one's lists cannot load.\n if (!isSame && !onlineManager.isOnline()) {\n notify.info(\n `You're offline — you can only use the ${noun} you're already in. Reconnect to switch.`\n )\n return false\n }\n\n const epoch = ++switchEpoch\n notify.info(`Opening \"${name}\" ${noun}…`, { workspaceId: target.id, duration: 2000 })\n // Signed in, but the keys not on this `Arbi` yet: the open waits for them, not fails.\n await signedIn(arbi)\n if (epoch !== switchEpoch) return false\n // Not yet open (a reload): nothing to leave, it only needs `/open`.\n if (!isSame) {\n session.leaveWorkspace()\n drainWorkspaceQueries(queryClient)\n session.setWorkspaceId(null)\n }\n session.setWorkspaceStatus('opening')\n\n performance.mark('arbi:workspace-open:start')\n let opened: WorkspaceOpenResponse\n try {\n opened = await arbi().selectWorkspace(target.id)\n } catch (error) {\n // A sign-out stopped it: the session is going, nothing to restore or report.\n if (isAbortError(error)) return false\n const superseded = error instanceof ArbiWorkspaceSupersededError\n if (!superseded) console.error('[switchWorkspace] /open failed:', error)\n // Overtaken before its turn by a newer switch: that one commits. By an open from elsewhere\n // (no newer switch): back to the previous selection, closed, as for a failure.\n if (superseded && epoch === switchEpoch) {\n if (previousId) session.setWorkspaceId(previousId)\n session.setWorkspaceStatus('closed')\n } else if (epoch === switchEpoch) {\n // Back to the previous selection, closed: `useOpenSelectedWorkspace` opens it again.\n if (previousId) session.setWorkspaceId(previousId)\n session.setWorkspaceStatus('closed')\n if (isWorkspaceArchivedError(error)) {\n // Archived since the list was read: refresh it so it shows as archived.\n notify.info(archivedWorkspaceMessage(name))\n void queryClient.invalidateQueries({ queryKey: arbiQueryKeys.workspaces() })\n } else {\n notify.error(`Failed to open \"${name}\" ${noun}`)\n }\n }\n return false\n }\n // A newer switch started meanwhile: it commits, not this one.\n if (epoch !== switchEpoch) return false\n\n seedOpenedWorkspace(queryClient, target.id, opened)\n performance.mark('arbi:workspace-open:response')\n session.setWorkspaceId(target.id)\n session.setWorkspaceStatus('open')\n return true\n }\n\n const clearWorkspace = () => {\n ++switchEpoch\n session.leaveWorkspace()\n drainWorkspaceQueries(queryClient)\n session.setWorkspaceId(null)\n }\n\n const openSelectedWorkspace = async (): Promise<boolean> => {\n const workspaceId = session.getState().workspaceId\n if (!workspaceId) return false\n const epoch = switchEpoch\n await signedIn(arbi)\n if (epoch !== switchEpoch || session.getState().workspaceId !== workspaceId) return false\n performance.mark('arbi:workspace-open:start')\n let opened: WorkspaceOpenResponse\n try {\n opened = await arbi().selectWorkspace(workspaceId)\n } catch (error) {\n // Overtaken by a newer open, or stopped by a sign-out: nothing to report.\n if (!(error instanceof ArbiWorkspaceSupersededError) && !isAbortError(error)) {\n console.error('[openSelectedWorkspace] /open failed:', error)\n }\n return false\n }\n // A switch started meanwhile: it commits its own workspace.\n if (epoch !== switchEpoch || session.getState().workspaceId !== workspaceId) return false\n seedOpenedWorkspace(queryClient, workspaceId, opened)\n performance.mark('arbi:workspace-open:response')\n session.setWorkspaceStatus('open')\n return true\n }\n\n return { switchWorkspace, clearWorkspace, openSelectedWorkspace, settled: switchesSettled }\n}\n\n/** The workspace switch of the `<ArbiHost>` in scope (its `Arbi`, its session state). */\nexport function useSwitchWorkspace(): UseSwitchWorkspaceResult {\n const arbi = useArbi()\n const arbiRef = useRef(arbi)\n arbiRef.current = arbi\n const session = useArbiSessionStore()\n const queryClient = useQueryClient()\n // Signing out: the switches and opens in flight are overtaken, the queries in flight cancelled.\n useEffect(\n () =>\n arbi.onSigningOut?.(() => {\n ++switchEpoch\n void queryClient.cancelQueries()\n }),\n [arbi, queryClient]\n )\n return useMemo(\n () => createWorkspaceSwitch({ arbi: () => arbiRef.current, session, queryClient }),\n [session, queryClient]\n )\n}\n\n/**\n * Keep the selected workspace open on the server session: open it once signed in (after a\n * sign-in or a reload, when the selection was kept but the server session is new), and drop it\n * when the workspace list says it was archived since (by its owner, perhaps on another device),\n * or that it is gone (deleted, or the person left or was removed): the app is then on the\n * workspace list. Mounted once, by the signed-in app.\n */\nexport function useOpenSelectedWorkspace(): void {\n const arbi = useArbi()\n const { clearWorkspace, openSelectedWorkspace } = useSwitchWorkspace()\n const workspaceId = useArbiSessionState((s) => s.workspaceId)\n const status = useArbiSessionState((s) => s.workspaceStatus)\n const session = useArbiSessionStore()\n const queryClient = useQueryClient()\n const { data: workspaces, isLoading: listing, isFetching } = useWorkspaces()\n const listed = workspaces as ListedWorkspace[] | undefined\n const archived = listed?.find((w) => w.external_id === workspaceId && w.archive)\n // The open workspace is gone (deleted, or the person left or was removed) once a list read after\n // it was opened no longer has it: one read before (access granted since) may not have it yet.\n // (Counted, not timed: a read can land in the same millisecond.)\n const reads = queryClient.getQueryState(arbiQueryKeys.workspaces())?.dataUpdateCount ?? 0\n const opened = useRef<{ id: string | null; reads: number }>({ id: null, reads: 0 })\n const openId = status === 'open' ? workspaceId : null\n if (opened.current.id !== openId) opened.current = { id: openId, reads }\n const gone =\n !!openId &&\n !!listed &&\n !isFetching &&\n reads > opened.current.reads &&\n !listed.some((w) => w.external_id === openId)\n\n useEffect(() => {\n if (!archived) return\n notify.info(archivedWorkspaceMessage(archived.name))\n clearWorkspace()\n }, [archived, clearWorkspace])\n\n useEffect(() => {\n if (gone) clearWorkspace()\n }, [gone, clearWorkspace])\n\n // One open at a time; a failed one is tried again when the session or selection changes.\n const opening = useRef(false)\n const signedIn = arbi.isLoggedIn\n useEffect(() => {\n // After the workspace list: it says whether the workspace was archived, and it holds the key\n // the open needs (no list of the open's own).\n if (\n !workspaceId ||\n archived ||\n gone ||\n listing ||\n status !== 'closed' ||\n !signedIn ||\n opening.current\n )\n return\n opening.current = true\n void openSelectedWorkspace()\n .then(async (ok) => {\n if (ok) return\n // Refused: deleted, or left, since (the kept selection of a reload)? The list read now\n // says. (Not the list a reload restores: it may predate a workspace created since.)\n const fresh = await queryClient\n .fetchQuery({\n queryKey: arbiQueryKeys.workspaces(),\n queryFn: () => arbi.workspaces.list(),\n staleTime: 0,\n })\n .catch(() => null)\n if (\n fresh &&\n session.getState().workspaceId === workspaceId &&\n !(fresh as ListedWorkspace[]).some((w) => w.external_id === workspaceId)\n )\n clearWorkspace()\n })\n .finally(() => {\n opening.current = false\n })\n }, [\n arbi,\n session,\n clearWorkspace,\n openSelectedWorkspace,\n queryClient,\n workspaceId,\n archived,\n gone,\n listing,\n status,\n signedIn,\n ])\n}\n","/**\n * Workspace writes over the SDK: create one, rename, describe or change the visibility of the open\n * workspace, and move a workspace to another project. Its members and their writes are in\n * `workspace-users.ts`.\n */\n\nimport { useMutation, useQueryClient } from '@tanstack/react-query'\nimport type { components } from '@arbidocs/client'\nimport { useArbi } from '../useArbi'\nimport { arbiQueryKeys } from '../hooks'\n\nexport type WorkspaceUpdate = components['schemas']['WorkspaceUpdateRequest']\ntype Workspace = components['schemas']['WorkspaceResponse']\n\n/** A new workspace: its name, the project it belongs to, and optionally a description. */\nexport interface CreateWorkspaceVars {\n name: string\n projectId: string\n description?: string | null\n isPublic?: boolean\n}\n\n/**\n * Create a workspace (its key generated and sealed by the SDK). The new workspace goes into the\n * cached list at once, so opening it right away finds it; the list and the projects (their\n * workspace counts) are then read again.\n */\nexport function useCreateWorkspace() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: ({ name, projectId, description, isPublic }: CreateWorkspaceVars) =>\n arbi.workspaces.create(name, projectId, description, isPublic),\n onSuccess: (created) => {\n if (qc.getQueryCache().find({ queryKey: arbiQueryKeys.workspaces(), exact: true })) {\n qc.setQueryData<Workspace[]>(arbiQueryKeys.workspaces(), (list = []) =>\n list.some((w) => w.external_id === created.external_id) ? list : [...list, created]\n )\n }\n void qc.invalidateQueries({ queryKey: arbiQueryKeys.workspaces() })\n void qc.invalidateQueries({ queryKey: arbiQueryKeys.projects() })\n },\n })\n}\n\n/** Move a workspace (open or not) to another project; both projects' counts change. */\nexport function useMoveWorkspaceToProject() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: ({ workspaceId, projectId }: { workspaceId: string; projectId: string }) =>\n arbi.workspaces.moveToProject(workspaceId, projectId),\n onSuccess: () => {\n void qc.invalidateQueries({ queryKey: arbiQueryKeys.workspaces() })\n void qc.invalidateQueries({ queryKey: arbiQueryKeys.projects() })\n },\n })\n}\n\n/** Change the open workspace's name, description or visibility. */\nexport function useUpdateWorkspace() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: (body: WorkspaceUpdate) => arbi.workspaces.update(body),\n onSuccess: () => qc.invalidateQueries({ queryKey: arbiQueryKeys.workspaces() }),\n })\n}\n","/**\n * A workspace's members and the writes that change them: adding people (standing membership, a\n * session-scoped grant, an invitation, a resource share), removing them, changing their role.\n *\n * The member list is read when shown and kept for 15 minutes; members change rarely and every\n * write here re-reads it, so it is not polled.\n */\n\nimport { useMutation, useQuery, useQueryClient, type QueryClient } from '@tanstack/react-query'\nimport type { components } from '@arbidocs/client'\nimport type { workspaces } from '@arbidocs/sdk/browser'\nimport { useArbi } from '../useArbi'\nimport { arbiMutationKeys, arbiQueryKeys } from '../hooks'\n\nexport type WorkspaceMember = components['schemas']['WorkspaceUserResponse']\nexport type AddWorkspaceMembersRequest = workspaces.AddWorkspaceMembersRequest\nexport type WorkspaceRole = 'owner' | 'collaborator' | 'guest'\n\n/** How long a member list is trusted before it is read again on use. */\nconst MEMBERS_STALE_MS = 15 * 60 * 1000\n\n/**\n * A workspace's members (default: the open one). `beforeFetch` runs first (e.g. to re-open the\n * workspace on the session); `enabled` overrides the \"a workspace is open\" gate.\n */\nexport function useWorkspaceUsers(\n workspaceId?: string | null,\n options?: {\n enabled?: boolean\n beforeFetch?: () => Promise<unknown>\n }\n) {\n const arbi = useArbi()\n const workspace = workspaceId ?? (arbi.hasWorkspace ? arbi.getWorkspaceId() : '')\n return useQuery({\n queryKey: arbiQueryKeys.workspaceUsers(workspace),\n enabled: !!workspace && (options?.enabled ?? arbi.hasWorkspace),\n queryFn: async (): Promise<WorkspaceMember[]> => {\n await options?.beforeFetch?.()\n return arbi.readInWorkspace(workspace, () => arbi.workspaces.listUsers())\n },\n staleTime: MEMBERS_STALE_MS,\n })\n}\n\n/** What a membership change affects: the member lists and the workspaces (their member counts). */\nfunction settleMembership(qc: QueryClient): Promise<unknown> {\n return Promise.all([\n qc.invalidateQueries({ queryKey: arbiQueryKeys.allWorkspaceUsers() }),\n qc.invalidateQueries({ queryKey: arbiQueryKeys.workspaces() }),\n // A project's collaborator quota counts workspace members.\n qc.invalidateQueries({ queryKey: arbiQueryKeys.projects() }),\n ])\n}\n\n/**\n * Add people to a workspace, with the whole request: the open workspace, or `workspace_ext_id`\n * with its key sealed to this session; a session-scoped grant (`session_pubkey_b64`); an invitation\n * to people not on the platform (`confirm_invite`, which also leaves a pending grant on their\n * contact); a share of one resource (`resource_type`, `resource_ext_id`). Resolves with the\n * memberships added (someone already a member, or not on the platform, is missing from it).\n */\nexport function useAddWorkspaceMembers() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationKey: arbiMutationKeys.workspaceMembership(),\n mutationFn: (request: AddWorkspaceMembersRequest): Promise<WorkspaceMember[]> =>\n arbi.workspaces.addMembers(request),\n onSuccess: () =>\n Promise.all([\n settleMembership(qc),\n qc.invalidateQueries({ queryKey: arbiQueryKeys.contacts() }),\n ]),\n })\n}\n\n/**\n * Remove people from `workspaceId` (default: the open workspace, read when the removal is sent),\n * owners only; anyone may remove themselves: leaving. The request names the workspace, so a\n * switch meanwhile cannot move the removal to another one.\n */\nexport function useRemoveWorkspaceMembers(workspaceId?: string | null) {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationKey: arbiMutationKeys.workspaceMembership(),\n mutationFn: (userIds: string[]) =>\n workspaceId\n ? arbi.workspaces.removeUsers(userIds, { workspaceId })\n : arbi.workspaces.removeUsers(userIds),\n onSuccess: () => settleMembership(qc),\n })\n}\n\n/** Change people's role in the open workspace (owners). */\nexport function useSetWorkspaceMemberRoles() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationKey: arbiMutationKeys.setWorkspaceMemberRoles(),\n mutationFn: ({ userIds, role }: { userIds: string[]; role: WorkspaceRole }) =>\n arbi.workspaces.setUserRole(userIds, role),\n onSuccess: () =>\n Promise.all([\n qc.invalidateQueries({ queryKey: arbiQueryKeys.allWorkspaceUsers() }),\n qc.invalidateQueries({ queryKey: arbiQueryKeys.workspaces() }),\n ]),\n })\n}\n","/**\n * Delete workspaces (owners only). They go to Recently deleted, where they can be restored for a\n * while; the workspace list refreshes.\n */\n\nimport { useMutation, useQueryClient } from '@tanstack/react-query'\nimport { useArbi } from '../useArbi'\nimport { arbiQueryKeys } from '../hooks'\n\nexport function useDeleteWorkspaces() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: (workspaceIds: string[]) => arbi.workspaces.delete(workspaceIds),\n onSuccess: () => qc.invalidateQueries({ queryKey: arbiQueryKeys.workspaces() }),\n })\n}\n","/**\n * Assemble the workspace export archive from `POST /v1/workspace/export`.\n *\n * manifest.json what the archive is: format, scope, counts, layout\n * documents/<folder>/<name> current versions (older ones under documents/_versions/); one\n * document id may name several files, one per version\n * .../<name> (markup).pdf beside a version with markup: its PDF with the annotations as\n * native PDF annotations\n * data/<entity>.json one JSON array per entity type, cross-referenced by external_id\n * index.csv the documents' metadata table (when columns were chosen)\n *\n * Pure apart from `fetchFile`, so it is tested without a network.\n */\n\nimport type { WorkspaceExport } from './transfer'\n\nexport type ExportFileKind = 'original' | 'markup'\n\nexport interface BuildArchiveInput {\n exportData: WorkspaceExport\n /**\n * Fetch one file: a version of a document (`original`), or that version's markup PDF\n * (`markup`); `null` when it could not be fetched.\n */\n fetchFile: (docExtId: string, version: number, kind: ExportFileKind) => Promise<Blob | null>\n /** Ready-made `index.csv` content, or null for none. */\n metadataCsv?: string | null\n onProgress?: (done: number, total: number) => void\n}\n\nexport interface BuiltArchive {\n blob: Blob\n fileCount: number\n /** Archive paths of the files that could not be fetched. */\n failed: string[]\n}\n\nexport async function buildWorkspaceArchive({\n exportData,\n fetchFile,\n metadataCsv,\n onProgress,\n}: BuildArchiveInput): Promise<BuiltArchive> {\n const JSZip = (await import('jszip')).default\n const zip = new JSZip()\n const failed: string[] = []\n let fileCount = 0\n const files = exportData.files ?? []\n for (const [index, file] of files.entries()) {\n try {\n const kind: ExportFileKind = file.markup ? 'markup' : 'original'\n const blob = await fetchFile(file.doc_ext_id, file.version ?? 1, kind)\n if (blob) {\n zip.file(file.path, blob)\n fileCount++\n } else {\n failed.push(file.path)\n }\n } catch {\n failed.push(file.path)\n }\n onProgress?.(index + 1, files.length)\n }\n for (const [entity, records] of Object.entries(exportData.data ?? {})) {\n zip.file(`data/${entity}.json`, JSON.stringify(records, null, 2))\n }\n if (metadataCsv) zip.file('index.csv', metadataCsv)\n zip.file(\n 'manifest.json',\n JSON.stringify({ ...exportData.manifest, files_missing: failed }, null, 2)\n )\n return { blob: await zip.generateAsync({ type: 'blob' }), fileCount, failed }\n}\n","/**\n * Download, copy or move a scope of the open workspace (`/v1/workspace/transfer*`,\n * `/v1/workspace/export`). One scope shape (`TransferScope`) feeds them all: the preview\n * (`usePlanWorkspaceTransfer`), the background copy or move (`useStartWorkspaceTransfer`, followed\n * with `useWorkspaceTransfer`) and the download (`useWorkspaceExportDownload`). The target\n * workspace's key is sealed by the SDK (`arbi.workspaces.transfer`).\n */\n\nimport { useCallback, useState } from 'react'\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'\nimport type { components } from '@arbidocs/client'\nimport { useArbi } from '../useArbi'\nimport { arbiQueryKeys } from '../hooks'\nimport { notify } from '../notifications/notify-store'\nimport { downloadBlob } from '../document-tools/environment'\nimport { fetchDocumentFile } from '../document-tools/document-pdf'\nimport { fetchMarkupPdf } from '../document-tools/markup-download'\nimport { archiveName, buildDocumentMetadataRows } from '../documents/document-download'\nimport type { WorkspaceDocument } from '../documents/documents-cache'\nimport { buildWorkspaceArchive } from './export-archive'\n\nexport type TransferScope = components['schemas']['TransferScope']\nexport type TransferKind = components['schemas']['TransferKind']\nexport type TransferMode = components['schemas']['TransferMode']\nexport type TransferPlan = components['schemas']['TransferPlanResponse']\nexport type TransferStatus = components['schemas']['TransferStatusResponse']\nexport type TransferConflictPolicy = components['schemas']['ConflictPolicy']\nexport type WorkspaceExport = components['schemas']['WorkspaceExportResponse']\n\n/** Polling cadence while a job runs; it goes idle once the job has finished. */\nexport const TRANSFER_POLL_MS = 1500\n\n/** A job no worker runs any more (interrupted, cancelled, failed, or done with failures). */\nexport function isTransferResumable(status: TransferStatus): boolean {\n if (\n status.status === 'interrupted' ||\n status.status === 'cancelled' ||\n status.status === 'failed'\n )\n return true\n return status.status === 'completed' && Number(status.counts?.failed ?? 0) > 0\n}\n\n/** The job has stopped (it is neither queued nor running). */\nexport function isTransferFinished(status: TransferStatus | null | undefined): boolean {\n return !!status && status.status !== 'running' && status.status !== 'queued'\n}\n\nfunction openWorkspaceId(arbi: ReturnType<typeof useArbi>): string {\n return arbi.hasWorkspace ? arbi.getWorkspaceId() : ''\n}\n\n/** What a scope would take in the open workspace; re-read when the scope or the mode changes. */\nexport function usePlanWorkspaceTransfer(\n scope: TransferScope,\n mode: TransferMode,\n options: { enabled?: boolean } = {}\n) {\n const arbi = useArbi()\n const workspaceId = openWorkspaceId(arbi)\n return useQuery({\n queryKey: arbiQueryKeys.workspaceTransferPlan(workspaceId, JSON.stringify(scope), mode),\n // The plan is of the workspace open on the server: kept only if it stayed `workspaceId`.\n queryFn: () =>\n arbi.readInWorkspace(\n workspaceId,\n () => arbi.workspaces.transfer.plan(scope, mode) as Promise<TransferPlan>\n ),\n enabled: !!workspaceId && (options.enabled ?? true),\n staleTime: 10_000,\n // The previous plan stays while the next loads, never another workspace's.\n // ['arbi', 'workspaceTransfers', 'plan', workspaceId, scope, mode]\n placeholderData: (previous, previousQuery) =>\n previousQuery?.queryKey[3] === workspaceId ? previous : undefined,\n })\n}\n\n/** Start copying or moving into another workspace (a background job). */\nexport function useStartWorkspaceTransfer() {\n const arbi = useArbi()\n return useMutation({\n mutationFn: (params: {\n scope: TransferScope\n mode: TransferMode\n targetWorkspaceId: string\n onConflict?: TransferConflictPolicy\n }) => arbi.workspaces.transfer.start(params) as Promise<TransferStatus>,\n })\n}\n\n/** Resume a stopped job (nothing is copied twice). */\nexport function useResumeWorkspaceTransfer() {\n const arbi = useArbi()\n return useMutation({\n mutationFn: ({\n transferId,\n targetWorkspaceId,\n }: {\n transferId: string\n targetWorkspaceId: string\n }) => arbi.workspaces.transfer.resume(transferId, targetWorkspaceId) as Promise<TransferStatus>,\n })\n}\n\nexport function useCancelWorkspaceTransfer() {\n const arbi = useArbi()\n return useMutation({\n mutationFn: (transferId: string) => arbi.workspaces.transfer.cancel(transferId),\n })\n}\n\n/** One job's progress, polled while it runs. */\nexport function useWorkspaceTransfer(transferId: string | null) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.workspaceTransfer(transferId ?? ''),\n queryFn: () => arbi.workspaces.transfer.get(transferId ?? '') as Promise<TransferStatus>,\n enabled: !!transferId && arbi.isLoggedIn,\n staleTime: 0,\n refetchInterval: (query) =>\n isTransferFinished(query.state.data as TransferStatus | undefined) ? false : TRANSFER_POLL_MS,\n })\n}\n\n/** The caller's recent jobs out of the open workspace (to offer a resume). */\nexport function useWorkspaceTransfers(options: { enabled?: boolean } = {}) {\n const arbi = useArbi()\n const workspaceId = openWorkspaceId(arbi)\n return useQuery({\n queryKey: arbiQueryKeys.workspaceTransfers(workspaceId),\n queryFn: () =>\n arbi.readInWorkspace(\n workspaceId,\n () => arbi.workspaces.transfer.list() as Promise<TransferStatus[]>\n ),\n enabled: !!workspaceId && (options.enabled ?? true),\n })\n}\n\n/** What to refresh once a job has finished: the workspaces' counts always, this one's lists after a move. */\nexport function useInvalidateAfterTransfer() {\n const queryClient = useQueryClient()\n return useCallback(\n (mode: TransferMode) => {\n void queryClient.invalidateQueries({ queryKey: arbiQueryKeys.workspaces() })\n void queryClient.invalidateQueries({ queryKey: arbiQueryKeys.allWorkspaceTransfers() })\n if (mode !== 'move') return\n for (const queryKey of [\n arbiQueryKeys.workflows(),\n arbiQueryKeys.allFacts(),\n arbiQueryKeys.allTags(),\n arbiQueryKeys.allDocuments(),\n arbiQueryKeys.allConversations(),\n ])\n void queryClient.invalidateQueries({ queryKey })\n },\n [queryClient]\n )\n}\n\nexport interface ExportDownloadRequest {\n scope: TransferScope\n /** Documents known to the page, for `index.csv` (only those in the export are listed). */\n documents?: WorkspaceDocument[]\n /** CSV columns: undefined = all standard columns, [] = no index.csv. */\n csvColumns?: string[]\n}\n\n/**\n * Download a scope of the open workspace as files: its documents (every version, and each\n * version's markup PDF), one JSON file per entity type and a manifest (`buildWorkspaceArchive`).\n */\nexport function useWorkspaceExportDownload({\n workspaceName,\n workspaceId,\n}: { workspaceName?: string; workspaceId?: string } = {}) {\n const arbi = useArbi()\n const [progress, setProgress] = useState<{ done: number; total: number } | null>(null)\n\n const download = useCallback(\n async ({ scope, documents = [], csvColumns }: ExportDownloadRequest) => {\n setProgress({ done: 0, total: 0 })\n try {\n const data = (await arbi.workspaces.transfer.exportData(\n scope,\n workspaceId ? { workspaceId } : undefined\n )) as WorkspaceExport\n let metadataCsv: string | null = null\n if (csvColumns === undefined || csvColumns.length > 0) {\n const exported = new Set(\n (data.files ?? []).filter((f) => !f.markup).map((f) => f.doc_ext_id)\n )\n const rows = documents.filter((d) => exported.has(d.external_id))\n if (rows.length > 0) {\n const Papa = (await import('papaparse')).default\n metadataCsv = Papa.unparse(buildDocumentMetadataRows(rows, csvColumns))\n }\n }\n const client = arbi.getClient().fetch\n const archive = await buildWorkspaceArchive({\n exportData: data,\n fetchFile: async (docExtId, version, kind) =>\n kind === 'markup'\n ? (await fetchMarkupPdf(client, docExtId, version, workspaceId)).blob\n : fetchDocumentFile(client, docExtId, { version, workspaceExtId: workspaceId }),\n metadataCsv,\n onProgress: (done, total) => setProgress({ done, total }),\n })\n const fileName = archiveName(workspaceName, 'export')\n downloadBlob(archive.blob, fileName)\n const files = `${archive.fileCount} file${archive.fileCount !== 1 ? 's' : ''}`\n if (archive.failed.length === 0) {\n notify.success(`Successfully downloaded ${files} and data in ${fileName}`)\n } else {\n notify.warning(\n `Downloaded ${files} in ${fileName}; ${archive.failed.length} could not be fetched (listed in manifest.json)`\n )\n }\n return true\n } catch (error) {\n console.error('Workspace export failed:', error)\n notify.error('Failed to download. Please try again.')\n return false\n } finally {\n setProgress(null)\n }\n },\n [arbi, workspaceName, workspaceId]\n )\n\n return { download, isDownloading: progress !== null, progress }\n}\n","/**\n * A workspace access request (a `workspace_access_request` notification): what the requester\n * sealed for the owner (their session's public key, for a temporary grant, and a note).\n */\nimport { decryptMessage, getUserEncryptionKeypair } from '@arbidocs/client'\nimport { useMutation, useQueryClient } from '@tanstack/react-query'\nimport { useArbi } from '../useArbi'\nimport { arbiQueryKeys } from '../hooks'\n\n/** What a request carries, sealed from the requester to the owner. */\nexport interface AccessRequestPayload {\n session_pubkey_b64: string\n note?: string\n}\n\n/**\n * Open a request's sealed content with the signed-in person's key. Null when no one is signed in\n * or it cannot be opened (not meant for them, damaged).\n */\nexport async function openAccessRequest(\n content: string,\n requesterPublicKey: string\n): Promise<AccessRequestPayload | null> {\n const keypair = await getUserEncryptionKeypair()\n if (!keypair) return null\n try {\n const plaintext = await decryptMessage(content, requesterPublicKey, keypair.secretKey)\n return JSON.parse(plaintext) as AccessRequestPayload\n } catch {\n return null\n }\n}\n\n/** Who a request goes to: anyone we can address and seal to. */\nexport interface AccessRequestRecipient {\n external_id: string\n encryption_public_key: string\n}\n\n/** What a request says beyond the session key: a note, and (rarely) the workspace it is for. */\nexport interface RequestAccessOptions {\n note?: string\n /**\n * Only when the workspace is already known (an invite-and-share completed after sign-up): it\n * locks the owner's review to it. Otherwise the owner picks.\n */\n workspaceExtId?: string\n}\n\n/**\n * Ask someone for workspace access: seal this session's public key (for a temporary grant) and a\n * note to them, and send it as a `workspace_access_request` notification.\n */\nexport function useRequestWorkspaceAccess() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: ({\n recipient,\n options,\n }: {\n recipient: AccessRequestRecipient\n options?: RequestAccessOptions\n }) =>\n arbi.workspaces.requestAccess({\n recipientExtId: recipient.external_id,\n recipientEncryptionPublicKey: recipient.encryption_public_key,\n note: options?.note,\n workspaceExtId: options?.workspaceExtId,\n }),\n onSuccess: () => qc.invalidateQueries({ queryKey: arbiQueryKeys.allNotifications() }),\n })\n}\n","/**\n * Workspace archive: a workspace's archive state, archiving and unarchiving it, and keeping a list\n * of workspaces current while one of them moves to or from the archive.\n */\n\nimport { useEffect } from 'react'\nimport { useMutation, useQuery, useQueryClient, type QueryClient } from '@tanstack/react-query'\nimport type { components } from '@arbidocs/client'\nimport { useArbi } from '../useArbi'\nimport { arbiQueryKeys } from '../query-keys'\n\nexport type WorkspaceArchive = components['schemas']['WorkspaceArchiveRead']\nexport type WorkspaceArchiveState = components['schemas']['WorkspaceArchiveState']\nexport type UnarchiveEstimate = components['schemas']['UnarchiveEstimate']\n\n/** How often a workspace on its way to or from the archive is checked. */\nexport const ARCHIVE_POLL_MS = 5_000\n\n/** Its files are moving (to the archive, or back and re-indexing): progress keeps changing. */\nexport const isArchiveMoving = (status: string | null | undefined) =>\n status === 'archiving' || status === 'restoring'\n\n/** A workspace's archive state, bytes per tier and (while archived) what unarchiving costs. */\nexport function useWorkspaceArchive(workspaceId: string | null | undefined, enabled = true) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.workspaceArchive(workspaceId ?? ''),\n queryFn: () => arbi.workspaces.archiveState(workspaceId as string),\n enabled: arbi.isLoggedIn && enabled && Boolean(workspaceId),\n retry: false,\n refetchInterval: (query) =>\n isArchiveMoving(query.state.data?.status) ? ARCHIVE_POLL_MS : false,\n })\n}\n\n/** After an archive or unarchive: the workspace list, its archive state and the storage views. */\nfunction invalidateArchive(queryClient: QueryClient) {\n return Promise.all([\n queryClient.invalidateQueries({ queryKey: arbiQueryKeys.workspaces() }),\n queryClient.invalidateQueries({ queryKey: arbiQueryKeys.workspaceArchive() }),\n queryClient.invalidateQueries({ queryKey: arbiQueryKeys.storage() }),\n ])\n}\n\n/** Archive a workspace (its owner or its project's owner). */\nexport function useArchiveWorkspace() {\n const arbi = useArbi()\n const queryClient = useQueryClient()\n return useMutation({\n mutationFn: (workspaceId: string) => arbi.workspaces.archive(workspaceId),\n onSuccess: () => invalidateArchive(queryClient),\n })\n}\n\n/** Start unarchiving a workspace; refused up front when the AI budget cannot cover the re-index. */\nexport function useUnarchiveWorkspace() {\n const arbi = useArbi()\n const queryClient = useQueryClient()\n return useMutation({\n mutationFn: (workspaceId: string) => arbi.workspaces.unarchive(workspaceId),\n onSuccess: () => invalidateArchive(queryClient),\n })\n}\n\n/**\n * Keep the workspace list fresh while any workspace in it is archiving or restoring, so its card\n * shows the progress and opens again as soon as it is back.\n */\nexport function useArchiveProgressPolling(\n workspaces: ReadonlyArray<{ archive?: { status?: string | null } | null }> | undefined\n) {\n const queryClient = useQueryClient()\n const moving = (workspaces ?? []).some((w) => isArchiveMoving(w.archive?.status))\n useEffect(() => {\n if (!moving) return\n const timer = window.setInterval(() => {\n void queryClient.invalidateQueries({ queryKey: arbiQueryKeys.workspaces() })\n }, ARCHIVE_POLL_MS)\n return () => window.clearInterval(timer)\n }, [moving, queryClient])\n}\n","/**\n * Workspace facts (notes): a workspace's list, filtered for the timeline or by tag, the writes\n * (create, batch, patch, delete) and the search. List, create and search name their workspace (the\n * one given, else the open one, captured when they are sent); patch and delete act in the fact's\n * own workspace. Every write refreshes every cached list.\n *\n * Requires an `ArbiHost` (with an `arbi`) and a React Query client above it.\n */\n\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'\nimport type {\n CreateFactRequest,\n CreateFactsRequest,\n FactResponse,\n FactSearchRequest,\n FactSearchResponse,\n ListFactsOptions,\n UpdateFactRequest,\n} from '@arbidocs/sdk/browser'\nimport { useArbi } from './useArbi'\nimport { arbiQueryKeys } from './hooks'\n\n/** The workspace a fact call names: the one given, else the one open now ('' when none is). */\nfunction factWorkspace(arbi: ReturnType<typeof useArbi>, workspaceId?: string | null): string {\n return workspaceId || (arbi.hasWorkspace ? arbi.getWorkspaceId() : '')\n}\n\n/** What a list asks for: the timeline range, or the notes carrying tags or citing a document. */\nexport type FactListFilter = Pick<\n ListFactsOptions,\n 'from' | 'to' | 'datedOnly' | 'tagExtIds' | 'docExtId'\n>\n\n/**\n * The facts of `workspaceId` (default: the open one), newest first, or the filtered ones\n * (`datedOnly` / a range: the timeline, by date; `tagExtIds`: the notes carrying all those tags).\n */\nexport function useFacts(\n workspaceId?: string | null,\n options?: FactListFilter & { enabled?: boolean }\n) {\n const arbi = useArbi()\n const { enabled = true, ...filter } = options ?? {}\n const workspace = factWorkspace(arbi, workspaceId)\n return useQuery({\n queryKey: arbiQueryKeys.factList(workspace, filter),\n // The request names the workspace, so a switch while it runs cannot answer for another.\n queryFn: (): Promise<FactResponse[]> => arbi.facts.list({ ...filter, workspaceId: workspace }),\n enabled: enabled && !!workspace && arbi.hasWorkspace,\n staleTime: 30_000,\n })\n}\n\n/** Refresh every cached fact list after a write. */\nfunction useRefreshFacts() {\n const qc = useQueryClient()\n return () => qc.invalidateQueries({ queryKey: arbiQueryKeys.allFacts() })\n}\n\n/**\n * Add a fact (by hand it is confirmed: typing it is the vouch) to `workspaceId` (the message's or\n * the page's), else to the workspace open when it is sent.\n */\nexport function useCreateFact(workspaceId?: string | null) {\n const arbi = useArbi()\n const refresh = useRefreshFacts()\n return useMutation({\n mutationFn: (body: CreateFactRequest) =>\n arbi.facts.create(body, { workspaceId: factWorkspace(arbi, workspaceId) || undefined }),\n onSuccess: refresh,\n })\n}\n\n/**\n * Add several facts in one all-or-nothing request (an imported chronology, say) to `workspaceId`,\n * else to the workspace open when it is sent.\n */\nexport function useCreateFacts(workspaceId?: string | null) {\n const arbi = useArbi()\n const refresh = useRefreshFacts()\n return useMutation({\n mutationFn: (body: CreateFactsRequest) =>\n arbi.facts.createBatch(body, { workspaceId: factWorkspace(arbi, workspaceId) || undefined }),\n onSuccess: refresh,\n })\n}\n\n/**\n * Patch a fact. A text edit replaces the fact (the old one is kept as history); `shared` and\n * `confirmed` change in place.\n */\nexport function useUpdateFact() {\n const arbi = useArbi()\n const refresh = useRefreshFacts()\n return useMutation({\n mutationFn: ({ factId, patch }: { factId: string; patch: UpdateFactRequest }) =>\n arbi.facts.update(factId, patch),\n onSuccess: refresh,\n })\n}\n\n/** Delete a fact (only where the server allows it: a refused delete fails with its reason). */\nexport function useDeleteFact() {\n const arbi = useArbi()\n const refresh = useRefreshFacts()\n return useMutation({\n mutationFn: (factId: string) => arbi.facts.delete(factId),\n onSuccess: refresh,\n })\n}\n\n/**\n * Search the facts of `workspaceId` (default: the open one), hybrid by default, as the agent's fact\n * recall does. The workspace is captured when the search is sent and named on the request.\n */\nexport function useSearchFacts(workspaceId?: string | null) {\n const arbi = useArbi()\n return useMutation({\n mutationFn: (body: FactSearchRequest): Promise<FactSearchResponse> =>\n arbi.facts.search(body, { workspaceId: factWorkspace(arbi, workspaceId) || undefined }),\n })\n}\n","/**\n * The facts Smart Search: one search of a workspace's facts (never documents), with keyword and\n * meaning recall, as the agent's `search_facts` tool does. It holds the query being typed, the\n * query last searched and its hits. They are kept in the session (`views.transient`), so leaving\n * the view and coming back shows the same search, as the documents' search does.\n *\n * Requires an `ArbiHost` (with an `arbi`) and a React Query client above it.\n */\nimport { useCallback, useRef } from 'react'\nimport type { FactSearchRequest, FactSearchResponse } from '@arbidocs/sdk/browser'\nimport { useArbi } from './useArbi'\nimport { useSearchFacts } from './facts'\nimport { useArbiSessionStore, useTransientView } from './session/session-hooks'\n\n/** One hit of a facts search: a fact and its recall score. */\nexport type FactSearchHit = FactSearchResponse['facts'][number]\n\n/** The session key the search is kept under (`views.transient`). Drop it to clear the search. */\nexport const FACTS_SEARCH_VIEW = 'facts.search'\n\n/** The search kept for the session. `hits === null`: nothing searched yet. */\nexport interface FactsSearchState {\n query: string\n lastQuery: string\n hits: FactSearchHit[] | null\n /** The workspace searched (null: none searched yet). */\n workspaceId: string | null\n}\n\nexport interface UseFactsSearchOptions {\n /** The workspace searched (default: the open one). */\n workspaceId?: string | null\n /** How it recalls (default `hybrid`: keyword and meaning). */\n mode?: FactSearchRequest['search_mode']\n /** The most hits it returns (default 30). */\n limit?: number\n}\n\nexport interface FactsSearch {\n /** The query in the box. */\n query: string\n setQuery: (query: string) => void\n /** The query last searched. */\n lastQuery: string\n /** Its hits, best first (null: nothing searched yet). */\n hits: FactSearchHit[] | null\n isSearching: boolean\n /**\n * Search the query in the box (a blank one does nothing). Rejects when the search fails. A search\n * overtaken by a newer one is dropped quietly; the request names its workspace, so a switch while\n * it runs cannot answer it from another.\n */\n search: () => Promise<void>\n /** Back to nothing searched, with an empty box. */\n clear: () => void\n}\n\nconst EMPTY: FactsSearchState = { query: '', lastQuery: '', hits: null, workspaceId: null }\n\n/** Search a workspace's facts and keep the search for the session. */\nexport function useFactsSearch(options: UseFactsSearchOptions = {}): FactsSearch {\n const { mode = 'hybrid', limit = 30 } = options\n const arbi = useArbi()\n const session = useArbiSessionStore()\n const workspaceId = options.workspaceId ?? (arbi.hasWorkspace ? arbi.getWorkspaceId() : null)\n const [kept, setKept] = useTransientView<FactsSearchState>(FACTS_SEARCH_VIEW, EMPTY)\n const searchFacts = useSearchFacts(workspaceId)\n const run = useRef(0)\n\n // Another workspace's search is not this one's.\n const foreign = !!kept.workspaceId && !!workspaceId && kept.workspaceId !== workspaceId\n const state = foreign ? EMPTY : kept\n\n /** Merge into the search as it is now (an answer lands after other changes). */\n const patch = useCallback(\n (next: Partial<FactsSearchState>) => {\n const current = session.getState().views.transient[FACTS_SEARCH_VIEW] as\n FactsSearchState | undefined\n const base = current && current.workspaceId === workspaceId ? current : EMPTY\n setKept({ ...base, ...next, workspaceId })\n },\n [session, setKept, workspaceId]\n )\n\n const query = state.query\n const search = useCallback(async () => {\n const q = query.trim()\n if (!q) return\n const mine = ++run.current\n try {\n const res = await searchFacts.mutateAsync({ query: q, search_mode: mode, limit })\n if (run.current !== mine) return\n patch({ hits: res.facts, lastQuery: q })\n } catch (error) {\n if (run.current !== mine) return\n throw error\n }\n }, [query, searchFacts, mode, limit, patch])\n\n const clear = useCallback(() => {\n run.current++\n patch({ query: '', hits: null })\n }, [patch])\n\n return {\n query,\n setQuery: useCallback((q: string) => patch({ query: q }), [patch]),\n lastQuery: state.lastQuery,\n hits: state.hits,\n isSearching: searchFacts.isPending,\n search,\n clear,\n }\n}\n","/**\n * Databases: user-defined tables of the open workspace (a client database, billing records),\n * encrypted under the workspace key like facts. The list also carries databases of public\n * workspaces, which come back `editable: false` (read here, edited from their own workspace).\n *\n * Reads are keyed by the one key factory (`arbiQueryKeys.database*`); every write keeps those\n * entries current.\n */\n\nimport { useCallback } from 'react'\nimport { useMutation, useQuery, useQueryClient, type QueryClient } from '@tanstack/react-query'\nimport type {\n Database,\n DatabaseColumnWrite,\n DatabaseImportResult,\n DatabaseRow,\n DatabaseRowPage,\n} from '@arbidocs/sdk/browser'\nimport type { components } from '@arbidocs/client'\nimport { useArbi } from './useArbi'\nimport { arbiQueryKeys } from './query-keys'\n\nexport type { Database, DatabaseColumnWrite, DatabaseImportResult, DatabaseRow, DatabaseRowPage }\nexport type { DatabaseColumn } from '@arbidocs/sdk/browser'\n\ntype DatabaseCreate = components['schemas']['DatabaseCreate']\ntype DatabaseUpdate = components['schemas']['DatabaseUpdate']\ntype DatabaseRowValues = components['schemas']['DatabaseRowWrite']['values']\nexport type DatabaseAggregateRequest = components['schemas']['DatabaseAggregateRequest']\nexport type DatabaseAggregateResult = components['schemas']['DatabaseAggregateResult']\n\n/** The most rows the grid loads at once (the API's page limit). Search runs on the server. */\nexport const DATABASE_ROWS_PAGE = 1000\n\n/** The most rows a relation cell's picker lists for one search. */\nexport const DATABASE_RELATION_PICK_LIMIT = 50\n\n/**\n * After a relation cell changes, other databases' rows can have changed with it (the paired column\n * of a two-way relation, lookups and rollups reading through it): refetch them when next shown.\n * The edited database's own rows are left alone (the grid already holds the server's answer)\n * unless the relation links it to itself.\n */\nfunction invalidateRelatedRows(queryClient: QueryClient, databaseId: string, includeSelf: boolean) {\n return queryClient.invalidateQueries({\n queryKey: arbiQueryKeys.databaseRows(),\n // ['arbi', 'databases', 'rows', workspaceId, databaseId, params]\n predicate: (query) => includeSelf || query.queryKey[4] !== databaseId,\n })\n}\n\n/** Whether a cached key (`['arbi', 'databases', kind, workspaceId, …]`) is this workspace's. */\nfunction sameWorkspace(queryKey: readonly unknown[] | undefined, workspaceId: string): boolean {\n return !!queryKey && queryKey[3] === workspaceId\n}\n\nfunction useInvalidate() {\n const queryClient = useQueryClient()\n return {\n list: () => queryClient.invalidateQueries({ queryKey: arbiQueryKeys.databaseList() }),\n rows: () =>\n Promise.all([\n queryClient.invalidateQueries({ queryKey: arbiQueryKeys.databaseRows() }),\n queryClient.invalidateQueries({ queryKey: arbiQueryKeys.databaseAggregate() }),\n ]),\n all: () => queryClient.invalidateQueries({ queryKey: arbiQueryKeys.databases() }),\n }\n}\n\n/** The open workspace's id, or '' with none open. */\nfunction openWorkspaceId(arbi: ReturnType<typeof useArbi>): string {\n return arbi.hasWorkspace ? arbi.getWorkspaceId() : ''\n}\n\n/**\n * The open workspace's databases, then those of public workspaces (read-only here). Kept per\n * workspace, and read only while that workspace stays open on the server (the list is the open\n * workspace's there): a read that crosses a switch is dropped, never cached as the other's.\n */\nexport function useDatabases() {\n const arbi = useArbi()\n const workspaceId = openWorkspaceId(arbi)\n return useQuery({\n queryKey: arbiQueryKeys.databaseList(workspaceId),\n queryFn: () => arbi.readInWorkspace(workspaceId, () => arbi.databases.list()),\n enabled: !!workspaceId,\n staleTime: 1000 * 30,\n })\n}\n\n/** `workspaceId`: the database's own workspace (a by-id read acts there), else the open one. */\nexport function useDatabase(databaseId: string | null, options?: { workspaceId?: string }) {\n const arbi = useArbi()\n const workspaceId = options?.workspaceId ?? openWorkspaceId(arbi)\n return useQuery({\n queryKey: arbiQueryKeys.database(workspaceId, databaseId ?? ''),\n queryFn: () => arbi.databases.get(databaseId as string),\n enabled: !!workspaceId && Boolean(databaseId),\n staleTime: 1000 * 30,\n })\n}\n\n/** A database's rows: searched (any cell) on the server, the first `DATABASE_ROWS_PAGE`. */\nexport function useDatabaseRows(\n databaseId: string | null,\n q: string,\n options?: { workspaceId?: string }\n) {\n const arbi = useArbi()\n const workspaceId = options?.workspaceId ?? openWorkspaceId(arbi)\n const query = { q: q.trim() || undefined, limit: DATABASE_ROWS_PAGE }\n return useQuery({\n queryKey: arbiQueryKeys.databaseRows(workspaceId, databaseId ?? '', query),\n queryFn: () => arbi.databases.rows(databaseId as string, query),\n enabled: !!workspaceId && Boolean(databaseId),\n staleTime: 1000 * 15,\n // What was shown stays while the next search loads, never another workspace's rows.\n placeholderData: (previous, previousQuery) =>\n sameWorkspace(previousQuery?.queryKey, workspaceId) ? previous : undefined,\n })\n}\n\n/**\n * A database's rows grouped and measured on the server (over every row): the labels and series a\n * chart or a metric tile draws. Row writes here refresh it.\n */\nexport function useDatabaseAggregate(\n databaseId: string | null,\n request: Partial<DatabaseAggregateRequest>,\n options?: { enabled?: boolean; workspaceId?: string }\n) {\n const arbi = useArbi()\n const workspaceId = options?.workspaceId ?? openWorkspaceId(arbi)\n return useQuery({\n queryKey: arbiQueryKeys.databaseAggregate(workspaceId, databaseId ?? '', request),\n queryFn: () => arbi.databases.aggregate(databaseId as string, request),\n enabled: (options?.enabled ?? true) && !!workspaceId && Boolean(databaseId),\n staleTime: 1000 * 15,\n placeholderData: (previous, previousQuery) =>\n sameWorkspace(previousQuery?.queryKey, workspaceId) ? previous : undefined,\n })\n}\n\n/**\n * Search a database's rows (any cell, on the server) for a relation cell's picker. Read once per\n * search rather than cached: the picker debounces its typing.\n */\nexport function useSearchDatabaseRows() {\n const arbi = useArbi()\n return useCallback(\n (databaseId: string, q: string): Promise<DatabaseRow[]> =>\n arbi.databases\n .rows(databaseId, { q: q.trim() || undefined, limit: DATABASE_RELATION_PICK_LIMIT })\n .then((page) => page.rows),\n [arbi]\n )\n}\n\nexport function useCreateDatabase() {\n const arbi = useArbi()\n const invalidate = useInvalidate()\n return useMutation({\n mutationFn: (body: DatabaseCreate) => arbi.databases.create(body),\n onSuccess: () => invalidate.list(),\n })\n}\n\n/** Rename, describe, or change columns (`columns` is the full new list). */\nexport function useUpdateDatabase() {\n const arbi = useArbi()\n const invalidate = useInvalidate()\n return useMutation({\n mutationFn: ({ databaseId, patch }: { databaseId: string; patch: DatabaseUpdate }) =>\n arbi.databases.update(databaseId, patch),\n onSuccess: () => invalidate.all(),\n })\n}\n\nexport function useDeleteDatabase() {\n const arbi = useArbi()\n const invalidate = useInvalidate()\n return useMutation({\n mutationFn: (databaseId: string) => arbi.databases.delete(databaseId),\n onSuccess: () => invalidate.list(),\n })\n}\n\nexport function useAddDatabaseRows() {\n const arbi = useArbi()\n const invalidate = useInvalidate()\n return useMutation({\n mutationFn: ({\n databaseId,\n rows,\n }: {\n databaseId: string\n rows: { values: DatabaseRowValues }[]\n }) => arbi.databases.addRows(databaseId, rows),\n onSuccess: () => Promise.all([invalidate.rows(), invalidate.list()]),\n })\n}\n\n/**\n * Change cells of one row (`null` empties a cell). The server's (normalised) row replaces the row in\n * every cached page of rows. Other databases are marked stale for relation/lookups/rollups;\n * the edited database is re-read for a self-relation or unknown column metadata. Failed edits\n * re-read rows to reconcile.\n */\nexport function useUpdateDatabaseRow() {\n const arbi = useArbi()\n const queryClient = useQueryClient()\n const workspaceId = openWorkspaceId(arbi)\n return useMutation({\n mutationFn: ({\n databaseId,\n rowId,\n values,\n }: {\n databaseId: string\n rowId: string\n values: DatabaseRowValues\n }) => arbi.databases.updateRow(databaseId, rowId, values),\n onSuccess: (saved, { databaseId, values }) => {\n queryClient.setQueriesData<DatabaseRowPage>(\n { queryKey: arbiQueryKeys.databaseRows() },\n (page) =>\n page && { ...page, rows: page.rows.map((row) => (row.id === saved.id ? saved : row)) }\n )\n const database = queryClient.getQueryData<Database>(\n arbiQueryKeys.database(workspaceId, databaseId)\n )\n const selfLinked =\n !database?.columns ||\n database.columns.some(\n (column) =>\n column.id in (values ?? {}) &&\n column.type === 'relation' &&\n column.relation?.database_id === databaseId\n )\n void invalidateRelatedRows(queryClient, databaseId, selfLinked)\n // Every chart over a database can read through the edited cell (relations, lookups).\n void queryClient.invalidateQueries({ queryKey: arbiQueryKeys.databaseAggregate() })\n },\n onError: () => {\n void queryClient.invalidateQueries({ queryKey: arbiQueryKeys.databaseRows() })\n },\n })\n}\n\nexport function useDeleteDatabaseRows() {\n const arbi = useArbi()\n const invalidate = useInvalidate()\n return useMutation({\n mutationFn: ({ databaseId, ids }: { databaseId: string; ids: string[] }) =>\n arbi.databases.deleteRows(databaseId, ids),\n onSuccess: () => Promise.all([invalidate.rows(), invalidate.list()]),\n })\n}\n\n/** Create a database from a .csv / .xlsx file (column types are inferred). */\nexport function useImportDatabase() {\n const arbi = useArbi()\n const invalidate = useInvalidate()\n return useMutation({\n mutationFn: ({ file, name }: { file: File; name?: string }) =>\n arbi.databases.import(file, name),\n onSuccess: () => invalidate.list(),\n })\n}\n\n/** Append a spreadsheet's rows; headers match column names, unknown ones become new columns. */\nexport function useImportDatabaseRows() {\n const arbi = useArbi()\n const invalidate = useInvalidate()\n return useMutation({\n mutationFn: ({ databaseId, file }: { databaseId: string; file: File }) =>\n arbi.databases.importRows(databaseId, file),\n onSuccess: () => invalidate.all(),\n })\n}\n\n/** Download a database as .xlsx or .csv. */\nexport function useExportDatabase() {\n const arbi = useArbi()\n return useCallback(\n (databaseId: string, format: 'csv' | 'xlsx') => arbi.databases.export(databaseId, format),\n [arbi]\n )\n}\n","/**\n * Saved table views in the user settings (`tableviews`): one array holding the views of every\n * table, keyed by workspace and table. A view without `table` belongs to the workspace's documents\n * table; one with `table` to that database (`dbs-…`). The grids write them (blocks' `useTableViews`);\n * a chart over a database reads a view's columns.\n */\nimport type { components } from '@arbidocs/client'\n\nexport type TableView = components['schemas']['TableView']\n\n/** The table a view belongs to: a database id, or `null` for the documents table. */\nexport type TableViewTable = string | null\n\n/** Whether `view` is one of `table`'s views in the workspace. */\nexport function isTableViewOf(view: TableView, workspaceId: string, table: TableViewTable) {\n return view.workspace === workspaceId && (view.table ?? null) === table\n}\n\n/** The views of one table, one per name (the last one stored wins). */\nexport function viewsOfTable(\n all: readonly TableView[] | null | undefined,\n workspaceId: string | null | undefined,\n table: TableViewTable\n): TableView[] {\n if (!workspaceId) return []\n const byName = new Map<string, TableView>()\n for (const view of all ?? []) {\n if (isTableViewOf(view, workspaceId, table)) byName.set(view.name, view)\n }\n return [...byName.values()]\n}\n","/**\n * Datasets: the one shape every chart and dashboard reads, whatever the data comes from.\n *\n * Three layers, each knowing only the one below it:\n * 1. A `DataSource` adapter (AI usage, documents, threads, projects, a database, later an external\n * feed) exposes its data as a normalized `Dataset`: typed fields and plain rows. Filtering,\n * grouping and aggregation happen here (`aggregateDataset`, or on the server where the backend\n * can, as a database does), never in a chart.\n * 2. A `ChartSpec` (inside a `PanelSpec`, inside a `DashboardSpec`) says what to show in terms of\n * field ids only: the chart type, x / series / y fields, the aggregate, sort and limit. It is\n * plain JSON, saved in dashboards and studio pages.\n * 3. A renderer (`@arbidocs/blocks/dashboards`) maps a spec plus the aggregated dataset onto the\n * drawing component. No renderer type appears here, so the renderer stays swappable.\n */\n\n/** A field's value type. Dates are ISO strings (`2026-06-12` or a full timestamp). */\nexport type DatasetFieldType = 'string' | 'number' | 'date' | 'boolean'\n\n/** One column of a dataset. */\nexport interface DatasetField {\n /** Stable id: what specs and rows use. */\n id: string\n /** What people read (a column name, \"Status\"). */\n label: string\n type: DatasetFieldType\n /**\n * The unit of a number field, which picks its formatting: `gbp` (£), `bytes`, `tokens`, or any\n * suffix (`\"MB\"`, `\"%\"`).\n */\n unit?: string\n /** The values a string field takes, when known (a select column's options), for a filter picker. */\n options?: readonly string[]\n /** A string field whose cell holds several values (tags, linked rows): a row counts in each. */\n multiple?: boolean\n}\n\n/** A cell: a scalar, `null` when empty, or a list for a `multiple` field. */\nexport type DatasetValue = string | number | boolean | null | readonly string[]\n\n/** One row, keyed by field id. */\nexport type DatasetRow = Readonly<Record<string, DatasetValue | undefined>>\n\n/** A normalized dataset: typed fields and the rows. */\nexport interface Dataset {\n fields: readonly DatasetField[]\n rows: readonly DatasetRow[]\n /** Rows matched before grouping (after filters). */\n totalRows?: number\n /** More groups existed than the query's `limit`. */\n truncated?: boolean\n}\n\n/** How a date field is grouped. Keys: `2026-06-12`, `2026-W24`, `2026-06`, `2026-Q2`, `2026`. */\nexport type TimeBucket = 'day' | 'week' | 'month' | 'quarter' | 'year'\n\nexport type AggregateOp = 'count' | 'sum' | 'avg' | 'min' | 'max'\n\nexport type FilterOp =\n 'eq' | 'neq' | 'contains' | 'gt' | 'gte' | 'lt' | 'lte' | 'empty' | 'not_empty'\n\n/** Keep rows whose `field` satisfies `op value` (compared in the field's type). */\nexport interface DatasetFilter {\n field: string\n op: FilterOp\n value?: string | number | boolean | null\n}\n\n/** How the groups are ordered: by label (dates: chronological), or by value. */\nexport type DatasetSort = 'label' | 'value-desc' | 'value-asc'\n\n/** How records are ordered: by a field (empty cells last). */\nexport interface DatasetOrder {\n field: string\n /** Default `asc`. */\n direction?: 'asc' | 'desc'\n}\n\n/**\n * What to read of a source. Grouped (the default): the (filtered) rows grouped and each group\n * measured, a dataset in long form with the fields {@link AGGREGATE_FIELDS}, one row per group (and\n * series). With `records`: the matching rows themselves, ordered by `orderBy` and cut at `limit`.\n */\nexport interface DatasetQuery {\n /** List the matching records instead of grouping them (`groupBy`, `splitBy`, `measure` unused). */\n records?: boolean\n /** The order of the records. */\n orderBy?: DatasetOrder\n filters?: readonly DatasetFilter[]\n /** The field whose values (or date buckets) are the groups. Absent: one group, \"All\". */\n groupBy?: string\n /** The bucket of a date `groupBy` / `splitBy`. Default `month`. */\n bucket?: TimeBucket\n /** A second field: one series per value (a stacked or multi-line chart). */\n splitBy?: string\n /** Default: count rows. `count` with a `field` counts the rows where it is not empty. */\n measure?: { op: AggregateOp; field?: string }\n /** Default: dates chronological, others by value, largest first. */\n sort?: DatasetSort\n /** Most groups kept (by value), or records listed. Default 50 groups; every record. */\n limit?: number\n}\n\n/** The field ids of an aggregated dataset. */\nexport const AGGREGATE_FIELDS = {\n /** The group's label (\"Open\", \"2026-06\"). */\n group: 'group',\n /** The group's key as grouped (a date bucket, an id), for ordering and links. */\n key: 'key',\n /** The series' label (only with `splitBy`). */\n series: 'series',\n /** The measured value; `null` when the group has no value to measure. */\n value: 'value',\n} as const\n\n/** A dataset (or a source's fields) as a hook reads it. */\nexport interface DatasetState {\n dataset: Dataset | undefined\n isLoading: boolean\n error: unknown\n}\n\nexport interface DataSourceFieldsState {\n fields: readonly DatasetField[]\n isLoading: boolean\n error: unknown\n}\n\n/** A source's parameters as saved in a panel (a database id, a period). */\nexport type DataSourceParams = Readonly<\n Record<string, string | number | boolean | null | undefined>\n>\n\n/** A choice for a parameter (an option of a select). */\nexport interface DataSourceOption {\n value: string\n label: string\n /** Other parameters set with this choice (a database's workspace, so a panel reads it anywhere). */\n params?: DataSourceParams\n}\n\n/** A parameter the panel editor asks for, before the source's fields are known. */\nexport interface DataSourceParam {\n id: string\n label: string\n /** Absent: the parameter may be left empty. */\n required?: boolean\n /** Shown when nothing is chosen (\"All columns\"). */\n placeholder?: string\n /** The choices, read live (databases of the open workspace; a database's saved views). */\n useOptions: (params: DataSourceParams) => {\n options: readonly DataSourceOption[]\n isLoading: boolean\n }\n}\n\n/**\n * A data source adapter: where a dataset comes from.\n *\n * `useFields` and `useDataset` are hooks. A caller renders them from a component keyed by the\n * source id, so switching source mounts afresh (the hooks differ between sources).\n *\n * Extension point: an external source (an HTTP/JSON API, a CSV feed, a warehouse) is one more\n * adapter. It reads its rows however it likes (its own `useQuery`) and returns them as a `Dataset`;\n * `defineRowsSource` aggregates them for it. A host lists it in `<ArbiHost config={{ dashboards:\n * { sources } }}>` and every editor, panel and studio block offers it. Fetching third-party URLs\n * from the browser is the host's decision (CORS, credentials, what a shared dashboard may reach),\n * so none is built in; data to chart today is imported into a database (CSV / spreadsheet import).\n */\nexport interface DataSource {\n id: string\n label: string\n description?: string\n /** `workspace`: it reads the open workspace's data (documents, threads…), so it shows nothing until\n * one is open; a function decides from the panel's parameters (a database panel that does not name\n * its workspace). Absent: it is the person's own or names what it reads (AI usage). */\n scope?: 'workspace' | ((params: DataSourceParams) => 'workspace' | undefined)\n params?: readonly DataSourceParam[]\n /** The fields a panel can use, given the parameters. */\n useFields: (params: DataSourceParams) => DataSourceFieldsState\n /**\n * The dataset: grouped and measured (long form with {@link AGGREGATE_FIELDS}), or the records\n * (`query.records`), filtered either way.\n */\n useDataset: (\n params: DataSourceParams,\n query: DatasetQuery,\n options?: { enabled?: boolean }\n ) => DatasetState\n}\n\n// ── Specs: what a panel shows (plain JSON) ───────────────────────────────────────────────────\n\n/** How a panel draws its data. `metric` is one number; `table` a table of rows or groups. */\nexport type ChartType = 'metric' | 'bar' | 'line' | 'area' | 'pie' | 'donut' | 'table'\n\n/** What to show, in terms of the dataset's field ids. Serialisable. */\nexport interface ChartSpec {\n type: ChartType\n /** The category or date field along the x axis (pie slices; table groups). */\n x?: string\n /** The bucket of a date `x`. Default `month`. */\n bucket?: TimeBucket\n /** A field whose values become the series (stacked bars or areas, several lines). */\n series?: string\n /** The number field the aggregate reads (absent: rows are counted). */\n y?: string\n /** Default `count`. */\n aggregate?: AggregateOp\n sort?: DatasetSort\n limit?: number\n /** Stack the series (bar, area). */\n stacked?: boolean\n filters?: readonly DatasetFilter[]\n /** A table of records (no aggregate): the fields shown, in order. Absent: every field. */\n columns?: readonly string[]\n /** A table of records: their order. */\n orderBy?: DatasetOrder\n}\n\n/** The source a panel reads, by registry id, with its parameters. */\nexport interface DataSourceRef {\n id: string\n params?: DataSourceParams\n}\n\n/** One panel of a dashboard. */\nexport interface PanelSpec {\n id: string\n title: string\n description?: string\n source: DataSourceRef\n chart: ChartSpec\n /** Columns of the 12-column grid it spans on a wide screen (it is full width on a phone). */\n width?: number\n}\n\n/** A dashboard: a titled grid of panels. Plain JSON (`version` for later migrations). */\nexport interface DashboardSpec {\n version: 1\n title: string\n description?: string\n panels: readonly PanelSpec[]\n}\n","/**\n * Grouping and measuring a dataset in the browser, for sources whose rows are already loaded\n * (documents, threads, projects, AI usage). The rules are the server's database aggregation\n * (`POST /v1/databases/{id}/aggregate`), so a panel reads the same whichever side measured it:\n * empty cells group as \"(empty)\", a multi-valued cell counts in each of its values' groups, date\n * groups run chronologically and others by value, at most {@link MAX_SERIES} series.\n */\nimport {\n AGGREGATE_FIELDS,\n type AggregateOp,\n type Dataset,\n type DatasetField,\n type DatasetFilter,\n type DatasetQuery,\n type DatasetRow,\n type DatasetValue,\n type TimeBucket,\n} from './types'\n\n/** The label of the group of empty cells. */\nexport const EMPTY_GROUP_LABEL = '(empty)'\n\n/** The most series a split keeps (the largest). */\nexport const MAX_SERIES = 12\n\nconst DEFAULT_LIMIT = 50\n\nconst pad = (n: number) => String(n).padStart(2, '0')\n\n/** A date value as a UTC day, or null. */\nfunction asDay(value: DatasetValue | undefined): Date | null {\n if (typeof value !== 'string' || value.length < 10) return null\n const day = new Date(`${value.slice(0, 10)}T00:00:00Z`)\n return Number.isNaN(day.getTime()) ? null : day\n}\n\n/** ISO 8601 week-numbering year and week of a UTC day. */\nfunction isoWeek(day: Date): [number, number] {\n const d = new Date(day)\n const weekday = d.getUTCDay() || 7\n d.setUTCDate(d.getUTCDate() + 4 - weekday)\n const yearStart = Date.UTC(d.getUTCFullYear(), 0, 1)\n return [d.getUTCFullYear(), Math.ceil(((d.getTime() - yearStart) / 86_400_000 + 1) / 7)]\n}\n\n/** The bucket key of a date (`2026-06-12`, `2026-W24`, `2026-06`, `2026-Q2`, `2026`), or null. */\nexport function bucketOf(value: DatasetValue | undefined, bucket: TimeBucket): string | null {\n const day = asDay(value)\n if (!day) return null\n const y = day.getUTCFullYear()\n const m = day.getUTCMonth() + 1\n switch (bucket) {\n case 'day':\n return `${y}-${pad(m)}-${pad(day.getUTCDate())}`\n case 'week': {\n const [wy, w] = isoWeek(day)\n return `${wy}-W${pad(w)}`\n }\n case 'quarter':\n return `${y}-Q${Math.floor((m - 1) / 3) + 1}`\n case 'year':\n return String(y)\n default:\n return `${y}-${pad(m)}`\n }\n}\n\n/** The first day of a bucket key, or null. */\nfunction bucketStart(key: string, bucket: TimeBucket): Date | null {\n const parts = key.match(/^(\\d{4})(?:-(W|Q)?(\\d{1,2}))?(?:-(\\d{2}))?$/)\n if (!parts) return null\n const year = Number(parts[1])\n const n = Number(parts[3] ?? 1)\n switch (bucket) {\n case 'day':\n return asDay(key)\n case 'week': {\n // Monday of ISO week 1 is the Monday on or before 4 January.\n const jan4 = new Date(Date.UTC(year, 0, 4))\n const monday = new Date(jan4)\n monday.setUTCDate(jan4.getUTCDate() - ((jan4.getUTCDay() || 7) - 1) + (n - 1) * 7)\n return monday\n }\n case 'quarter':\n return new Date(Date.UTC(year, (n - 1) * 3, 1))\n case 'year':\n return new Date(Date.UTC(year, 0, 1))\n default:\n return new Date(Date.UTC(year, n - 1, 1))\n }\n}\n\nfunction nextBucket(day: Date, bucket: TimeBucket): Date {\n const d = new Date(day)\n if (bucket === 'day') d.setUTCDate(d.getUTCDate() + 1)\n else if (bucket === 'week') d.setUTCDate(d.getUTCDate() + 7)\n else if (bucket === 'month') d.setUTCMonth(d.getUTCMonth() + 1)\n else if (bucket === 'quarter') d.setUTCMonth(d.getUTCMonth() + 3)\n else d.setUTCFullYear(d.getUTCFullYear() + 1)\n return d\n}\n\n/** Every bucket key from `first` to `last` (at most `max`; null when the keys are not buckets). */\nexport function bucketRange(\n first: string,\n last: string,\n bucket: TimeBucket,\n max = 500\n): string[] | null {\n const start = bucketStart(first, bucket)\n const end = bucketStart(last, bucket)\n if (!start || !end || start > end) return null\n const keys: string[] = []\n for (let d = start; d <= end && keys.length <= max; d = nextBucket(d, bucket)) {\n keys.push(bucketOf(d.toISOString(), bucket) as string)\n }\n return keys.length > max ? null : keys\n}\n\nconst isEmpty = (value: DatasetValue | undefined) =>\n value === null || value === undefined || value === '' || (Array.isArray(value) && !value.length)\n\n/** The groups a cell puts its row in: one, or one per value of a list; `''` when empty. */\nfunction groupKeys(\n value: DatasetValue | undefined,\n field: DatasetField,\n bucket: TimeBucket\n): string[] {\n if (isEmpty(value)) return ['']\n if (Array.isArray(value)) {\n return [...new Set(value.map((v) => groupKeys(v, field, bucket)[0]))]\n }\n if (field.type === 'date') return [bucketOf(value as DatasetValue, bucket) ?? '']\n if (typeof value === 'boolean') return [value ? 'Yes' : 'No']\n return [String(value)]\n}\n\nconst lower = (v: unknown) => String(v).toLowerCase()\n\nfunction compare(value: DatasetValue | undefined, filter: DatasetFilter, field: DatasetField) {\n const empty = isEmpty(value)\n if (filter.op === 'empty') return empty\n if (filter.op === 'not_empty') return !empty\n if (Array.isArray(value)) {\n const values = value as readonly string[]\n if (filter.op === 'contains')\n return values.some((v) => lower(v).includes(lower(filter.value ?? '')))\n if (filter.op === 'eq' || filter.op === 'neq') {\n const hit = values.some((v) => lower(v) === lower(filter.value))\n return filter.op === 'eq' ? hit : !hit\n }\n return false\n }\n const same =\n typeof value === 'string' ? lower(value) === lower(filter.value) : value === filter.value\n if (filter.op === 'eq') return same\n if (filter.op === 'neq') return !same\n if (filter.op === 'contains') return !empty && lower(value).includes(lower(filter.value ?? ''))\n if (empty || filter.value === null || filter.value === undefined) return false\n const [a, b] =\n field.type === 'number'\n ? [Number(value), Number(filter.value)]\n : [String(value).slice(0, 19), String(filter.value).slice(0, 19)]\n return { gt: a > b, gte: a >= b, lt: a < b, lte: a <= b }[filter.op]\n}\n\n/** The records of a query: those that pass its filters, in its order, at most its limit. */\nexport function recordsOf(dataset: Dataset, query: DatasetQuery): Dataset {\n const rows = filterRows(dataset.rows, dataset.fields, query.filters)\n const order = query.orderBy\n const field = order && dataset.fields.find((f) => f.id === order.field)\n if (order && field) {\n const dir = order.direction === 'desc' ? -1 : 1\n const key = (v: DatasetValue | undefined) => (Array.isArray(v) ? v.join(', ') : v)\n rows.sort((a, b) => {\n const x = key(a[field.id])\n const y = key(b[field.id])\n if (isEmpty(x) || isEmpty(y)) return isEmpty(x) === isEmpty(y) ? 0 : isEmpty(x) ? 1 : -1\n if (typeof x === 'number' && typeof y === 'number') return dir * (x - y)\n return dir * String(x).localeCompare(String(y))\n })\n }\n return {\n fields: dataset.fields,\n rows: query.limit ? rows.slice(0, query.limit) : rows,\n totalRows: rows.length,\n truncated: !!query.limit && rows.length > query.limit,\n }\n}\n\n/** The rows that pass every filter (a filter on an unknown field passes nothing). */\nexport function filterRows(\n rows: readonly DatasetRow[],\n fields: readonly DatasetField[],\n filters: readonly DatasetFilter[] = []\n): DatasetRow[] {\n if (!filters.length) return [...rows]\n const byId = new Map(fields.map((f) => [f.id, f]))\n return rows.filter((row) =>\n filters.every((filter) => {\n const field = byId.get(filter.field)\n return field ? compare(row[filter.field], filter, field) : false\n })\n )\n}\n\nfunction measure(values: DatasetValue[], op: AggregateOp, countRows: boolean): number | null {\n if (op === 'count') return countRows ? values.length : values.filter((v) => !isEmpty(v)).length\n const numbers = values.filter((v): v is number => typeof v === 'number' && Number.isFinite(v))\n if (!numbers.length) return null\n if (op === 'sum') return numbers.reduce((a, b) => a + b, 0)\n if (op === 'avg') return numbers.reduce((a, b) => a + b, 0) / numbers.length\n return op === 'min' ? Math.min(...numbers) : Math.max(...numbers)\n}\n\n/** \"count\", \"sum of Amount\": the value field's label. */\nexport function measureLabel(op: AggregateOp, field?: DatasetField): string {\n return field ? `${op} of ${field.label}` : 'count'\n}\n\nconst labelOf = (key: string) => (key === '' ? EMPTY_GROUP_LABEL : key)\n\n/** The fields of an aggregated dataset. */\nexport function aggregateFields(\n fields: readonly DatasetField[],\n query: DatasetQuery\n): DatasetField[] {\n const byId = new Map(fields.map((f) => [f.id, f]))\n const group = query.groupBy ? byId.get(query.groupBy) : undefined\n const split = query.splitBy ? byId.get(query.splitBy) : undefined\n const op = query.measure?.op ?? 'count'\n const value = query.measure?.field ? byId.get(query.measure.field) : undefined\n return [\n { id: AGGREGATE_FIELDS.group, label: group?.label ?? 'All', type: 'string' },\n { id: AGGREGATE_FIELDS.key, label: group?.label ?? 'All', type: 'string' },\n ...(split\n ? [{ id: AGGREGATE_FIELDS.series, label: split.label, type: 'string' as const }]\n : []),\n {\n id: AGGREGATE_FIELDS.value,\n label: measureLabel(op, value),\n type: 'number',\n ...(value?.unit && op !== 'count' ? { unit: value.unit } : {}),\n },\n ]\n}\n\n/**\n * Group the rows that pass the filters and measure each group: a long-form dataset with the fields\n * `AGGREGATE_FIELDS` (one row per group, or per group and series with `splitBy`).\n */\nexport function aggregateDataset(dataset: Dataset, query: DatasetQuery): Dataset {\n const byId = new Map(dataset.fields.map((f) => [f.id, f]))\n const group = query.groupBy ? byId.get(query.groupBy) : undefined\n const split = query.splitBy ? byId.get(query.splitBy) : undefined\n const op = query.measure?.op ?? 'count'\n const valueField = query.measure?.field ? byId.get(query.measure.field) : undefined\n const bucket = query.bucket ?? 'month'\n const fields = aggregateFields(dataset.fields, query)\n if (op !== 'count' && valueField?.type !== 'number') {\n throw new Error(`${op} needs a number field`)\n }\n\n const rows = filterRows(dataset.rows, dataset.fields, query.filters)\n const cells = new Map<string, Map<string, DatasetValue[]>>()\n for (const row of rows) {\n const groups = group ? groupKeys(row[group.id], group, bucket) : ['All']\n const splits = split ? groupKeys(row[split.id], split, bucket) : ['']\n const value = valueField ? (row[valueField.id] ?? null) : 1\n for (const g of groups) {\n const bySplit = cells.get(g) ?? new Map<string, DatasetValue[]>()\n cells.set(g, bySplit)\n for (const s of splits) bySplit.set(s, [...(bySplit.get(s) ?? []), value])\n }\n }\n\n const countRows = !valueField\n const totals = new Map(\n [...cells].map(([g, bySplit]) => [g, measure([...bySplit.values()].flat(), op, countRows)])\n )\n const byLabel = (a: string, b: string) => (a === '' ? 1 : b === '' ? -1 : a.localeCompare(b))\n const byValue = (dir: 1 | -1) => (a: string, b: string) =>\n (a === '') !== (b === '')\n ? a === ''\n ? 1\n : -1\n : dir * ((totals.get(a) ?? 0) - (totals.get(b) ?? 0)) || byLabel(a, b)\n const sort = query.sort ?? (group?.type === 'date' ? 'label' : 'value-desc')\n const keys = [...cells.keys()].sort(\n sort === 'label' ? byLabel : byValue(sort === 'value-asc' ? 1 : -1)\n )\n const limit = query.limit ?? DEFAULT_LIMIT\n const kept = keys.slice(0, limit)\n\n let splitKeys = ['']\n if (split) {\n const splitTotals = new Map<string, number>()\n for (const g of kept) {\n for (const [s, values] of cells.get(g) ?? []) {\n splitTotals.set(s, (splitTotals.get(s) ?? 0) + (measure(values, op, countRows) ?? 0))\n }\n }\n splitKeys = [...splitTotals.keys()]\n .sort((a, b) =>\n (a === '') !== (b === '')\n ? a === ''\n ? 1\n : -1\n : (splitTotals.get(b) ?? 0) - (splitTotals.get(a) ?? 0) || byLabel(a, b)\n )\n .slice(0, MAX_SERIES)\n }\n\n const out: DatasetRow[] = []\n for (const g of kept) {\n for (const s of splitKeys) {\n const values = cells.get(g)?.get(s)\n out.push({\n [AGGREGATE_FIELDS.group]: labelOf(g),\n [AGGREGATE_FIELDS.key]: g,\n ...(split ? { [AGGREGATE_FIELDS.series]: labelOf(s) } : {}),\n [AGGREGATE_FIELDS.value]: values ? measure(values, op, countRows) : null,\n })\n }\n }\n return { fields, rows: out, totalRows: rows.length, truncated: keys.length > limit }\n}\n\n/**\n * Add the missing date buckets between the first and last group of an aggregated dataset (value\n * `null`), so a trend over time has no silent gaps. Datasets whose keys are not buckets, or that\n * would grow beyond a few hundred groups, come back unchanged.\n */\nexport function fillTimeGaps(dataset: Dataset, bucket: TimeBucket): Dataset {\n const keyId = AGGREGATE_FIELDS.key\n const keys = [...new Set(dataset.rows.map((r) => String(r[keyId] ?? '')))].filter(Boolean)\n if (keys.length < 2) return dataset\n const sorted = [...keys].sort()\n const range = bucketRange(sorted[0], sorted[sorted.length - 1], bucket)\n if (!range || range.length === keys.length) return dataset\n const hasSeries = dataset.fields.some((f) => f.id === AGGREGATE_FIELDS.series)\n const seriesLabels = hasSeries\n ? [...new Set(dataset.rows.map((r) => String(r[AGGREGATE_FIELDS.series])))]\n : [null]\n const byKey = new Map<string, DatasetRow[]>()\n for (const row of dataset.rows) {\n const k = String(row[keyId] ?? '')\n byKey.set(k, [...(byKey.get(k) ?? []), row])\n }\n const rows: DatasetRow[] = []\n for (const k of range) {\n const existing = byKey.get(k)\n if (existing) rows.push(...existing)\n else {\n for (const s of seriesLabels) {\n rows.push({\n [AGGREGATE_FIELDS.group]: k,\n [keyId]: k,\n ...(hasSeries ? { [AGGREGATE_FIELDS.series]: s } : {}),\n [AGGREGATE_FIELDS.value]: null,\n })\n }\n }\n }\n // Rows without a date (the \"(empty)\" group) stay last.\n rows.push(...(byKey.get('') ?? []))\n return { ...dataset, rows }\n}\n","/**\n * `defineRowsSource`: an adapter for data whose rows are loaded in the browser. The adapter gives\n * its fields and a hook reading its rows; filtering, grouping and measuring are applied here\n * (`aggregateDataset`), so every such source answers a query the same way.\n */\nimport { useMemo } from 'react'\nimport { aggregateDataset, recordsOf } from './aggregate'\nimport type {\n DataSource,\n DataSourceFieldsState,\n DataSourceParam,\n DataSourceParams,\n DatasetField,\n DatasetQuery,\n DatasetRow,\n DatasetState,\n} from './types'\n\n/** What a rows adapter's hook reads. */\nexport interface RowsState {\n rows: readonly DatasetRow[] | undefined\n isLoading: boolean\n error: unknown\n}\n\nexport interface RowsSourceDefinition {\n id: string\n label: string\n description?: string\n params?: readonly DataSourceParam[]\n scope?: DataSource['scope']\n /** The fields; a hook, so they may depend on loaded data (a project's own fields). */\n useFields: (params: DataSourceParams) => DataSourceFieldsState\n /** The rows (the same fields' ids). */\n useRows: (params: DataSourceParams, enabled: boolean) => RowsState\n}\n\n/** Answer a query over loaded rows: the groups measured, or the records. */\nexport function datasetOf(\n fields: readonly DatasetField[],\n rows: readonly DatasetRow[],\n query: DatasetQuery\n) {\n return query.records\n ? recordsOf({ fields, rows }, query)\n : aggregateDataset({ fields, rows }, query)\n}\n\n/** A `DataSource` over rows loaded in the browser. */\nexport function defineRowsSource(definition: RowsSourceDefinition): DataSource {\n const { useFields, useRows } = definition\n function useDataset(\n params: DataSourceParams,\n query: DatasetQuery,\n options?: { enabled?: boolean }\n ): DatasetState {\n const fields = useFields(params)\n const rows = useRows(params, options?.enabled ?? true)\n const result = useMemo(() => {\n if (!rows.rows) return { dataset: undefined, error: null }\n try {\n return { dataset: datasetOf(fields.fields, rows.rows, query), error: null }\n } catch (error) {\n return { dataset: undefined, error }\n }\n }, [fields.fields, rows.rows, query])\n return {\n dataset: result.dataset,\n isLoading: rows.isLoading || fields.isLoading,\n error: rows.error ?? fields.error ?? result.error,\n }\n }\n return {\n id: definition.id,\n label: definition.label,\n description: definition.description,\n ...(definition.scope ? { scope: definition.scope } : {}),\n params: definition.params,\n useFields,\n useDataset,\n }\n}\n\n/** A fields hook for a fixed list. */\nexport function staticFields(fields: readonly DatasetField[]) {\n const state: DataSourceFieldsState = { fields, isLoading: false, error: null }\n return () => state\n}\n","/**\n * From a panel's spec to its dataset: the query a `ChartSpec` asks of its source, and the hook a\n * panel reads (grouped and measured by the source, date gaps filled for a trend).\n */\nimport { useMemo } from 'react'\nimport { fillTimeGaps } from './aggregate'\nimport type {\n ChartSpec,\n DataSource,\n DataSourceParams,\n DatasetField,\n DatasetQuery,\n DatasetState,\n} from './types'\n\n/**\n * The query a chart asks: its x field grouped (a metric: one group), its series split, its y\n * measured by the aggregate; a table without `x` lists the records (filtered, ordered, limited).\n */\nexport function queryOfChart(chart: ChartSpec): DatasetQuery {\n if (chart.type === 'table' && !chart.x) {\n return {\n records: true,\n ...(chart.filters?.length ? { filters: chart.filters } : {}),\n ...(chart.orderBy ? { orderBy: chart.orderBy } : {}),\n ...(chart.limit ? { limit: chart.limit } : {}),\n }\n }\n const grouped = chart.type !== 'metric'\n const split = grouped && chart.type !== 'pie' && chart.type !== 'donut' && chart.series\n const op = chart.aggregate ?? 'count'\n return {\n ...(chart.filters?.length ? { filters: chart.filters } : {}),\n ...(grouped && chart.x ? { groupBy: chart.x, bucket: chart.bucket ?? 'month' } : {}),\n ...(split ? { splitBy: chart.series } : {}),\n measure: { op, ...(chart.y ? { field: chart.y } : {}) },\n ...(chart.sort ? { sort: chart.sort } : {}),\n ...(chart.limit ? { limit: chart.limit } : {}),\n }\n}\n\n/** Charts drawn along time, whose missing buckets read as gaps. */\nconst TRENDS = new Set<ChartSpec['type']>(['bar', 'line', 'area'])\n\nexport interface PanelDatasetState extends DatasetState {\n /** The source's fields (for labels and units). */\n fields: readonly DatasetField[]\n}\n\n/**\n * The dataset a panel shows. Render it from a component keyed by `source.id`: the source's hooks\n * run here, and differ from one source to another.\n */\nexport function usePanelDataset(\n source: DataSource,\n params: DataSourceParams | undefined,\n chart: ChartSpec,\n options?: { enabled?: boolean }\n): PanelDatasetState {\n // Specs arrive as fresh objects (edited, parsed); key the memo on their content.\n const paramsKey = JSON.stringify(params ?? {})\n const chartKey = JSON.stringify(chart)\n const stableParams = useMemo(() => JSON.parse(paramsKey) as DataSourceParams, [paramsKey])\n const query = useMemo(() => queryOfChart(JSON.parse(chartKey) as ChartSpec), [chartKey])\n const fields = source.useFields(stableParams)\n const state = source.useDataset(stableParams, query, options)\n const xField = fields.fields.find((f) => f.id === chart.x)\n const fillGaps =\n !!state.dataset &&\n xField?.type === 'date' &&\n TRENDS.has(chart.type) &&\n (chart.sort ?? 'label') === 'label'\n const dataset = useMemo(\n () =>\n state.dataset && fillGaps\n ? fillTimeGaps(state.dataset, chart.bucket ?? 'month')\n : state.dataset,\n [state.dataset, fillGaps, chart.bucket]\n )\n return { ...state, dataset, fields: fields.fields }\n}\n","/**\n * People's names by account id, from the workspaces the user can see (their members), so a chart\n * groups by \"Alex Doe\" rather than `usr-…`. An id nobody can name stays as it is.\n */\nimport { useMemo } from 'react'\nimport { useWorkspaces } from '../hooks'\n\ninterface WorkspaceMembers {\n external_id: string\n name?: string\n users?: Array<{\n user?: {\n external_id?: string\n given_name?: string | null\n family_name?: string | null\n email?: string | null\n } | null\n }> | null\n}\n\n/** Names of members (`usr-…`) and of workspaces (`wrk-…`) by id. */\nexport function namesOfWorkspaces(\n workspaces: readonly WorkspaceMembers[] | undefined\n): Map<string, string> {\n const names = new Map<string, string>()\n for (const w of workspaces ?? []) {\n if (w.name) names.set(w.external_id, w.name)\n for (const member of w.users ?? []) {\n const user = member.user\n if (!user?.external_id || names.has(user.external_id)) continue\n const name = [user.given_name, user.family_name].filter(Boolean).join(' ').trim()\n names.set(user.external_id, name || user.email || user.external_id)\n }\n }\n return names\n}\n\n/** A lookup of people's and workspaces' names (the id itself when unknown). */\nexport function useNames(enabled = true): (id: string | null | undefined) => string | null {\n const { data } = useWorkspaces({ enabled })\n return useMemo(() => {\n const names = namesOfWorkspaces(data as WorkspaceMembers[] | undefined)\n return (id) => (id ? (names.get(id) ?? id) : null)\n }, [data])\n}\n","/**\n * The open workspace's workflows as a dataset: a row per workflow with what starts it, whether it\n * is on, how its last run ended and when it runs next. Reads the shared workflow list\n * (`useWorkflows`), keeping the workflows of the open workspace, so the figures match its\n * activity (a workflow's runs over time are the activity source's `workflow` entries). Nothing is\n * read while the host's `workflows` feature is off.\n */\nimport { useMemo } from 'react'\nimport type { WorkflowResponse } from '@arbidocs/sdk/browser'\nimport { useFeature } from '../../host/features'\nimport { useArbiSessionState } from '../../session'\nimport { useWorkflows } from '../../workforce'\nimport { useNames } from '../members'\nimport { defineRowsSource, staticFields } from '../rows-source'\nimport type { DataSource, DatasetField, DatasetRow } from '../types'\n\ntype Trigger = 'manual' | 'after' | 'event' | 'schedule' | 'once'\n\nexport interface WorkflowsSourceLabels {\n source: string\n description: string\n name: string\n trigger: string\n triggers: Record<Trigger, string>\n active: string\n lastRun: string\n lastResult: string\n /** A last run status by the server's name; one not listed is shown as it comes. */\n results: Readonly<Record<string, string>>\n nextRun: string\n owner: string\n shared: string\n created: string\n}\n\nexport const DEFAULT_WORKFLOWS_SOURCE_LABELS: WorkflowsSourceLabels = {\n source: 'Workflows',\n description:\n 'Your workflows: what starts them, how their last run ended, and when they run next.',\n name: 'Workflow',\n trigger: 'Starts',\n triggers: {\n manual: 'By hand',\n after: 'After a task',\n event: 'On an event',\n schedule: 'On a schedule',\n once: 'Once',\n },\n active: 'On',\n lastRun: 'Last run',\n lastResult: 'Last result',\n results: {\n completed: 'Success',\n success: 'Success',\n failed: 'Failed',\n running: 'In progress',\n awaiting_authorization: 'Awaiting access',\n },\n nextRun: 'Next run',\n owner: 'Owner',\n shared: 'Shared',\n created: 'Created',\n}\n\nfunction triggerOf(w: WorkflowResponse): Trigger {\n if (w.on_demand) return 'manual'\n if (w.after_conversation_ext_id) return 'after'\n if (w.event_kind) return 'event'\n if (w.rrule) return 'schedule'\n if (w.run_at) return 'once'\n return 'manual'\n}\n\nexport function createWorkflowsSource(labels?: Partial<WorkflowsSourceLabels>): DataSource {\n const l = { ...DEFAULT_WORKFLOWS_SOURCE_LABELS, ...labels }\n const fields: DatasetField[] = [\n { id: 'name', label: l.name, type: 'string' },\n { id: 'trigger', label: l.trigger, type: 'string', options: Object.values(l.triggers) },\n { id: 'active', label: l.active, type: 'boolean' },\n { id: 'lastRun', label: l.lastRun, type: 'date' },\n { id: 'lastResult', label: l.lastResult, type: 'string' },\n { id: 'nextRun', label: l.nextRun, type: 'date' },\n { id: 'owner', label: l.owner, type: 'string' },\n { id: 'shared', label: l.shared, type: 'boolean' },\n { id: 'created', label: l.created, type: 'date' },\n ]\n return defineRowsSource({\n id: 'workflows',\n scope: 'workspace',\n label: l.source,\n description: l.description,\n useFields: staticFields(fields),\n useRows(_params, enabled) {\n const on = useFeature('workflows')\n const workspaceId = useArbiSessionState((s) => s.workspaceId)\n const query = useWorkflows({ enabled: enabled && on })\n const nameOf = useNames(enabled)\n const rows = useMemo(\n () =>\n query.data\n ?.filter((w) => !!workspaceId && w.workspace_ext_id === workspaceId)\n .map((w): DatasetRow => {\n const result = w.last_run_status\n return {\n name: w.name,\n trigger: l.triggers[triggerOf(w)],\n active: w.active,\n lastRun: w.last_fired_at ?? null,\n lastResult: result ? (l.results[result] ?? result.replaceAll('_', ' ')) : null,\n nextRun: w.next_fire_at ?? null,\n owner: nameOf(w.owner_ext_id),\n shared: w.shared,\n created: w.created_at,\n }\n }),\n [query.data, nameOf, workspaceId]\n )\n return { rows, isLoading: query.isLoading, error: query.error }\n },\n })\n}\n","/**\n * The open workspace's recent activity as a dataset: a row per entry of its activity feed (thread\n * history, people posting, uploads, new versions and signatures, workflow runs), newest first, as\n * far as the feed's first page reaches (up to 100 entries, cached apart from the feed's own pages).\n * Titles and names decrypt only while the session has the workspace open, so it is re-opened\n * before the read, as the activity feed does. Activity by day, by person, or the\n * workflow runs and how they ended, are a group-by away. Reads the shared feed\n * (`useWorkspaceActivity`), so only what the user can see is counted.\n */\nimport { useMemo } from 'react'\nimport type { components } from '@arbidocs/client'\nimport { useArbi } from '../../useArbi'\nimport { useWorkspaceActivity } from '../../hooks'\nimport { useArbiSessionState } from '../../session'\nimport { useSwitchWorkspace } from '../../workspaces/switch'\nimport { useNames } from '../members'\nimport { defineRowsSource, staticFields } from '../rows-source'\nimport type { DataSource, DatasetField, DatasetRow } from '../types'\nimport { DEFAULT_WORKFLOWS_SOURCE_LABELS } from './workflows'\n\ntype ActivityEntry = components['schemas']['WorkspaceActivityEntry']\ntype ActivityArea = components['schemas']['WorkspaceActivitySource']\n\n/** Entries read: the most the feed gives in one page. */\nconst ENTRIES = 100\n\nexport interface ActivitySourceLabels {\n source: string\n description: string\n when: string\n area: string\n areas: Record<ActivityArea, string>\n kind: string\n /** An entry's kind by the server's name; one not listed is shown in words (`task_done`: \"Task done\"). */\n kinds: Readonly<Record<string, string>>\n person: string\n item: string\n status: string\n /** A workflow run's status by the server's name; one not listed is shown as it comes. */\n statuses: Readonly<Record<string, string>>\n}\n\nexport const DEFAULT_ACTIVITY_SOURCE_LABELS: ActivitySourceLabels = {\n source: 'Recent activity',\n description:\n 'The latest activity of the open workspace: threads, messages, documents and workflow runs.',\n when: 'When',\n area: 'Area',\n areas: { thread: 'Threads', message: 'Messages', document: 'Documents', workflow: 'Workflows' },\n kind: 'What happened',\n kinds: {\n message_posted: 'Message posted',\n document_uploaded: 'Document uploaded',\n document_version: 'New version',\n document_signed: 'Document signed',\n workflow_run: 'Workflow run',\n },\n person: 'Person',\n item: 'Item',\n status: 'Status',\n statuses: DEFAULT_WORKFLOWS_SOURCE_LABELS.results,\n}\n\nconst inWords = (name: string) => {\n const words = name.replaceAll('_', ' ')\n return words.charAt(0).toUpperCase() + words.slice(1)\n}\n\nexport function createActivitySource(labels?: Partial<ActivitySourceLabels>): DataSource {\n const l = { ...DEFAULT_ACTIVITY_SOURCE_LABELS, ...labels }\n const fields: DatasetField[] = [\n { id: 'when', label: l.when, type: 'date' },\n { id: 'area', label: l.area, type: 'string', options: Object.values(l.areas) },\n { id: 'kind', label: l.kind, type: 'string' },\n { id: 'person', label: l.person, type: 'string' },\n { id: 'item', label: l.item, type: 'string' },\n { id: 'status', label: l.status, type: 'string' },\n ]\n return defineRowsSource({\n id: 'activity',\n scope: 'workspace',\n label: l.source,\n description: l.description,\n useFields: staticFields(fields),\n useRows(_params, enabled) {\n const arbi = useArbi()\n const workspaceId = useArbiSessionState((s) => s.workspaceId) ?? undefined\n const { settled, openSelectedWorkspace } = useSwitchWorkspace()\n const feed = useWorkspaceActivity(workspaceId, {\n enabled: enabled && arbi.isLoggedIn,\n limit: ENTRIES,\n beforeFetch: async () => {\n await settled()\n await openSelectedWorkspace()\n },\n })\n const nameOf = useNames(enabled)\n const rows = useMemo(\n () =>\n feed.data?.pages.flatMap((page) =>\n (page.items as ActivityEntry[]).map((e): DatasetRow => ({\n when: e.created_at,\n area: l.areas[e.source] ?? e.source,\n kind: l.kinds[e.kind] ?? inWords(e.kind),\n person: nameOf(e.actor_ext_id),\n item: e.conversation_title || e.document_name || e.workflow_name || null,\n status: e.status ? (l.statuses[e.status] ?? inWords(e.status)) : null,\n }))\n ),\n [feed.data, nameOf]\n )\n return { rows, isLoading: feed.isLoading && !!workspaceId, error: feed.error }\n },\n })\n}\n","/**\n * The conversations of a workspace (threads and tasks) as a dataset (default: the open one;\n * `params.workspaceId` names another): activity over time, work by status, owner and due date.\n * Reads the shared conversation list (`useConversations`), which live updates keep current.\n */\nimport { useMemo } from 'react'\nimport { useArbi } from '../../useArbi'\nimport { useConversations } from '../../hooks'\nimport { useNames } from '../members'\nimport { defineRowsSource, staticFields } from '../rows-source'\nimport type { DataSource, DataSourceParams, DatasetField, DatasetRow } from '../types'\n\nexport interface ConversationsSourceLabels {\n source: string\n description: string\n title: string\n created: string\n lastActivity: string\n due: string\n completed: string\n kind: string\n /** The `kind` of a conversation without a work status. */\n thread: string\n /** The `kind` of a conversation with a work status. */\n task: string\n status: string\n statuses: { todo: string; generating: string; done: string }\n overdue: string\n owner: string\n messages: string\n shared: string\n}\n\nexport const DEFAULT_CONVERSATIONS_SOURCE_LABELS: ConversationsSourceLabels = {\n source: 'Threads',\n description: 'The threads and tasks of the open workspace: activity, status, owners, due dates.',\n title: 'Title',\n created: 'Started',\n lastActivity: 'Last activity',\n due: 'Due',\n completed: 'Completed',\n kind: 'Kind',\n thread: 'Thread',\n task: 'Task',\n status: 'Status',\n statuses: { todo: 'To do', generating: 'Running', done: 'Done' },\n overdue: 'Overdue',\n owner: 'Owner',\n messages: 'Messages',\n shared: 'Shared',\n}\n\ninterface ConversationLike {\n external_id: string\n title?: string | null\n created_at?: string | null\n updated_at?: string | null\n last_message_updated_at?: string | null\n due_at?: string | null\n completed_at?: string | null\n status?: 'todo' | 'generating' | 'done' | null\n is_shared?: boolean | null\n message_count?: number | null\n owner_ext_id?: string | null\n created_by_ext_id?: string | null\n}\n\nexport function createConversationsSource(labels?: Partial<ConversationsSourceLabels>): DataSource {\n const l = { ...DEFAULT_CONVERSATIONS_SOURCE_LABELS, ...labels }\n const fields: DatasetField[] = [\n { id: 'title', label: l.title, type: 'string' },\n { id: 'created', label: l.created, type: 'date' },\n { id: 'lastActivity', label: l.lastActivity, type: 'date' },\n { id: 'due', label: l.due, type: 'date' },\n { id: 'completed', label: l.completed, type: 'date' },\n { id: 'kind', label: l.kind, type: 'string', options: [l.thread, l.task] },\n { id: 'status', label: l.status, type: 'string', options: Object.values(l.statuses) },\n { id: 'overdue', label: l.overdue, type: 'boolean' },\n { id: 'owner', label: l.owner, type: 'string' },\n { id: 'messages', label: l.messages, type: 'number' },\n { id: 'shared', label: l.shared, type: 'boolean' },\n ]\n return defineRowsSource({\n id: 'conversations',\n scope: 'workspace',\n label: l.source,\n description: l.description,\n useFields: staticFields(fields),\n useRows(params: DataSourceParams, enabled) {\n const arbi = useArbi()\n const workspaceId =\n typeof params.workspaceId === 'string' && params.workspaceId\n ? params.workspaceId\n : arbi.hasWorkspace\n ? arbi.getWorkspaceId()\n : undefined\n const query = useConversations(workspaceId, { enabled })\n const nameOf = useNames(enabled)\n const rows = useMemo(() => {\n const now = new Date().toISOString()\n return (query.data as ConversationLike[] | undefined)?.map((c): DatasetRow => ({\n title: c.title || null,\n created: c.created_at ?? null,\n lastActivity: c.last_message_updated_at ?? c.updated_at ?? null,\n due: c.due_at ?? null,\n completed: c.completed_at ?? null,\n kind: c.status ? l.task : l.thread,\n status: c.status ? l.statuses[c.status] : null,\n overdue: Boolean(c.due_at && c.status !== 'done' && c.due_at < now),\n owner: nameOf(c.owner_ext_id ?? c.created_by_ext_id),\n messages: c.message_count ?? null,\n shared: c.is_shared ?? null,\n }))\n }, [query.data, nameOf])\n return { rows, isLoading: query.isLoading && !!workspaceId, error: query.error }\n },\n })\n}\n","/**\n * A database of the open workspace (one the user created or imported from a spreadsheet) as a\n * dataset: `params.databaseId` picks it, `params.view` one of its saved views (the grid's\n * \"Columns\" menu), whose columns are then the fields offered. Grouping and measuring run on the\n * server (`POST /v1/databases/{id}/aggregate`, over every row, so totals are exact however large the\n * database is); a table of records reads the first page of rows.\n */\nimport { useMemo } from 'react'\nimport { useUserSettings } from '../../account/settings'\nimport { viewsOfTable, type TableView } from '../../account/table-views'\nimport { useArbi } from '../../useArbi'\nimport {\n useDatabase,\n useDatabaseAggregate,\n useDatabaseRows,\n useDatabases,\n type Database,\n type DatabaseAggregateRequest,\n type DatabaseAggregateResult,\n type DatabaseColumn,\n type DatabaseRow,\n} from '../../databases'\nimport { aggregateFields, recordsOf } from '../aggregate'\nimport {\n AGGREGATE_FIELDS,\n type DataSource,\n type DataSourceFieldsState,\n type DataSourceParams,\n type Dataset,\n type DatasetField,\n type DatasetQuery,\n type DatasetRow,\n type DatasetState,\n type DatasetValue,\n} from '../types'\n\nexport interface DatabaseSourceLabels {\n source: string\n description: string\n database: string\n view: string\n allColumns: string\n}\n\nexport const DEFAULT_DATABASE_SOURCE_LABELS: DatabaseSourceLabels = {\n source: 'Database',\n description: 'A database, or one of its saved views.',\n database: 'Database',\n view: 'Saved view',\n allColumns: 'All columns',\n}\n\nconst MULTI = new Set(['document', 'relation', 'lookup', 'tag'])\n\n/** A database column as a dataset field (ids are the column ids the server groups by). */\nexport function fieldOfColumn(column: DatabaseColumn): DatasetField {\n const type =\n column.type === 'number' || column.type === 'rollup'\n ? 'number'\n : column.type === 'date'\n ? 'date'\n : column.type === 'checkbox'\n ? 'boolean'\n : 'string'\n return {\n id: column.id,\n label: column.name,\n type,\n ...(column.options?.length ? { options: column.options } : {}),\n ...(MULTI.has(column.type) ? { multiple: true } : {}),\n }\n}\n\nconst text = (v: DatasetValue | undefined) => (typeof v === 'string' && v ? v : undefined)\n\n/** The fields of a database, limited to a saved view's columns (in its order) when one is named. */\nexport function databaseFields(\n database: Pick<Database, 'columns'> | undefined,\n view?: Pick<TableView, 'columns'>\n): DatasetField[] {\n const columns = database?.columns ?? []\n if (!view?.columns?.length) return columns.map(fieldOfColumn)\n const byId = new Map(columns.map((c) => [c.id, c]))\n return view.columns.flatMap((id) => {\n const column = byId.get(id)\n return column ? [fieldOfColumn(column)] : []\n })\n}\n\n/** The server request for a query. */\nexport function aggregateRequest(query: DatasetQuery): Partial<DatabaseAggregateRequest> {\n return {\n group_by: query.groupBy ?? null,\n split_by: query.splitBy ?? null,\n time_bucket: query.bucket ?? 'month',\n measure: { op: query.measure?.op ?? 'count', column: query.measure?.field ?? null },\n filters: (query.filters ?? []).map((f) => ({ column: f.field, op: f.op, value: f.value })),\n limit: query.limit ?? 50,\n }\n}\n\n/** The server's labels and series as a long-form aggregated dataset, re-sorted when asked. */\nexport function datasetOfAggregate(\n result: DatabaseAggregateResult,\n fields: readonly DatasetField[],\n query: DatasetQuery\n): Dataset {\n const split = Boolean(query.splitBy)\n let order = result.keys.map((_, i) => i)\n const total = (i: number) => result.series.reduce((sum, s) => sum + (s.values[i] ?? 0), 0)\n if (query.sort === 'label') {\n order = [...order].sort((a, b) =>\n result.keys[a] === ''\n ? 1\n : result.keys[b] === ''\n ? -1\n : result.labels[a].localeCompare(result.labels[b])\n )\n } else if (query.sort === 'value-asc') {\n order = [...order].sort((a, b) => total(a) - total(b))\n } else if (query.sort === 'value-desc') {\n order = [...order].sort((a, b) => total(b) - total(a))\n }\n const rows: DatasetRow[] = order.flatMap((i) =>\n result.series.map((s) => ({\n [AGGREGATE_FIELDS.group]: result.labels[i],\n [AGGREGATE_FIELDS.key]: result.keys[i],\n ...(split ? { [AGGREGATE_FIELDS.series]: s.label } : {}),\n [AGGREGATE_FIELDS.value]: s.values[i] ?? null,\n }))\n )\n return {\n fields: aggregateFields(fields, query),\n rows,\n totalRows: result.total_rows,\n truncated: result.truncated,\n }\n}\n\n/** A database row as a dataset row: linked ids read as their titles. */\nexport function datasetRowOf(row: DatabaseRow, fields: readonly DatasetField[]): DatasetRow {\n const titles = row.titles ?? {}\n const out: Record<string, DatasetValue> = {}\n for (const field of fields) {\n const raw = row.values[field.id]\n if (raw === null || raw === undefined) out[field.id] = null\n else if (Array.isArray(raw)) out[field.id] = raw.map((v) => titles[String(v)] ?? String(v))\n else if (typeof raw === 'string')\n out[field.id] = field.type === 'string' ? (titles[raw] ?? raw) : raw\n else if (typeof raw === 'number' || typeof raw === 'boolean') out[field.id] = raw\n else out[field.id] = String(raw)\n }\n return out\n}\n\nexport function createDatabaseSource(labels?: Partial<DatabaseSourceLabels>): DataSource {\n const l = { ...DEFAULT_DATABASE_SOURCE_LABELS, ...labels }\n\n function useView(params: DataSourceParams): TableView | undefined {\n const arbi = useArbi()\n const databaseId = text(params.databaseId)\n const viewName = text(params.view)\n const settings = useUserSettings({ enabled: Boolean(viewName) })\n const workspaceId = arbi.hasWorkspace ? arbi.getWorkspaceId() : null\n return useMemo(\n () =>\n viewName && databaseId\n ? viewsOfTable(settings.data?.tableviews, workspaceId, databaseId).find(\n (v) => v.name === viewName\n )\n : undefined,\n [settings.data?.tableviews, workspaceId, databaseId, viewName]\n )\n }\n\n function useFields(params: DataSourceParams): DataSourceFieldsState {\n const databaseId = text(params.databaseId) ?? null\n const database = useDatabase(databaseId, { workspaceId: text(params.workspaceId) })\n const view = useView(params)\n const fields = useMemo(() => databaseFields(database.data, view), [database.data, view])\n return { fields, isLoading: database.isLoading && !!databaseId, error: database.error }\n }\n\n function useDataset(\n params: DataSourceParams,\n query: DatasetQuery,\n options?: { enabled?: boolean }\n ): DatasetState {\n const databaseId = text(params.databaseId) ?? null\n const enabled = options?.enabled ?? true\n const fields = useFields(params)\n const grouped = !query.records\n const request = useMemo(() => (grouped ? aggregateRequest(query) : {}), [grouped, query])\n const workspaceId = text(params.workspaceId)\n const aggregate = useDatabaseAggregate(databaseId, request, {\n enabled: enabled && grouped,\n workspaceId,\n })\n const rows = useDatabaseRows(enabled && !grouped ? databaseId : null, '', { workspaceId })\n const dataset = useMemo(() => {\n if (grouped) {\n return aggregate.data ? datasetOfAggregate(aggregate.data, fields.fields, query) : undefined\n }\n if (!rows.data) return undefined\n const records = rows.data.rows.map((r) => datasetRowOf(r, fields.fields))\n return recordsOf({ fields: fields.fields, rows: records }, query)\n }, [grouped, query, aggregate.data, rows.data, fields.fields])\n const active = grouped ? aggregate : rows\n return {\n dataset,\n isLoading: !!databaseId && (active.isLoading || fields.isLoading),\n error: active.error ?? fields.error,\n }\n }\n\n return {\n id: 'database',\n label: l.source,\n description: l.description,\n // A panel that names its database's workspace reads it anywhere; an older one, only in the open one.\n scope: (params) => (text(params.workspaceId) ? undefined : 'workspace'),\n params: [\n {\n id: 'databaseId',\n label: l.database,\n required: true,\n // The open workspace's databases (the list is read there), and the panel's own database\n // wherever it is (read by id in its workspace), so its name shows with none or another open.\n useOptions(params) {\n const databases = useDatabases()\n const currentId = text(params.databaseId) ?? null\n const listed = (databases.data ?? []).some((d) => d.id === currentId)\n const current = useDatabase(listed ? null : currentId, {\n workspaceId: text(params.workspaceId),\n })\n const options = useMemo(() => {\n const all = [...(databases.data ?? [])]\n if (current.data && !listed) all.push(current.data)\n return all.map((d) => ({\n value: d.id,\n label: d.name,\n params: { workspaceId: d.workspace_id },\n }))\n }, [databases.data, current.data, listed])\n return { options, isLoading: databases.isLoading || current.isLoading }\n },\n },\n {\n id: 'view',\n label: l.view,\n placeholder: l.allColumns,\n useOptions(params) {\n const arbi = useArbi()\n const databaseId = text(params.databaseId)\n const settings = useUserSettings({ enabled: Boolean(databaseId) })\n const workspaceId = arbi.hasWorkspace ? arbi.getWorkspaceId() : null\n const options = useMemo(\n () =>\n databaseId\n ? viewsOfTable(settings.data?.tableviews, workspaceId, databaseId).map((v) => ({\n value: v.name,\n label: v.name,\n }))\n : [],\n [settings.data?.tableviews, workspaceId, databaseId]\n )\n return { options, isLoading: settings.isLoading && !!databaseId }\n },\n },\n ],\n useFields,\n useDataset,\n }\n}\n","/**\n * The documents of a workspace as a dataset (default: the open one; `params.workspaceId` names\n * another): counts and status by type, folder, author or time. Reads the shared documents list\n * (`useDocuments`), which live updates keep current, so a panel follows uploads as they process.\n */\nimport { useMemo } from 'react'\nimport { useDocuments } from '../../documents/documents-data'\nimport { friendlyFileType } from '../../entities/file-type'\nimport { useNames } from '../members'\nimport { defineRowsSource, staticFields } from '../rows-source'\nimport type { DataSource, DataSourceParams, DatasetField, DatasetRow } from '../types'\n\n/** The field labels (a site's words). */\nexport interface DocumentsSourceLabels {\n source: string\n description: string\n created: string\n updated: string\n documentDate: string\n status: string\n /** A processing status by the server's name; one not listed is shown as it comes. */\n statuses: Readonly<Record<string, string>>\n type: string\n folder: string\n nature: string\n author: string\n createdBy: string\n pages: string\n size: string\n shared: string\n}\n\nexport const DEFAULT_DOCUMENTS_SOURCE_LABELS: DocumentsSourceLabels = {\n source: 'Documents',\n description: 'The documents of the open workspace: type, folder, status, dates.',\n created: 'Added',\n updated: 'Updated',\n documentDate: 'Document date',\n status: 'Status',\n statuses: {\n completed: 'Ready',\n 'low-content': 'Little text',\n failed: 'Failed',\n skipped: 'Skipped',\n empty: 'Empty',\n queued: 'Queued',\n uploading: 'Uploading',\n parsing: 'Processing',\n encrypting: 'Processing',\n indexing: 'Processing',\n analysing: 'Processing',\n },\n type: 'Type',\n folder: 'Folder',\n nature: 'Kind of document',\n author: 'Author',\n createdBy: 'Added by',\n pages: 'Pages',\n size: 'Size',\n shared: 'Shared',\n}\n\ninterface DocumentLike {\n external_id: string\n file_name?: string | null\n file_type?: string | null\n file_size?: number | null\n status?: string | null\n folder?: string | null\n n_pages?: number | null\n shared?: boolean | null\n created_by_ext_id?: string | null\n created_at?: string | null\n updated_at?: string | null\n doc_metadata?: {\n doc_nature?: string | null\n doc_author?: string | null\n doc_date?: string | null\n title?: string | null\n } | null\n}\n\nconst workspaceOf = (params: DataSourceParams) =>\n typeof params.workspaceId === 'string' && params.workspaceId ? params.workspaceId : undefined\n\nexport function createDocumentsSource(labels?: Partial<DocumentsSourceLabels>): DataSource {\n const l = { ...DEFAULT_DOCUMENTS_SOURCE_LABELS, ...labels }\n const fields: DatasetField[] = [\n { id: 'name', label: l.source, type: 'string' },\n { id: 'created', label: l.created, type: 'date' },\n { id: 'updated', label: l.updated, type: 'date' },\n { id: 'documentDate', label: l.documentDate, type: 'date' },\n {\n id: 'status',\n label: l.status,\n type: 'string',\n options: [...new Set(Object.values(l.statuses))],\n },\n { id: 'type', label: l.type, type: 'string' },\n { id: 'folder', label: l.folder, type: 'string' },\n { id: 'nature', label: l.nature, type: 'string' },\n { id: 'author', label: l.author, type: 'string' },\n { id: 'createdBy', label: l.createdBy, type: 'string' },\n { id: 'pages', label: l.pages, type: 'number' },\n { id: 'size', label: l.size, type: 'number', unit: 'bytes' },\n { id: 'shared', label: l.shared, type: 'boolean' },\n ]\n return defineRowsSource({\n id: 'documents',\n scope: 'workspace',\n label: l.source,\n description: l.description,\n useFields: staticFields(fields),\n useRows(params, enabled) {\n const query = useDocuments(workspaceOf(params), { enabled })\n const nameOf = useNames(enabled)\n const rows = useMemo(\n () =>\n (query.data as DocumentLike[] | undefined)?.map((d): DatasetRow => ({\n name: d.doc_metadata?.title || d.file_name || d.external_id,\n created: d.created_at ?? null,\n updated: d.updated_at ?? null,\n documentDate: d.doc_metadata?.doc_date ?? null,\n status: d.status ? (l.statuses[d.status] ?? d.status) : null,\n type: friendlyFileType(d.file_type, d.file_name) || null,\n folder: d.folder || null,\n nature: d.doc_metadata?.doc_nature ?? null,\n author: d.doc_metadata?.doc_author ?? null,\n createdBy: nameOf(d.created_by_ext_id),\n pages: d.n_pages ?? null,\n size: d.file_size ?? null,\n shared: d.shared ?? null,\n })),\n [query.data, nameOf]\n )\n return { rows, isLoading: query.isLoading, error: query.error }\n },\n })\n}\n","/**\n * The facts (notes) of the open workspace as a dataset: a row per fact with its tags (a fact counts\n * under each), whether it is confirmed, its date and who added it. Reads the shared fact list\n * (`useFacts`), which every fact write refreshes.\n */\nimport { useMemo } from 'react'\nimport type { FactResponse } from '@arbidocs/sdk/browser'\nimport { useFacts } from '../../facts'\nimport { useNames } from '../members'\nimport { defineRowsSource, staticFields } from '../rows-source'\nimport type { DataSource, DatasetField, DatasetRow } from '../types'\n\nexport interface FactsSourceLabels {\n source: string\n description: string\n text: string\n tags: string\n confirmed: string\n shared: string\n date: string\n created: string\n createdBy: string\n}\n\nexport const DEFAULT_FACTS_SOURCE_LABELS: FactsSourceLabels = {\n source: 'Facts',\n description:\n 'The facts of the open workspace: their tags, dates, and whether they are confirmed.',\n text: 'Fact',\n tags: 'Tags',\n confirmed: 'Confirmed',\n shared: 'Shared',\n date: 'Date',\n created: 'Added',\n createdBy: 'Added by',\n}\n\nexport function createFactsSource(labels?: Partial<FactsSourceLabels>): DataSource {\n const l = { ...DEFAULT_FACTS_SOURCE_LABELS, ...labels }\n const fields: DatasetField[] = [\n { id: 'text', label: l.text, type: 'string' },\n { id: 'tags', label: l.tags, type: 'string', multiple: true },\n { id: 'confirmed', label: l.confirmed, type: 'boolean' },\n { id: 'shared', label: l.shared, type: 'boolean' },\n { id: 'date', label: l.date, type: 'date' },\n { id: 'created', label: l.created, type: 'date' },\n { id: 'createdBy', label: l.createdBy, type: 'string' },\n ]\n return defineRowsSource({\n id: 'facts',\n scope: 'workspace',\n label: l.source,\n description: l.description,\n useFields: staticFields(fields),\n useRows(_params, enabled) {\n const query = useFacts(undefined, { enabled })\n const nameOf = useNames(enabled)\n const rows = useMemo(\n () =>\n (query.data as FactResponse[] | undefined)?.map((f): DatasetRow => ({\n text: f.text,\n tags: f.tags.map((t) => t.name),\n confirmed: f.confirmed,\n shared: f.shared,\n date: f.date_start ?? null,\n created: f.created_at,\n createdBy: nameOf(f.created_by_ext_id),\n })),\n [query.data, nameOf]\n )\n return { rows, isLoading: query.isLoading, error: query.error }\n },\n })\n}\n","/**\n * The user's projects as a dataset: by stage, lead, client and the host's own project fields, and\n * opened or closed over time. Reads the shared project list (`useProjects`).\n *\n * The backend records a stage and when it last changed, not a \"closed\" flag: a host that has\n * closing stages names them (`closedStages`), and a project in one of them is closed as of its\n * stage change. A site's word for a project and its stages come in through `labels`.\n */\nimport { useMemo } from 'react'\nimport type { components } from '@arbidocs/client'\nimport { useProjects } from '../../hooks'\nimport { useNames } from '../members'\nimport { defineRowsSource } from '../rows-source'\nimport type { DataSource, DataSourceFieldsState, DatasetField, DatasetRow } from '../types'\n\ntype ProjectResponse = components['schemas']['ProjectResponse']\ntype FieldSchemaEntry = components['schemas']['FieldSchemaEntry']\n\nexport interface ProjectsSourceLabels {\n source: string\n description: string\n name: string\n opened: string\n stage: string\n stageChanged: string\n lead: string\n client: string\n plan: string\n state: string\n open: string\n closed: string\n closedAt: string\n}\n\nexport const DEFAULT_PROJECTS_SOURCE_LABELS: ProjectsSourceLabels = {\n source: 'Projects',\n description: 'Your projects: stage, lead, client and their own fields; opened and closed.',\n name: 'Name',\n opened: 'Opened',\n stage: 'Stage',\n stageChanged: 'Stage changed',\n lead: 'Lead',\n client: 'Client',\n plan: 'Plan',\n state: 'Open or closed',\n open: 'Open',\n closed: 'Closed',\n closedAt: 'Closed',\n}\n\nexport interface ProjectsSourceOptions {\n labels?: Partial<ProjectsSourceLabels>\n /** Stages that close a project (compared without case). */\n closedStages?: readonly string[]\n}\n\nconst FIELD_PREFIX = 'field:'\n\nfunction hostField(entry: FieldSchemaEntry): DatasetField {\n const type =\n entry.type === 'number' || entry.type === 'rollup'\n ? 'number'\n : entry.type === 'date'\n ? 'date'\n : entry.type === 'checkbox'\n ? 'boolean'\n : 'string'\n return {\n id: `${FIELD_PREFIX}${entry.key}`,\n label: entry.label || entry.key,\n type,\n ...(entry.options?.length ? { options: entry.options } : {}),\n }\n}\n\n/** A host field's cell as a dataset value. */\nfunction hostValue(value: unknown, field: DatasetField): DatasetRow[string] {\n if (value === null || value === undefined || value === '') return null\n if (Array.isArray(value)) return value.map(String)\n if (field.type === 'number') return typeof value === 'number' ? value : Number(value) || null\n if (field.type === 'boolean') return Boolean(value)\n return String(value)\n}\n\nexport function createProjectsSource(options: ProjectsSourceOptions = {}): DataSource {\n const l = { ...DEFAULT_PROJECTS_SOURCE_LABELS, ...options.labels }\n const closing = new Set((options.closedStages ?? []).map((s) => s.toLowerCase()))\n const base: DatasetField[] = [\n { id: 'name', label: l.name, type: 'string' },\n { id: 'opened', label: l.opened, type: 'date' },\n { id: 'stage', label: l.stage, type: 'string' },\n { id: 'stageChanged', label: l.stageChanged, type: 'date' },\n { id: 'lead', label: l.lead, type: 'string' },\n { id: 'client', label: l.client, type: 'string' },\n { id: 'plan', label: l.plan, type: 'string' },\n ...(closing.size\n ? [\n { id: 'state', label: l.state, type: 'string' as const, options: [l.open, l.closed] },\n { id: 'closedAt', label: l.closedAt, type: 'date' as const },\n ]\n : []),\n ]\n\n /** The host fields every project declares (the first declaration of a key wins). */\n function fieldsOf(projects: readonly ProjectResponse[] | undefined): DatasetField[] {\n const seen = new Map<string, DatasetField>()\n for (const p of projects ?? []) {\n for (const entry of p.field_schema ?? []) {\n if (!seen.has(entry.key)) seen.set(entry.key, hostField(entry))\n }\n }\n return [...base, ...seen.values()]\n }\n\n return defineRowsSource({\n id: 'projects',\n label: l.source,\n description: l.description,\n useFields(): DataSourceFieldsState {\n const query = useProjects()\n const fields = useMemo(\n () => fieldsOf(query.data as ProjectResponse[] | undefined),\n [query.data]\n )\n return { fields, isLoading: query.isLoading, error: query.error }\n },\n useRows(_params, enabled) {\n const query = useProjects({ enabled })\n const nameOf = useNames(enabled)\n const rows = useMemo(() => {\n const projects = query.data as ProjectResponse[] | undefined\n if (!projects) return undefined\n const host = fieldsOf(projects).filter((f) => f.id.startsWith(FIELD_PREFIX))\n const people = new Set(\n projects.flatMap((p) =>\n (p.field_schema ?? []).filter((e) => e.type === 'person').map((e) => e.key)\n )\n )\n return projects.map((p): DatasetRow => {\n const closed = !!p.stage && closing.has(p.stage.toLowerCase())\n const row: Record<string, DatasetRow[string]> = {\n name: p.name,\n opened: p.created_at,\n stage: p.stage ?? null,\n stageChanged: p.stage_changed_at ?? null,\n lead: nameOf(p.lead_user),\n client: p.client ?? null,\n plan: p.subscription ?? null,\n }\n if (closing.size) {\n row.state = closed ? l.closed : l.open\n row.closedAt = closed ? (p.stage_changed_at ?? null) : null\n }\n for (const field of host) {\n const key = field.id.slice(FIELD_PREFIX.length)\n const value = hostValue(p.fields?.[key], field)\n row[field.id] =\n people.has(key) && value !== null\n ? Array.isArray(value)\n ? value.map((id) => nameOf(id) ?? id)\n : nameOf(String(value))\n : value\n }\n return row\n })\n }, [query.data, nameOf])\n return { rows, isLoading: query.isLoading, error: query.error }\n },\n })\n}\n","/**\n * The tags of the open workspace as a dataset: a row per tag with its kind, and how many\n * documents, facts and threads carry it. The most used tags, or tags by kind, are a group-by and a\n * sum away. Reads the shared tag list (`useTags`), which every tag write keeps current.\n */\nimport { useMemo } from 'react'\nimport type { TagResponse } from '@arbidocs/sdk/browser'\nimport { useTags } from '../../hooks'\nimport { useNames } from '../members'\nimport { defineRowsSource, staticFields } from '../rows-source'\nimport type { DataSource, DatasetField, DatasetRow } from '../types'\n\nexport interface TagsSourceLabels {\n source: string\n description: string\n name: string\n kind: string\n kinds: Record<TagResponse['kind'], string>\n documents: string\n facts: string\n threads: string\n shared: string\n created: string\n createdBy: string\n}\n\nexport const DEFAULT_TAGS_SOURCE_LABELS: TagsSourceLabels = {\n source: 'Tags',\n description:\n 'The tags of the open workspace: their kind, and the documents, facts and threads carrying them.',\n name: 'Tag',\n kind: 'Kind',\n kinds: {\n label: 'Label',\n annotation: 'Annotation',\n search: 'Search',\n issue: 'Issue',\n person: 'Person',\n organisation: 'Organisation',\n },\n documents: 'Documents',\n facts: 'Facts',\n threads: 'Threads',\n shared: 'Shared',\n created: 'Created',\n createdBy: 'Created by',\n}\n\nexport function createTagsSource(labels?: Partial<TagsSourceLabels>): DataSource {\n const l = { ...DEFAULT_TAGS_SOURCE_LABELS, ...labels }\n const fields: DatasetField[] = [\n { id: 'name', label: l.name, type: 'string' },\n { id: 'kind', label: l.kind, type: 'string', options: Object.values(l.kinds) },\n { id: 'documents', label: l.documents, type: 'number' },\n { id: 'facts', label: l.facts, type: 'number' },\n { id: 'threads', label: l.threads, type: 'number' },\n { id: 'shared', label: l.shared, type: 'boolean' },\n { id: 'created', label: l.created, type: 'date' },\n { id: 'createdBy', label: l.createdBy, type: 'string' },\n ]\n return defineRowsSource({\n id: 'tags',\n scope: 'workspace',\n label: l.source,\n description: l.description,\n useFields: staticFields(fields),\n useRows(_params, enabled) {\n const query = useTags(undefined, { enabled })\n const nameOf = useNames(enabled)\n const rows = useMemo(\n () =>\n (query.data as TagResponse[] | undefined)?.map((t): DatasetRow => ({\n name: t.name,\n kind: l.kinds[t.kind] ?? t.kind,\n documents: t.doctag_count,\n facts: t.facttag_count,\n threads: t.convotag_count,\n shared: t.shared,\n created: t.created_at,\n createdBy: nameOf(t.created_by_ext_id),\n })),\n [query.data, nameOf]\n )\n return { rows, isLoading: query.isLoading, error: query.error }\n },\n })\n}\n","/**\n * AI usage (recorded by the model gateway) as datasets, for this billing period or the last\n * (`params.period` `\"0\"` / `\"1\"`):\n *\n * - `usage`: one row per project, day and model group.\n * - `usage-breakdown`: the period's totals by user, workspace, model or feature (`params.by`), one\n * row per project and name: the gateway records who and where for the period only, not by day.\n *\n * Both read one project (`params.project`, its error surfaced: a project's own usage view) or every\n * project the user owns (the server answers a project's usage to its owner alone; a project whose\n * usage cannot be read is left out rather than failing the others, so a member sees no usage).\n * Each project's usage is read through the same queries as `useProjectUsage`, so a dashboard and\n * the project's usage view share one cache. £ are ex VAT.\n */\nimport { useMemo } from 'react'\nimport { useQueries } from '@tanstack/react-query'\nimport type { components } from '@arbidocs/client'\nimport { useArbi } from '../../useArbi'\nimport { useCurrentUser, useProjects, useWorkspaces } from '../../hooks'\nimport { arbiQueryKeys } from '../../query-keys'\nimport { getUserDisplayName } from '../../users/user-display'\nimport { defineRowsSource, staticFields, type RowsState } from '../rows-source'\nimport type {\n DataSource,\n DataSourceFieldsState,\n DataSourceParam,\n DataSourceParams,\n DatasetField,\n DatasetRow,\n} from '../types'\n\ntype ProjectResponse = components['schemas']['ProjectResponse']\ntype ProjectUsageResponse = components['schemas']['ProjectUsageResponse']\ntype WorkspaceResponse = components['schemas']['WorkspaceResponse']\n\n/**\n * People's names for model groups whose gateway names are not meant to be read (the LLM tiers are\n * already readable).\n */\nexport const MODEL_GROUP_LABELS: Readonly<Record<string, string>> = {\n 'arbi-transcribe-diarized': 'Transcription (diarized)',\n 'arbi-transcribe': 'Transcription',\n}\n\n/** What usage is broken down by (`usage-breakdown`'s `by`). */\nexport type UsageBreakdownKey = 'user' | 'workspace' | 'model' | 'feature'\n\n/** `usage-breakdown`'s `by`: a breakdown, or `total` (the period's totals as the server counts them). */\nexport type UsageBreakdownBy = UsageBreakdownKey | 'total'\n\nexport interface UsageSourceLabels {\n source: string\n description: string\n period: string\n periods: { current: string; previous: string }\n /** The project parameter (its placeholder: every project the user owns). */\n projectParam: string\n allProjects: string\n day: string\n project: string\n model: string\n spend: string\n tokens: string\n requests: string\n}\n\nexport const DEFAULT_USAGE_SOURCE_LABELS: UsageSourceLabels = {\n source: 'AI usage',\n description: 'AI usage of your projects by day and model: £ (ex VAT), tokens and requests.',\n period: 'Period',\n periods: { current: 'This period', previous: 'Last period' },\n projectParam: 'Project',\n allProjects: 'All your projects',\n day: 'Day',\n project: 'Project',\n model: 'Model',\n spend: 'AI usage (£)',\n tokens: 'Tokens',\n requests: 'Requests',\n}\n\nexport interface UsageBreakdownSourceLabels extends Omit<\n UsageSourceLabels,\n 'day' | 'model' | 'description'\n> {\n description: string\n breakdown: string\n /** The breakdowns, as the parameter's choices and the name field's label. */\n by: Record<UsageBreakdownBy, string>\n}\n\nexport const DEFAULT_USAGE_BREAKDOWN_SOURCE_LABELS: UsageBreakdownSourceLabels = {\n ...DEFAULT_USAGE_SOURCE_LABELS,\n source: 'AI usage breakdown',\n description:\n 'AI usage of your projects this period, in total or by user, workspace, model or feature: £ (ex VAT), tokens and requests.',\n breakdown: 'Breakdown',\n by: { total: 'Total', user: 'User', workspace: 'Workspace', model: 'Model', feature: 'Feature' },\n}\n\nconst monthsBackOf = (params: DataSourceParams) => (String(params.period ?? '0') === '1' ? 1 : 0)\n\nconst projectOf = (params: DataSourceParams) =>\n typeof params.project === 'string' && params.project ? params.project : undefined\n\nconst BREAKDOWNS: readonly UsageBreakdownBy[] = ['total', 'user', 'workspace', 'model', 'feature']\n\nconst breakdownOf = (params: DataSourceParams): UsageBreakdownBy =>\n BREAKDOWNS.find((b) => b === params.by) ?? 'user'\n\n/** The projects `me` owns (the server answers a project's usage to its owner alone). */\nconst ownedBy = (projects: unknown, me: string | undefined) =>\n ((projects as ProjectResponse[] | undefined) ?? []).filter((p) => !!me && p.created_by === me)\n\n/** Every day of the billing period starting `start` (to the day before the same date next month). */\nfunction periodDays(start: string): string[] {\n const end = new Date(`${start}T00:00:00Z`)\n end.setUTCMonth(end.getUTCMonth() + 1)\n end.setUTCDate(end.getUTCDate() - 1)\n const days: string[] = []\n for (const d = new Date(`${start}T00:00:00Z`); d <= end; d.setUTCDate(d.getUTCDate() + 1)) {\n days.push(d.toISOString().slice(0, 10))\n }\n return days\n}\n\n/** A feature key as people read it: `document_qa` → \"Document qa\". */\nconst featureLabel = (key: string) =>\n key.replace(/[_-]+/g, ' ').replace(/^\\w/, (c) => c.toUpperCase())\n\n/** A model group as people read it. */\nconst modelLabelOf = (group: string) => MODEL_GROUP_LABELS[group] ?? group\n\n/**\n * Rows of one project's usage: a row per day and model group. The days without usage get a row of\n * 0, so a chart by day spans the whole billing period.\n */\nexport function usageRows(\n usage: ProjectUsageResponse,\n project: string,\n modelLabel: (group: string) => string = modelLabelOf\n): DatasetRow[] {\n const rows: DatasetRow[] = (usage.daily ?? []).flatMap((day) =>\n Object.entries(day.model_groups ?? {}).map(([group, mg]) => ({\n day: day.date,\n project,\n model: modelLabel(group),\n spend: mg.spend ?? 0,\n tokens: mg.total_tokens ?? 0,\n requests: (mg.successful_requests ?? 0) + (mg.failed_requests ?? 0),\n }))\n )\n const model = rows[0]?.model\n if (!usage.period_start || model === undefined) return rows\n const used = new Set(rows.map((r) => r.day))\n const gaps = periodDays(usage.period_start)\n .filter((day) => !used.has(day))\n .map((day) => ({ day, project, model, spend: 0, tokens: 0, requests: 0 }))\n return [...rows, ...gaps]\n}\n\n/** Workspace and member names by external id, from the workspaces the user can see. */\nfunction usageNamesOf(workspaces: readonly WorkspaceResponse[]): Record<string, string> {\n const names: Record<string, string> = {}\n for (const ws of workspaces) {\n names[ws.external_id] = ws.name\n for (const wu of ws.users ?? []) {\n const user = wu.user\n if (user?.external_id && !names[user.external_id]) {\n names[user.external_id] = getUserDisplayName(user)\n }\n }\n }\n return names\n}\n\n/** Rows of one project's period totals by `by`: a row per name. */\nfunction usageBreakdownRows(\n usage: ProjectUsageResponse,\n project: string,\n by: UsageBreakdownBy,\n names: Readonly<Record<string, string>> = {},\n totalLabel = 'Total'\n): DatasetRow[] {\n if (by === 'total') {\n return [\n {\n project,\n name: totalLabel,\n spend: usage.total_spend ?? 0,\n tokens: usage.total_tokens ?? 0,\n requests: usage.total_requests ?? 0,\n },\n ]\n }\n if (by === 'model') {\n return Object.entries(usage.model_groups ?? {}).map(([group, mg]) => ({\n project,\n name: names[group] ?? modelLabelOf(group),\n spend: mg.spend ?? 0,\n tokens: mg.total_tokens ?? 0,\n requests: (mg.successful_requests ?? 0) + (mg.failed_requests ?? 0),\n }))\n }\n const totals =\n by === 'workspace' ? usage.by_workspace : by === 'feature' ? usage.by_feature : usage.by_user\n return Object.entries(totals ?? {}).map(([key, t]) => ({\n project,\n name: by === 'feature' ? featureLabel(key) : (names[key] ?? key),\n spend: t.spend ?? 0,\n tokens: t.total_tokens ?? 0,\n requests: t.requests ?? 0,\n }))\n}\n\ninterface UsageResponses {\n /** Each project read with its usage (absent when it could not be read). */\n usages:\n | {\n project: ProjectResponse | { external_id: string; name: string }\n usage?: ProjectUsageResponse\n }[]\n | undefined\n isLoading: boolean\n error: unknown\n}\n\n/** The usage of the project asked for, or of every project the user owns. */\nfunction useUsageResponses(params: DataSourceParams, enabled: boolean): UsageResponses {\n const arbi = useArbi()\n const monthsBack = monthsBackOf(params)\n const only = projectOf(params)\n const projects = useProjects({ enabled })\n const user = useCurrentUser({ enabled: enabled && arbi.isLoggedIn && !only })\n const me = user.data?.external_id\n const list = useMemo(() => {\n const all = (projects.data as ProjectResponse[] | undefined) ?? []\n if (only) return [all.find((p) => p.external_id === only) ?? { external_id: only, name: only }]\n return ownedBy(all, me)\n }, [projects.data, me, only])\n const results = useQueries({\n queries: list.map((p) => ({\n queryKey: arbiQueryKeys.projectUsage(p.external_id, monthsBack),\n queryFn: () => arbi.projects.usage(p.external_id, monthsBack),\n enabled: enabled && arbi.isLoggedIn,\n retry: false,\n })),\n })\n const signature = results.map((r) => `${r.status}:${r.dataUpdatedAt}`).join('|')\n // `signature` stands for the results, which are a new array every render.\n const usages = useMemo(() => {\n if (results.some((r) => r.isLoading)) return undefined\n if (!only && (!projects.data || !me)) return undefined\n return results.map((r, i) => ({\n project: list[i],\n usage: r.data as ProjectUsageResponse | undefined,\n }))\n }, [projects.data, me, only, signature])\n const loading = results.some((r) => r.isLoading)\n return only\n ? // One project: its usage is the point, so its error shows (the project's name can wait).\n { usages, isLoading: loading, error: results[0]?.error ?? null }\n : {\n usages,\n isLoading: projects.isLoading || user.isLoading || loading,\n // One project's usage failing (not its owner after all, a hiccup) leaves it out.\n error: projects.error ?? user.error ?? null,\n }\n}\n\n/** The period and project parameters both sources take. */\nfunction usageParams(\n l: Pick<UsageSourceLabels, 'period' | 'periods' | 'projectParam' | 'allProjects'>\n): DataSourceParam[] {\n const periodOptions = {\n options: [\n { value: '0', label: l.periods.current },\n { value: '1', label: l.periods.previous },\n ],\n isLoading: false,\n }\n return [\n {\n id: 'period',\n label: l.period,\n placeholder: l.periods.current,\n useOptions: () => periodOptions,\n },\n {\n id: 'project',\n label: l.projectParam,\n placeholder: l.allProjects,\n useOptions() {\n const arbi = useArbi()\n const projects = useProjects()\n const user = useCurrentUser({ enabled: arbi.isLoggedIn })\n const me = user.data?.external_id\n const options = useMemo(\n () => ownedBy(projects.data, me).map((p) => ({ value: p.external_id, label: p.name })),\n [projects.data, me]\n )\n return { options, isLoading: projects.isLoading || user.isLoading }\n },\n },\n ]\n}\n\nexport function createUsageSource(labels?: Partial<UsageSourceLabels>): DataSource {\n const l = { ...DEFAULT_USAGE_SOURCE_LABELS, ...labels }\n const fields: DatasetField[] = [\n { id: 'day', label: l.day, type: 'date' },\n { id: 'project', label: l.project, type: 'string' },\n { id: 'model', label: l.model, type: 'string' },\n { id: 'spend', label: l.spend, type: 'number', unit: 'gbp' },\n { id: 'tokens', label: l.tokens, type: 'number', unit: 'tokens' },\n { id: 'requests', label: l.requests, type: 'number' },\n ]\n return defineRowsSource({\n id: 'usage',\n label: l.source,\n description: l.description,\n params: usageParams(l),\n useFields: staticFields(fields),\n useRows(params, enabled): RowsState {\n const { usages, isLoading, error } = useUsageResponses(params, enabled)\n const rows = useMemo(\n () => usages?.flatMap((u) => (u.usage ? usageRows(u.usage, u.project.name) : [])),\n [usages]\n )\n return { rows, isLoading, error }\n },\n })\n}\n\nexport function createUsageBreakdownSource(\n labels?: Partial<UsageBreakdownSourceLabels>\n): DataSource {\n const l = { ...DEFAULT_USAGE_BREAKDOWN_SOURCE_LABELS, ...labels }\n const fieldsBy = Object.fromEntries(\n BREAKDOWNS.map((by): [UsageBreakdownBy, DataSourceFieldsState] => [\n by,\n {\n fields: [\n { id: 'project', label: l.project, type: 'string' },\n { id: 'name', label: l.by[by], type: 'string' },\n { id: 'spend', label: l.spend, type: 'number', unit: 'gbp' },\n { id: 'tokens', label: l.tokens, type: 'number', unit: 'tokens' },\n { id: 'requests', label: l.requests, type: 'number' },\n ],\n isLoading: false,\n error: null,\n },\n ])\n ) as Record<UsageBreakdownBy, DataSourceFieldsState>\n const byOptions = {\n options: BREAKDOWNS.map((by) => ({ value: by, label: l.by[by] })),\n isLoading: false,\n }\n return defineRowsSource({\n id: 'usage-breakdown',\n label: l.source,\n description: l.description,\n params: [\n ...usageParams(l),\n { id: 'by', label: l.breakdown, placeholder: l.by.user, useOptions: () => byOptions },\n ],\n useFields: (params) => fieldsBy[breakdownOf(params)],\n useRows(params, enabled): RowsState {\n const by = breakdownOf(params)\n const { usages, isLoading, error } = useUsageResponses(params, enabled)\n // Names only matter for people and workspaces; models and features name themselves.\n const workspaces = useWorkspaces({\n enabled: enabled && (by === 'user' || by === 'workspace'),\n })\n const names = useMemo(\n () => usageNamesOf((workspaces.data as WorkspaceResponse[] | undefined) ?? []),\n [workspaces.data]\n )\n const rows = useMemo(\n () =>\n usages?.flatMap((u) =>\n u.usage ? usageBreakdownRows(u.usage, u.project.name, by, names, l.by.total) : []\n ),\n [usages, by, names, l.by.total]\n )\n return { rows, isLoading, error }\n },\n })\n}\n","/**\n * The workspaces the user can see as a dataset: a row per workspace with its project, how many\n * documents, threads and members it has, and its stored files. Documents or storage by workspace or\n * by project are a group-by and a sum away. Reads the shared lists (`useWorkspaces`, `useProjects`).\n */\nimport { useMemo } from 'react'\nimport { useProjects, useWorkspaces } from '../../hooks'\nimport { defineRowsSource, staticFields } from '../rows-source'\nimport type { DataSource, DatasetField, DatasetRow } from '../types'\n\nexport interface WorkspacesSourceLabels {\n source: string\n description: string\n name: string\n project: string\n documents: string\n threads: string\n members: string\n storage: string\n created: string\n updated: string\n shared: string\n}\n\nexport const DEFAULT_WORKSPACES_SOURCE_LABELS: WorkspacesSourceLabels = {\n source: 'Workspaces',\n description: 'Your workspaces: their project, documents, threads, members and storage.',\n name: 'Workspace',\n project: 'Project',\n documents: 'Documents',\n threads: 'Threads',\n members: 'Members',\n storage: 'Storage (MB)',\n created: 'Created',\n updated: 'Updated',\n shared: 'Public',\n}\n\ninterface WorkspaceLike {\n external_id: string\n name: string\n project_ext_id?: string | null\n shared_document_count?: number | null\n private_document_count?: number | null\n shared_conversation_count?: number | null\n private_conversation_count?: number | null\n users?: unknown[] | null\n user_files_mb?: number | null\n created_at?: string | null\n updated_at?: string | null\n is_public?: boolean | null\n}\n\nexport function createWorkspacesSource(labels?: Partial<WorkspacesSourceLabels>): DataSource {\n const l = { ...DEFAULT_WORKSPACES_SOURCE_LABELS, ...labels }\n const fields: DatasetField[] = [\n { id: 'name', label: l.name, type: 'string' },\n { id: 'project', label: l.project, type: 'string' },\n { id: 'documents', label: l.documents, type: 'number' },\n { id: 'threads', label: l.threads, type: 'number' },\n { id: 'members', label: l.members, type: 'number' },\n { id: 'storage', label: l.storage, type: 'number', unit: 'MB' },\n { id: 'created', label: l.created, type: 'date' },\n { id: 'updated', label: l.updated, type: 'date' },\n { id: 'shared', label: l.shared, type: 'boolean' },\n ]\n return defineRowsSource({\n id: 'workspaces',\n label: l.source,\n description: l.description,\n useFields: staticFields(fields),\n useRows(_params, enabled) {\n const workspaces = useWorkspaces({ enabled })\n const projects = useProjects({ enabled })\n const rows = useMemo(() => {\n const list = workspaces.data as WorkspaceLike[] | undefined\n if (!list) return undefined\n const projectNames = new Map(\n ((projects.data ?? []) as Array<{ external_id: string; name: string }>).map((p) => [\n p.external_id,\n p.name,\n ])\n )\n return list.map((w): DatasetRow => ({\n name: w.name,\n project: w.project_ext_id ? (projectNames.get(w.project_ext_id) ?? null) : null,\n documents: (w.shared_document_count ?? 0) + (w.private_document_count ?? 0),\n threads: (w.shared_conversation_count ?? 0) + (w.private_conversation_count ?? 0),\n members: w.users?.length ?? 0,\n storage: Math.round((w.user_files_mb ?? 0) * 10) / 10,\n created: w.created_at ?? null,\n updated: w.updated_at ?? null,\n shared: w.is_public ?? null,\n }))\n }, [workspaces.data, projects.data])\n return { rows, isLoading: workspaces.isLoading, error: workspaces.error }\n },\n })\n}\n","/**\n * The data sources a host offers, by id: the built-in adapters (AI usage and its breakdown, documents, threads,\n * projects, workspaces, tags, facts, workflows, recent activity, databases) plus the host's own from `<ArbiHost config={{ dashboards: { sources } }}>`\n * (a source with a built-in id replaces it, which is how a site relabels one in its own words).\n */\nimport { useMemo } from 'react'\nimport { useArbiHost } from '../host/config'\nimport { createActivitySource } from './sources/activity'\nimport { createConversationsSource } from './sources/conversations'\nimport { createDatabaseSource } from './sources/database'\nimport { createDocumentsSource } from './sources/documents'\nimport { createFactsSource } from './sources/facts'\nimport { createProjectsSource } from './sources/projects'\nimport { createTagsSource } from './sources/tags'\nimport { createUsageBreakdownSource, createUsageSource } from './sources/usage'\nimport { createWorkflowsSource } from './sources/workflows'\nimport { createWorkspacesSource } from './sources/workspaces'\nimport type { DataSource } from './types'\nimport type { DashboardStore } from './store'\n\n/** What a host configures for charts and dashboards. */\nexport interface DashboardsHost {\n /** More sources, or replacements for built-ins (same `id`). */\n sources?: readonly DataSource[]\n /** Leave the built-in sources out (only `sources` are offered). */\n builtins?: false\n /**\n * Where saved dashboards are kept, as a hook. Absent: the person's own, sealed to their key\n * (`useUserDashboardStore`); `useDatabaseDashboardStore` keeps them in the open workspace.\n */\n useStore?: () => DashboardStore\n}\n\n/** A lookup of sources by id, in the order offered. */\nexport interface DataSourceRegistry {\n list: readonly DataSource[]\n get: (id: string) => DataSource | undefined\n}\n\n/** Built-in sources with their default (neutral) labels. */\nexport const BUILTIN_DATA_SOURCES: readonly DataSource[] = [\n createUsageSource(),\n createUsageBreakdownSource(),\n createDocumentsSource(),\n createConversationsSource(),\n createProjectsSource(),\n createWorkspacesSource(),\n createTagsSource(),\n createFactsSource(),\n createWorkflowsSource(),\n createActivitySource(),\n createDatabaseSource(),\n]\n\n/** A registry over `sources`; a later source replaces an earlier one with the same id. */\nexport function createDataSourceRegistry(sources: readonly DataSource[]): DataSourceRegistry {\n const byId = new Map<string, DataSource>()\n for (const source of sources) byId.set(source.id, source)\n const list = [...byId.values()]\n return { list, get: (id) => byId.get(id) }\n}\n\n/** The sources offered here: the built-ins and the host's (`dashboards.sources`). */\nexport function useDataSources(): DataSourceRegistry {\n const { dashboards } = useArbiHost()\n return useMemo(\n () =>\n createDataSourceRegistry([\n ...(dashboards?.builtins === false ? [] : BUILTIN_DATA_SOURCES),\n ...(dashboards?.sources ?? []),\n ]),\n [dashboards]\n )\n}\n","/**\n * Saved dashboards: where `DashboardSpec`s are kept, and the hooks that read and write them.\n *\n * Default store: the person's own (`useUserDashboardStore`, `/v1/user/dashboards`), each spec sealed\n * in the browser to their own key, so Analytics is theirs across workspaces. A host keeps them\n * elsewhere with `<ArbiHost config={{ dashboards: { useStore } }}>`, e.g. in a database of the open\n * workspace, shared with its members (`useDatabaseDashboardStore`).\n */\nimport { useMemo } from 'react'\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'\nimport { useArbiHost } from '../host/config'\nimport { useArbi } from '../useArbi'\nimport { arbiQueryKeys } from '../query-keys'\nimport type { DashboardSpec, PanelSpec } from './types'\n\n/**\n * The transient view through which a host asks Analytics to chart a database (\"Chart this\"): set it to\n * `{ id, name, workspaceId }` and open the page, which makes a dashboard on that database and clears it.\n */\nexport const ANALYTICS_CHART_VIEW = 'analytics.chartDatabase'\n\n/** A database Analytics is asked to chart. */\nexport interface AnalyticsChartRequest {\n id: string\n name: string\n /** The database's workspace, so the new panels read it from anywhere. */\n workspaceId?: string\n}\n\n/** A dashboard as stored. */\nexport interface SavedDashboard {\n id: string\n spec: DashboardSpec\n updatedAt?: string\n /** It could not be opened (sealed under another key, or not a dashboard): it can only be deleted. */\n unreadable?: boolean\n}\n\n/** Where dashboards are kept. */\nexport interface DashboardStore {\n /** What the saved list is cached under (the workspace it belongs to). `null`: not available. */\n scope: string | null\n list: () => Promise<SavedDashboard[]>\n /** Create (no `id`) or replace a dashboard; resolves with it as stored. */\n save: (dashboard: { id?: string; spec: DashboardSpec }) => Promise<SavedDashboard>\n remove: (id: string) => Promise<void>\n}\n\n/** The longest spec a database text cell holds (the server's limit). */\nexport const MAX_DASHBOARD_SPEC_CHARS = 10_000\n\nconst isObject = (v: unknown): v is Record<string, unknown> =>\n typeof v === 'object' && v !== null && !Array.isArray(v)\n\nfunction isPanel(v: unknown): v is PanelSpec {\n return (\n isObject(v) &&\n typeof v.id === 'string' &&\n typeof v.title === 'string' &&\n isObject(v.source) &&\n typeof v.source.id === 'string' &&\n isObject(v.chart) &&\n typeof v.chart.type === 'string'\n )\n}\n\n/** A stored spec, checked: `null` when it is not a dashboard (malformed panels are dropped). */\nexport function parseDashboardSpec(value: unknown): DashboardSpec | null {\n let parsed = value\n if (typeof value === 'string') {\n try {\n parsed = JSON.parse(value)\n } catch {\n return null\n }\n }\n if (!isObject(parsed) || parsed.version !== 1 || typeof parsed.title !== 'string') return null\n const panels = Array.isArray(parsed.panels) ? parsed.panels.filter(isPanel) : []\n return {\n version: 1,\n title: parsed.title,\n ...(typeof parsed.description === 'string' ? { description: parsed.description } : {}),\n panels,\n }\n}\n\n/** A spec as JSON for storage; throws when it is longer than the store holds. */\nexport function serializeDashboardSpec(spec: DashboardSpec, max = MAX_DASHBOARD_SPEC_CHARS) {\n const json = JSON.stringify(spec)\n if (json.length > max) {\n throw new Error(\n `This dashboard is too large to save (${json.length.toLocaleString('en-GB')} characters, at most ${max.toLocaleString('en-GB')}). Remove a panel or split it into two dashboards.`\n )\n }\n return json\n}\n\n/** The person's own dashboards (`arbi.dashboards`: sealed to their key); unavailable signed out. */\nexport function useUserDashboardStore(): DashboardStore {\n const arbi = useArbi()\n const scope = arbi.isLoggedIn ? (arbi.user.identity()?.externalId ?? null) : null\n return useMemo(\n () => ({\n scope: scope && `user:${scope}`,\n list: async () =>\n (await arbi.dashboards.list()).map(({ id, json, updatedAt }) => {\n const spec = json === null ? null : parseDashboardSpec(json)\n return spec\n ? { id, spec, updatedAt }\n : {\n id,\n spec: { version: 1 as const, title: '', panels: [] },\n updatedAt,\n unreadable: true,\n }\n }),\n async save({ id, spec }) {\n const saved = await arbi.dashboards.save({ id, json: serializeDashboardSpec(spec) })\n return { id: saved.id, spec, updatedAt: saved.updatedAt }\n },\n remove: (id) => arbi.dashboards.remove(id),\n }),\n [arbi, scope]\n )\n}\n\n/** A store kept in memory (a demo, a test, a page without a workspace). */\nexport function createMemoryDashboardStore(\n initial: readonly SavedDashboard[] = [],\n scope = 'memory'\n): DashboardStore {\n let items = [...initial]\n let next = items.length + 1\n return {\n scope,\n list: async () => items.map((d) => ({ ...d })),\n save: async ({ id, spec }) => {\n const saved = { id: id ?? `dash-${next++}`, spec, updatedAt: new Date().toISOString() }\n items = id ? items.map((d) => (d.id === id ? saved : d)) : [...items, saved]\n return saved\n },\n remove: async (id) => {\n items = items.filter((d) => d.id !== id)\n },\n }\n}\n\nexport interface DatabaseDashboardStoreOptions {\n /** The database's name. Default \"Dashboards\". */\n name?: string\n}\n\nconst NAME_COLUMN = 'Name'\nconst SPEC_COLUMN = 'Spec'\n\n/** Dashboards kept as rows of a database of the open workspace (made on the first save). */\nexport function useDatabaseDashboardStore(\n options: DatabaseDashboardStoreOptions = {}\n): DashboardStore {\n const arbi = useArbi()\n const queryClient = useQueryClient()\n const name = options.name ?? 'Dashboards'\n const workspaceId = arbi.hasWorkspace ? arbi.getWorkspaceId() : null\n return useMemo(() => {\n /** The workspace's own dashboards database, if there is one. */\n async function find() {\n const all = await arbi.databases.list()\n return all.find(\n (d) =>\n d.editable &&\n d.workspace_id === workspaceId &&\n d.name === name &&\n (d.columns ?? []).some((c) => c.name === SPEC_COLUMN)\n )\n }\n /**\n * Run `read` only while this store's workspace is the one open on the server (databases are\n * listed and created there): a switch meanwhile drops it, so nothing is cached, or created,\n * as another workspace's.\n */\n function inWorkspace<T>(read: () => Promise<T>): Promise<T> {\n return workspaceId ? arbi.readInWorkspace(workspaceId, read) : read()\n }\n async function ensure() {\n return inWorkspace(ensureHere)\n }\n async function ensureHere() {\n const found = await find()\n if (found) return found\n const created = await arbi.databases.create({\n name,\n description: 'Saved dashboards (written by the Dashboards page).',\n columns: [\n { name: NAME_COLUMN, type: 'text' },\n { name: SPEC_COLUMN, type: 'text' },\n ],\n })\n void queryClient.invalidateQueries({\n queryKey: arbiQueryKeys.databaseList(workspaceId ?? undefined),\n })\n return created\n }\n return {\n scope: workspaceId,\n list: () =>\n inWorkspace(async () => {\n const database = await find()\n if (!database) return []\n const spec = database.columns?.find((c) => c.name === SPEC_COLUMN)?.id ?? SPEC_COLUMN\n const page = await arbi.databases.rows(database.id, { limit: 1000 })\n return page.rows.flatMap((row) => {\n const parsed = parseDashboardSpec(row.values[spec])\n return parsed ? [{ id: row.id, spec: parsed, updatedAt: row.updated_at }] : []\n })\n }),\n async save({ id, spec }) {\n const values = { [NAME_COLUMN]: spec.title, [SPEC_COLUMN]: serializeDashboardSpec(spec) }\n const database = await ensure()\n const row = id\n ? await arbi.databases.updateRow(database.id, id, values)\n : (await arbi.databases.addRows(database.id, [{ values }]))[0]\n // The database's own rows changed (it shows in Databases like any other).\n void queryClient.invalidateQueries({\n queryKey: arbiQueryKeys.databaseRows(workspaceId ?? '', database.id),\n })\n return { id: row.id, spec, updatedAt: row.updated_at }\n },\n async remove(id) {\n const database = await find()\n if (!database) return\n await arbi.databases.deleteRows(database.id, [id])\n void queryClient.invalidateQueries({\n queryKey: arbiQueryKeys.databaseRows(workspaceId ?? '', database.id),\n })\n },\n }\n }, [arbi, queryClient, name, workspaceId])\n}\n\n/** The store dashboards are kept in here: the host's (`dashboards.useStore`) or a database. */\nexport function useDashboardStore(): DashboardStore {\n const { dashboards } = useArbiHost()\n // The host's configuration is one object for its life: the same hook runs every render.\n return (dashboards?.useStore ?? useUserDashboardStore)()\n}\n\n/** The saved dashboards, oldest first. */\nexport function useSavedDashboards(store: DashboardStore) {\n return useQuery({\n queryKey: arbiQueryKeys.dashboards(store.scope ?? ''),\n queryFn: () => store.list(),\n enabled: store.scope !== null,\n })\n}\n\n/** Save a dashboard (create without `id`); the saved list takes it straight away. */\nexport function useSaveDashboard(store: DashboardStore) {\n const queryClient = useQueryClient()\n const key = arbiQueryKeys.dashboards(store.scope ?? '')\n return useMutation({\n mutationFn: (dashboard: { id?: string; spec: DashboardSpec }) => store.save(dashboard),\n onSuccess: (saved) => {\n queryClient.setQueryData<SavedDashboard[]>(key, (old = []) =>\n old.some((d) => d.id === saved.id)\n ? old.map((d) => (d.id === saved.id ? saved : d))\n : [...old, saved]\n )\n },\n })\n}\n\nexport function useDeleteDashboard(store: DashboardStore) {\n const queryClient = useQueryClient()\n const key = arbiQueryKeys.dashboards(store.scope ?? '')\n return useMutation({\n mutationFn: (id: string) => store.remove(id),\n onSuccess: (_void, id) => {\n queryClient.setQueryData<SavedDashboard[]>(key, (old = []) => old.filter((d) => d.id !== id))\n },\n })\n}\n","/**\n * Cited passages' text, read live from their documents. A citation stores only chunk ids (plus the\n * document and page); the passage text stays encrypted in the document, so an excerpt is read on\n * demand from the document's parsed content — the same `final` stage the viewer renders and\n * highlights from, cached with it (`useParsedDocument`), one read per distinct document.\n */\n\nimport { useMemo } from 'react'\nimport { useQueries } from '@tanstack/react-query'\nimport { useArbi } from '../useArbi'\nimport { arbiQueryKeys } from '../hooks'\nimport type { ParsedDocument } from './parsed-types'\n\n/** A passage's excerpt (raw markdown) by its chunk id; undefined while loading or unknown. */\nexport type QuoteResolver = (chunkId: string) => string | undefined\n\n/** A passage's 0-based position in its document (`Infinity` while loading or unknown). */\nexport type OrderResolver = (chunkId: string) => number\n\nexport interface PassageResolvers {\n quoteFor: QuoteResolver\n orderOf: OrderResolver\n}\n\n/** The parsed document lasts until it is re-ingested: keep it while several citations open. */\nconst PARSED_STALE_TIME = 5 * 60 * 1000\n\n/** Every passage of the read documents by chunk id: its text and its place in its document. */\ntype PassageIndex = Map<string, { text: string; order: number }>\n\n/** One index over the documents' parsed content (newlines kept, uncapped: it renders as markdown). */\nfunction indexPassages(results: ReadonlyArray<{ data?: ParsedDocument }>): PassageIndex {\n const index: PassageIndex = new Map()\n for (const r of results)\n (r.data?.chunks ?? []).forEach((chunk, order) => {\n const id = chunk.metadata?.chunk_ext_id\n if (id && !index.has(id)) index.set(id, { text: (chunk.content ?? '').trim(), order })\n })\n return index\n}\n\n/**\n * Resolve the passages of these documents (`null`: none yet — e.g. until a list is opened, so a\n * closed popover reads nothing).\n */\nexport function usePassageQuotes(docIds: readonly string[] | null | undefined): PassageResolvers {\n const arbi = useArbi()\n const passages = useQueries({\n queries: [...new Set(docIds ?? [])].map((docId) => ({\n queryKey: arbiQueryKeys.parsedDoc(docId, 'final'),\n queryFn: () =>\n arbi.documents.getParsedContent(docId, 'final') as unknown as Promise<ParsedDocument>,\n enabled: arbi.hasWorkspace,\n staleTime: PARSED_STALE_TIME,\n })),\n combine: indexPassages,\n })\n return useMemo(\n () => ({\n quoteFor: (chunkId: string) => passages.get(chunkId)?.text || undefined,\n orderOf: (chunkId: string) => passages.get(chunkId)?.order ?? Number.POSITIVE_INFINITY,\n }),\n [passages]\n )\n}\n","/**\n * The query cache kept for an offline start (`createArbiQueryClient({ persist: true })`).\n *\n * Persists a *metadata-only* slice of the query cache to IndexedDB so an already signed-in user\n * can cold-start offline and still see their workspaces and documents list (and open a pinned\n * document). Deliberately conservative about what is written to disk: only the families\n * {@link isOfflineReadableArbiQuery} names; NEVER conversations, messages or document bytes (the\n * pinned bytes live separately, encrypted: `offline-documents.ts`).\n *\n * An async IndexedDB persister (idb-keyval, structured clone) rather than the JSON sync persister:\n * the robust choice for binary-capable storage.\n */\n\nimport { get, set, del } from 'idb-keyval'\nimport type {\n PersistedClient,\n Persister,\n PersistQueryClientOptions,\n} from '@tanstack/react-query-persist-client'\nimport {\n isOfflineReadableArbiQuery,\n isReplayableArbiMutation,\n isRestorableArbiQueryOnline,\n} from './offline'\n\nconst IDB_KEY = 'arbi-react-query-cache'\n\n// Which account the persisted offline queue belongs to. The queue is one record\n// per browser, so it is only valid for the account that wrote it.\nconst OWNER_KEY = 'arbi-react-query-cache-owner'\n\n// Bump to invalidate everyone's persisted cache after an incompatible change.\n// v2: documents and their writes moved to the `@arbidocs/react` keys.\nconst CACHE_BUSTER = 'arbi-rq-v2'\n\nconst MAX_AGE = 1000 * 60 * 60 * 24 * 7 // 7 days\n\n/** What `<PersistQueryClientProvider persistOptions>` takes for the package's offline cache. */\nexport type ArbiQueryPersistOptions = Omit<PersistQueryClientOptions, 'queryClient'>\n\nfunction createIDBPersister(): Persister {\n return {\n persistClient: (client: PersistedClient) => set(IDB_KEY, client),\n // The offline persister must be INERT when online. Because the documents\n // list never auto-refetches, a rehydrated copy would be trusted\n // indefinitely and surface stale statuses across a reload — e.g. a document\n // that finished processing while the tab was closed (its one-shot\n // completion WS event is long gone) still renders as \"queued\". So when\n // online we strip that query from the restored cache; it then loads\n // fresh from the server exactly as it did before offline support existed.\n // A document caught mid-processing is stripped for the same reason, and the\n // entitlements are read fresh (isRestorableArbiQueryOnline).\n // Queued offline mutations and all other queries restore normally. When\n // offline we keep everything so the pages still have something to show.\n restoreClient: async () => {\n const persisted = await get<PersistedClient>(IDB_KEY)\n if (!persisted) return persisted\n const isOffline = typeof navigator !== 'undefined' && navigator.onLine === false\n if (isOffline) return persisted\n persisted.clientState.queries = persisted.clientState.queries.filter((q) =>\n isRestorableArbiQueryOnline(q.queryKey, q.state.data)\n )\n return persisted\n },\n removeClient: () => del(IDB_KEY),\n }\n}\n\n/**\n * Hand the offline write queue to the account that is signing in. Queued edits\n * are replayed under whoever is logged in on reload, so a queue left by a\n * different account (or one whose owner was never recorded) must be discarded\n * here — otherwise another person's edit syncs, and fails, as this user.\n * The same account keeps its queue across logins.\n */\nexport async function claimOfflineQueue(userExtId: string): Promise<void> {\n const owner = await get<string>(OWNER_KEY)\n if (owner !== userExtId) await del(IDB_KEY)\n await set(OWNER_KEY, userExtId)\n}\n\n/** The persistence of the offline cache (see the module comment). */\nexport function createArbiQueryPersistOptions(): ArbiQueryPersistOptions {\n return {\n persister: createIDBPersister(),\n maxAge: MAX_AGE,\n buster: CACHE_BUSTER,\n dehydrateOptions: {\n // Persist mutations that were paused offline so a queued write (apply tag,\n // edit field) survives a reload and replays on reconnect. Resuming them\n // after a reload requires the registered mutation defaults\n // (registerArbiMutationDefaults). Scope to real offline EDITS: an incidental\n // paused mutation (e.g. workspace-open) isn't a user change to queue/replay.\n shouldDehydrateMutation: (mutation) =>\n mutation.state.isPaused && isReplayableArbiMutation(mutation.options.mutationKey),\n shouldDehydrateQuery: (query) => {\n if (query.state.status !== 'success') return false\n // Every query key comes from the package factory: its offline families are the whole\n // list (document metadata, the workspace list, the settings, the projects, the\n // entitlements; never a document's content or bytes).\n return isOfflineReadableArbiQuery(query.queryKey)\n },\n },\n }\n}\n","/**\n * The React Query client every ARBI host shares: ARBI-frontend's own, and a blocks-only site's\n * through `defaultHost`. Call once per page, at module scope.\n *\n * const { queryClient } = createArbiQueryClient()\n * const { queryClient, persistOptions } = createArbiQueryClient({ persist: true })\n * <PersistQueryClientProvider client={queryClient} persistOptions={persistOptions}>\n *\n * Reads are fresh for 5 minutes and kept 30, are not re-read on window focus, and retry twice\n * with backoff, never on a 4xx (but 408/429) nor on a read a sign-out aborted. Writes never retry.\n * A write refused because the account's deletion is pending, or dropped by the client's settings\n * write breaker, tells the user. With `persist`, the offline slice of the cache is kept on this\n * device (`query-persist.ts`). Sign-out and sign-in clear it with `queryClient.clear()`; the same\n * client stays, so the provider and every hook keep theirs.\n */\n\nimport { MutationCache, QueryClient } from '@tanstack/react-query'\nimport { isAbortError, SETTINGS_WRITE_BREAKER_CODE } from '@arbidocs/client'\nimport { notify } from './notifications/notify-store'\nimport { createArbiQueryPersistOptions, type ArbiQueryPersistOptions } from './query-persist'\n\n/**\n * Returns true for HTTP 4xx errors that should NOT be retried, except for\n * 408 (Request Timeout) and 429 (Too Many Requests) which are transient\n * and worth retrying.\n *\n * Auth errors (401/403) are already handled by the client's re-login, so\n * React Query does not stack additional retries on top of its retry.\n */\nexport function isClientError(error: unknown): boolean {\n if (error && typeof error === 'object' && 'status' in error) {\n const status = (error as { status?: number }).status\n if (typeof status === 'number' && status >= 400 && status < 500) {\n // Transient client errors — allow retry\n if (status === 408 || status === 429) return false\n return true\n }\n }\n return false\n}\n\n/**\n * Exponential backoff with jitter.\n * attempt 0 → ~1 s, attempt 1 → ~2 s, capped at 30 s.\n */\nexport function retryDelay(attempt: number): number {\n return Math.min(1000 * 2 ** attempt, 30_000) + Math.random() * 500\n}\n\n/** Whether a failed read is tried again (`failureCount` failures so far). */\nexport function shouldRetryQuery(failureCount: number, error: unknown): boolean {\n return failureCount < 2 && !isClientError(error) && !isAbortError(error)\n}\n\n// A write storm fails hundreds of writes a minute: tell the user once per minute, not per write.\nconst BREAKER_NOTICE_MS = 60_000\n\nexport interface ArbiQueryClientOptions {\n /** Keep the offline slice of the cache on this device, for an offline start. */\n persist?: boolean\n}\n\nexport interface ArbiQueryClient {\n queryClient: QueryClient\n /** For `<PersistQueryClientProvider persistOptions>`; `null` without `persist`. */\n persistOptions: ArbiQueryPersistOptions | null\n}\n\n/** The shared React Query client (see the module comment). */\nexport function createArbiQueryClient(options: {\n persist: true\n}): ArbiQueryClient & { persistOptions: ArbiQueryPersistOptions }\nexport function createArbiQueryClient(options?: ArbiQueryClientOptions): ArbiQueryClient\nexport function createArbiQueryClient({\n persist = false,\n}: ArbiQueryClientOptions = {}): ArbiQueryClient {\n let breakerNoticeAt = -Infinity\n const queryClient = new QueryClient({\n mutationCache: new MutationCache({\n onError: (error: unknown) => {\n const { detail, code } = (error ?? {}) as { detail?: unknown; code?: unknown }\n // The structured 403 of an account whose deletion is pending.\n if (detail === 'account_deletion_pending') {\n notify.error('Your account is read-only while deletion is pending.')\n }\n if (\n code === SETTINGS_WRITE_BREAKER_CODE &&\n Date.now() - breakerNoticeAt > BREAKER_NOTICE_MS\n ) {\n breakerNoticeAt = Date.now()\n notify.warning('Settings are being saved too frequently', {\n description: 'Some changes were not saved. Refresh the page if this keeps happening.',\n duration: 10_000,\n })\n }\n },\n }),\n defaultOptions: {\n queries: {\n staleTime: 1000 * 60 * 5,\n refetchOnWindowFocus: false,\n retry: shouldRetryQuery,\n retryDelay,\n gcTime: 1000 * 60 * 30,\n },\n mutations: {\n retry: false,\n },\n },\n })\n return { queryClient, persistOptions: persist ? createArbiQueryPersistOptions() : null }\n}\n","/**\n * Project details (budget, client, stage, lead, fields) and spend by conversation.\n *\n * Requires an `ArbiHost` (with an `arbi`) and a React Query client above it.\n */\n\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'\nimport type {\n ProjectConversationUsageResponse,\n ProjectResponse,\n ProjectUpdateRequest,\n} from '@arbidocs/sdk/browser'\nimport { useArbi } from './useArbi'\nimport { arbiQueryKeys } from './hooks'\n\n/**\n * Patch a project (owner only): name, daily cap, and the details a host sets (`budget` in minor\n * units, `client`, `client_ref`, `stage`, `lead_user`, `fields` merged key by key, `field_schema`).\n * The project list and the workspace list (which carries project names) refresh.\n */\nexport function useUpdateProjectFields() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: ({\n projectExtId,\n patch,\n }: {\n projectExtId: string\n patch: ProjectUpdateRequest\n }): Promise<ProjectResponse> => arbi.projects.update(projectExtId, patch),\n onSuccess: () => {\n void qc.invalidateQueries({ queryKey: arbiQueryKeys.projects() })\n // Each workspace carries its project's name: a rename shows there at once.\n void qc.invalidateQueries({ queryKey: arbiQueryKeys.workspaces() })\n },\n })\n}\n\n/** A project's spend by conversation (and what no conversation accounts for), in £. */\nexport function useProjectConversationUsage(\n projectExtId: string | undefined,\n monthsBack: number = 0,\n options?: { enabled?: boolean }\n) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.projectConversationUsage(projectExtId ?? '', monthsBack),\n queryFn: (): Promise<ProjectConversationUsageResponse> =>\n arbi.projects.usageByConversation(projectExtId as string, monthsBack),\n enabled: (options?.enabled ?? true) && !!projectExtId && arbi.isLoggedIn,\n })\n}\n","/**\n * useChargeWatch — feedback for a money action that can take a while (\"Paying…\", \"Upgrading…\").\n *\n * - After 5 s pending, `isSlow` turns on (show STILL_WORKING) and the projects list is refetched\n * every 3 s, so a change that lands while the request is still open shows up here.\n * - `watch(landed, onLanded)` at press time: `landed(project)` says whether the change shows on\n * the project. The first time it does, `onLanded` runs once (from a poll, the request's success,\n * or a check after a failure), so success is never reported twice.\n * - `settleFailure(onNotLanded)` after an error that doesn't say what happened (timeout, 5xx):\n * refetch, and report success if the change landed after all; otherwise `onNotLanded`.\n */\n\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport { useQueryClient } from '@tanstack/react-query'\nimport type { ProjectResponse } from '@arbidocs/sdk/browser'\nimport { arbiQueryKeys } from './hooks'\n\nexport const SLOW_AFTER_MS = 5000\nexport const POLL_EVERY_MS = 3000\nexport const STILL_WORKING =\n \"Still working — confirm in your bank's tab if it opened. We'll update here.\"\n\n/** True once `isPending` has lasted `ms`. */\nexport function useIsSlow(isPending: boolean, ms = SLOW_AFTER_MS): boolean {\n const [isSlow, setIsSlow] = useState(false)\n useEffect(() => {\n if (!isPending) {\n setIsSlow(false)\n return\n }\n const timer = setTimeout(() => setIsSlow(true), ms)\n return () => clearTimeout(timer)\n }, [isPending, ms])\n return isSlow\n}\n\ninterface Watch {\n landed: (project: ProjectResponse) => boolean\n onLanded: () => void\n settled: boolean\n}\n\nexport function useChargeWatch(project: ProjectResponse, isPending: boolean) {\n const queryClient = useQueryClient()\n const isSlow = useIsSlow(isPending)\n const watchRef = useRef<Watch | null>(null)\n\n useEffect(() => {\n if (!isSlow) return\n const timer = setInterval(\n () => queryClient.invalidateQueries({ queryKey: arbiQueryKeys.projects(), exact: true }),\n POLL_EVERY_MS\n )\n return () => clearInterval(timer)\n }, [isSlow, queryClient])\n\n const settle = useCallback((ok: boolean, onNotLanded?: () => void) => {\n const watch = watchRef.current\n if (!watch || watch.settled) return\n watch.settled = true\n if (ok) watch.onLanded()\n else onNotLanded?.()\n }, [])\n\n // A refetched project that shows the change settles the action, request or no request.\n useEffect(() => {\n const watch = watchRef.current\n if (watch && !watch.settled && watch.landed(project)) settle(true)\n }, [project, settle])\n\n const watch = useCallback((landed: Watch['landed'], onLanded: Watch['onLanded']) => {\n watchRef.current = { landed, onLanded, settled: false }\n }, [])\n\n /** The request succeeded. */\n const succeeded = useCallback(() => settle(true), [settle])\n\n /** The request failed with a known refusal: nothing changed. */\n const refused = useCallback(() => settle(false), [settle])\n\n const settleFailure = useCallback(\n async (onNotLanded: () => void) => {\n const watch = watchRef.current\n if (!watch || watch.settled) return\n let fresh: ProjectResponse | undefined\n try {\n await queryClient.refetchQueries({ queryKey: arbiQueryKeys.projects(), exact: true })\n fresh = queryClient\n .getQueryData<ProjectResponse[]>(arbiQueryKeys.projects())\n ?.find((p) => p.external_id === project.external_id)\n } catch {\n fresh = undefined\n }\n settle(!!fresh && watch.landed(fresh), onNotLanded)\n },\n [queryClient, project.external_id, settle]\n )\n\n return { isSlow, watch, succeeded, refused, settleFailure }\n}\n","/**\n * Plans and billing of a project: the plans on sale, the taxed price of a purchase or a change,\n * Stripe checkout and the billing portal, add-on blocks and their settings, plan changes and\n * cancellation. Every write that changes a project refreshes the project list\n * (`arbiQueryKeys.projects()`); those that change what the user may do refresh the user settings\n * and the workspace list too.\n *\n * Requires an `ArbiHost` (with an `arbi`) and a React Query client above it.\n */\n\nimport { useMutation, useQuery, useQueryClient, type QueryClient } from '@tanstack/react-query'\nimport type {\n ProjectAddonKind,\n ProjectAddonSettingsRequest,\n ProjectCheckoutRequest,\n ProjectCreateOptions,\n ProjectNextPeriodAddonsRequest,\n ProjectPlanChangeRequest,\n ProjectQuoteRequest,\n} from '@arbidocs/sdk/browser'\nimport type { Arbi } from '@arbidocs/sdk/browser'\nimport { useArbi } from './useArbi'\nimport { arbiQueryKeys } from './hooks'\n\n/** Refresh the projects, and with `wide` the user settings and workspaces they gate. */\nfunction refreshProjects(qc: QueryClient, wide = false) {\n void qc.invalidateQueries({ queryKey: arbiQueryKeys.projects() })\n if (wide) {\n void qc.invalidateQueries({ queryKey: arbiQueryKeys.userSettings() })\n void qc.invalidateQueries({ queryKey: arbiQueryKeys.workspaces() })\n }\n}\n\n/**\n * Prices are not retried on a real failure (the UI says what failed), but a request aborted before\n * it ran (a remount cancels it, e.g. React StrictMode) runs again.\n */\nconst retryAbortOnly = (failureCount: number, error: unknown) =>\n failureCount < 1 && (error as { name?: string } | null)?.name === 'AbortError'\n\n/** Refresh the project list now (e.g. a paid project to list before its refresh returns). */\nexport function useInvalidateProjects(): () => Promise<void> {\n const qc = useQueryClient()\n return () => qc.invalidateQueries({ queryKey: arbiQueryKeys.projects() })\n}\n\n/** The plans and add-ons on sale, with their prices. */\nexport function useProducts(options?: { enabled?: boolean }) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.products(),\n queryFn: () => arbi.projects.products(),\n staleTime: 5 * 60_000,\n enabled: (options?.enabled ?? true) && arbi.isLoggedIn,\n })\n}\n\nexport interface CreateProjectVars extends ProjectCreateOptions {\n name: string\n plan?: 'free' | 'pro'\n /** Also create the project's first (encrypted) workspace, of the project's name. */\n workspace?: { description?: string | null }\n}\n\ntype CreatedProjectResponse = Awaited<ReturnType<Arbi['projects']['create']>>\ntype CreatedWorkspaceResponse = Awaited<ReturnType<Arbi['workspaces']['create']>>\n\n/** A created project, with its first workspace when one was asked for. */\nexport type CreatedProject = CreatedProjectResponse & { workspace?: CreatedWorkspaceResponse }\n\n/**\n * Create a project (Free is usable at once; Pro is pending until its checkout completes), with its\n * first workspace if asked. The project and workspace lists show them at once (updated in place,\n * then refetched); selecting the workspace is the caller's.\n */\nexport function useCreateProject() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: async ({ name, plan, workspace, ...details }: CreateProjectVars) => {\n const project: CreatedProject = await arbi.projects.create(name, plan, details)\n if (workspace) {\n project.workspace = await arbi.workspaces.create(\n name,\n project.external_id,\n workspace.description ?? null\n )\n }\n return project\n },\n onSuccess: async ({ workspace, ...project }) => {\n // A list fetch that started before the project existed must not land over the update.\n await Promise.all([\n qc.cancelQueries({ queryKey: arbiQueryKeys.projects() }),\n qc.cancelQueries({ queryKey: arbiQueryKeys.workspaces() }),\n ])\n const id = (item: { external_id: string }) => item.external_id\n qc.setQueryData(arbiQueryKeys.projects(), (old: unknown) =>\n Array.isArray(old) ? [project, ...old.filter((p) => id(p) !== project.external_id)] : old\n )\n if (workspace) {\n const listed = { ...workspace, project_ext_id: project.external_id }\n qc.setQueryData(arbiQueryKeys.workspaces(), (old: unknown) =>\n Array.isArray(old) ? [listed, ...old.filter((w) => id(w) !== workspace.external_id)] : old\n )\n }\n refreshProjects(qc, true)\n },\n })\n}\n\n/** Delete an empty project (no workspaces, no subscription). */\nexport function useDeleteProject() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: (projectExtId: string) => arbi.projects.delete(projectExtId),\n onSuccess: () => refreshProjects(qc, true),\n })\n}\n\n/** Re-read a project's subscription from Stripe (after a checkout completes). */\nexport function useRefreshProject() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: (projectExtId: string) => arbi.projects.refresh(projectExtId),\n onSuccess: () => refreshProjects(qc, true),\n })\n}\n\n/** Start an embedded Stripe checkout for a project; resolves to its `client_secret`. */\nexport function useCreateProjectCheckout() {\n const arbi = useArbi()\n return useMutation({\n mutationFn: ({ projectExtId, body }: { projectExtId: string; body: ProjectCheckoutRequest }) =>\n arbi.projects.checkout(projectExtId, body),\n })\n}\n\n/**\n * Switch a Pro project between monthly and annual billing at the end of the period; the current\n * interval clears a pending switch, and resumes a project set to cancel. Resolves to the project.\n */\nexport function useChangeProjectPlan() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: ({\n projectExtId,\n body,\n }: {\n projectExtId: string\n body: ProjectPlanChangeRequest\n }) => arbi.projects.changePlan(projectExtId, body),\n onSuccess: () => refreshProjects(qc, true),\n })\n}\n\n/** Move a Pro project to Free at the end of the period (no refunds). */\nexport function useCancelProjectSubscription() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: (projectExtId: string) => arbi.projects.cancelSubscription(projectExtId),\n onSuccess: () => {\n void qc.invalidateQueries({ queryKey: arbiQueryKeys.projects() })\n void qc.invalidateQueries({ queryKey: arbiQueryKeys.userSettings() })\n },\n })\n}\n\n/** What a plan change would charge now and at the first renewal. `null` skips. */\nexport function usePreviewProjectPlanChange(\n projectExtId: string,\n change: { packs: number; interval: 'month' | 'year' } | null\n) {\n const arbi = useArbi()\n return useQuery({\n queryKey: [...arbiQueryKeys.billingQuotes(), 'preview', projectExtId, change],\n queryFn: () => arbi.projects.previewPlanChange(projectExtId, change!),\n enabled: !!change && arbi.isLoggedIn,\n staleTime: 60_000,\n retry: retryAbortOnly,\n })\n}\n\n/**\n * The taxed total of a Pro purchase for a billing address: for a new project without\n * `projectExtId`, else for that (Free) project. 422 `TAX_LOCATION_INVALID` asks for a ZIP /\n * postcode; 429 `QUOTE_RATE_LIMITED`. `null` skips.\n */\nexport function usePlanQuote(\n projectExtId: string | null | undefined,\n body: ProjectQuoteRequest | null\n) {\n const arbi = useArbi()\n return useQuery({\n queryKey: [...arbiQueryKeys.billingQuotes(), 'plan', projectExtId ?? null, body],\n queryFn: () => arbi.projects.quotePlan(projectExtId ?? null, body!),\n enabled: !!body && arbi.isLoggedIn,\n staleTime: 5 * 60_000,\n retry: retryAbortOnly,\n })\n}\n\n/** What one more add-on block costs now and at renewal, taxed for the saved address. */\nexport function useAddonQuote(projectExtId: string, kind: ProjectAddonKind, enabled = true) {\n const arbi = useArbi()\n return useQuery({\n queryKey: [...arbiQueryKeys.billingQuotes(), 'addon', projectExtId, kind],\n queryFn: () => arbi.projects.quoteAddon(projectExtId, kind),\n enabled: enabled && arbi.isLoggedIn,\n staleTime: 60_000,\n retry: retryAbortOnly,\n })\n}\n\n/** A fresh, short-lived Stripe customer-portal link for a project; open it as soon as it arrives. */\nexport function useProjectBillingPortal() {\n const arbi = useArbi()\n return useMutation({\n mutationFn: (projectExtId: string) => arbi.projects.billingPortal(projectExtId),\n })\n}\n\n/**\n * Buy one add-on block (AI usage or storage) on a Pro project, charged now and renewed every period\n * until reduced. `status: 'requires_action'` comes with a `confirm_url` (3-D Secure).\n */\nexport function useAddProjectAddonBlock() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: ({ projectExtId, kind }: { projectExtId: string; kind: ProjectAddonKind }) =>\n arbi.projects.addAddonBlock(projectExtId, kind),\n onSuccess: () => refreshProjects(qc),\n })\n}\n\n/** How many add-on blocks to keep from the next period (reductions only). */\nexport function useUpdateProjectNextPeriodAddons() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: ({\n projectExtId,\n body,\n }: {\n projectExtId: string\n body: ProjectNextPeriodAddonsRequest\n }) => arbi.projects.setNextPeriodAddons(projectExtId, body),\n onSuccess: () => refreshProjects(qc),\n })\n}\n\n/** A Pro project's add-on settings: the auto top-up threshold and the monthly usage cap. */\nexport function useUpdateProjectAddonSettings() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: ({\n projectExtId,\n body,\n }: {\n projectExtId: string\n body: ProjectAddonSettingsRequest\n }) => arbi.projects.updateAddonSettings(projectExtId, body),\n onSuccess: () => refreshProjects(qc),\n })\n}\n\nexport {\n useChargeWatch,\n useIsSlow,\n SLOW_AFTER_MS,\n POLL_EVERY_MS,\n STILL_WORKING,\n} from './charge-watch'\n\nexport type {\n ProjectResponse,\n ProductResponse,\n TaxQuoteResponse,\n ProjectAddonKind,\n ProjectQuoteRequest,\n ProjectCheckoutRequest,\n ProjectPlanChangeRequest,\n ProjectInvoicesResponse,\n ProjectUsageResponse,\n} from '@arbidocs/sdk/browser'\n","/**\n * Storage: what each project stores (by kind, workspace, live and trash), its largest items, the\n * deployment's view for Box admins / billing managers, a workspace's Recently deleted, and the trash\n * actions (restore, delete permanently, empty trash). The server counts every stored byte against\n * one project (ARBI `src/core/storage_ledger.py`).\n *\n * Requires an `ArbiHost` (with an `arbi`) and a React Query client above it.\n */\n\nimport { useMemo } from 'react'\nimport { useQuery, useQueryClient } from '@tanstack/react-query'\nimport type { components } from '@arbidocs/client'\nimport { useArbi } from './useArbi'\nimport { arbiQueryKeys } from './query-keys'\n\nexport type StorageProjectUsage = components['schemas']['StorageProjectUsage']\nexport type StorageItem = components['schemas']['StorageItem']\nexport type StorageKindUsage = components['schemas']['StorageKindUsage']\nexport type StorageDeploymentUsage = components['schemas']['StorageDeploymentUsage']\nexport type StorageSnapshot = components['schemas']['StorageSnapshotRead']\nexport type DeletedDocument = components['schemas']['DeletedDocument']\nexport type DeletedDocumentsPage = components['schemas']['DeletedDocumentsPage']\n\nexport type StorageScope = 'mine' | 'deployment'\nexport type StorageItemState = 'live' | 'trash' | 'all'\nexport type StorageItemKind = NonNullable<StorageItem['kind']>\n\nexport interface StorageItemsQuery {\n scope?: StorageScope\n project?: string\n workspace?: string\n kind?: 'document' | 'mail' | 'mail_draft' | 'recording' | 'chat_attachment' | 'other'\n state?: StorageItemState\n limit?: number\n}\n\n/** A read's data, or its error response thrown. */\nfunction dataOrThrow<T>({ data, error }: { data?: T; error?: unknown }): T {\n if (error !== undefined) throw error\n return data as T\n}\n\n/** My projects' storage (`mine`), or the deployment's (`deployment`: 403 for anyone but admins, not retried). */\nexport function useStorageProjects(scope: StorageScope = 'mine', project?: string) {\n const arbi = useArbi()\n const query = { scope, include: ['workspaces' as const], ...(project ? { project } : {}) }\n return useQuery({\n queryKey: arbiQueryKeys.storageProjects(query),\n queryFn: async () =>\n dataOrThrow(await arbi.getClient().fetch.GET('/v1/storage/projects', { params: { query } })),\n enabled: arbi.isLoggedIn,\n retry: false,\n staleTime: 30_000,\n })\n}\n\n/** The largest items stored, largest first (`state: 'trash'` is Recently deleted). */\nexport function useStorageItems(query: StorageItemsQuery, enabled = true) {\n const arbi = useArbi()\n const params = { limit: 50, ...query }\n return useQuery({\n queryKey: arbiQueryKeys.storageItems(params),\n queryFn: async () =>\n dataOrThrow(\n await arbi.getClient().fetch.GET('/v1/storage/items', { params: { query: params } })\n ),\n enabled: arbi.isLoggedIn && enabled,\n retry: false,\n staleTime: 30_000,\n })\n}\n\n/**\n * Names of the documents among `items`, one request per workspace (its key is primed on the session\n * when needed, without switching workspace). Names are encrypted; the server decrypts them with the key.\n */\nexport function useStorageItemNames(items: StorageItem[] | undefined, query: StorageItemsQuery) {\n const arbi = useArbi()\n const workspaces = [\n ...new Set(\n (items ?? [])\n .filter((i) => i.kind === 'document' && i.workspace_ext_id)\n .map((i) => i.workspace_ext_id as string)\n ),\n ].sort()\n return useQuery({\n queryKey: arbiQueryKeys.storageItemNames({ workspaces, query }),\n enabled: arbi.isLoggedIn && workspaces.length > 0,\n staleTime: 60_000,\n retry: false,\n queryFn: async () => {\n const names: Record<string, string> = {}\n for (const workspace of workspaces) {\n const { data } = await arbi.getClient().fetch.GET('/v1/storage/items', {\n params: {\n query: {\n ...query,\n workspace,\n kind: 'document',\n include: ['names'],\n limit: 200,\n },\n },\n })\n for (const item of data?.items ?? []) {\n if (item.ref && item.name) names[item.ref] = item.name\n }\n }\n return names\n },\n })\n}\n\n/** The deployment's storage day by day (admins). */\nexport function useStorageSnapshots(enabled: boolean) {\n const arbi = useArbi()\n const query = { limit: 90 }\n return useQuery({\n queryKey: arbiQueryKeys.storageSnapshots(query),\n queryFn: async () =>\n dataOrThrow(await arbi.getClient().fetch.GET('/v1/storage/snapshots', { params: { query } })),\n enabled: arbi.isLoggedIn && enabled,\n retry: false,\n staleTime: 5 * 60_000,\n })\n}\n\n/** After anything that changes what is stored: storage views, and the projects' quota meters. */\nexport function useInvalidateStorage() {\n const queryClient = useQueryClient()\n return () =>\n Promise.all([\n queryClient.invalidateQueries({ queryKey: arbiQueryKeys.storage() }),\n queryClient.invalidateQueries({ queryKey: arbiQueryKeys.projects() }),\n ])\n}\n\n/** A refused storage action, with the server's message. */\nexport class StorageActionError extends Error {}\n\n/** How often a Recently deleted list with documents being restored is checked. */\nconst RESTORE_POLL_MS = 3_000\n\nfunction fail(fallback: string, error: unknown): never {\n const detail = (error as { detail?: unknown } | undefined)?.detail\n const message =\n typeof detail === 'string'\n ? detail\n : typeof (detail as { message?: unknown } | undefined)?.message === 'string'\n ? (detail as { message: string }).message\n : fallback\n throw new StorageActionError(message)\n}\n\n/**\n * A workspace's Recently deleted documents — only those the caller could see live (shared, or theirs) —\n * with what they may do; for a workspace manager (project or workspace owner), how much other members keep\n * private in the trash. The workspace's key is primed on the session when needed.\n */\nexport function useWorkspaceTrash(workspace: string | undefined, enabled = true) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.workspaceTrash(workspace ?? ''),\n enabled: arbi.isLoggedIn && Boolean(workspace) && enabled,\n retry: false,\n // Other members delete and restore too, and deleting from the documents list doesn't touch this cache:\n // refetch whenever Recently deleted is opened instead of trusting a long staleTime.\n staleTime: 0,\n // A restore copies files back from archive storage first: follow it until the documents leave the list.\n refetchInterval: (query) =>\n query.state.data?.items.some((d) => d.restoring) ? RESTORE_POLL_MS : false,\n queryFn: async (): Promise<DeletedDocumentsPage> => {\n const { data, error, response } = await arbi.getClient().fetch.GET('/v1/document/deleted', {\n params: { query: { workspace_ext_id: workspace as string } },\n })\n if (!response.ok || !data) fail('Could not load Recently deleted', error)\n return data\n },\n })\n}\n\n/** The trash actions on the signed-in session. Each throws a {@link StorageActionError} when refused. */\nexport interface StorageActions {\n /**\n * Delete a workspace's deleted documents for good: these `externalIds`, or (omitted) Empty trash — a\n * manager's everything-they-can-see, plus other members' private items only with `includeOthersPrivate`;\n * anyone else their own. Returns the documents removed.\n */\n purgeDeletedDocuments(\n workspace: string,\n options?: { externalIds?: string[]; includeOthersPrivate?: boolean }\n ): Promise<string[]>\n /** Delete permanently what is in a project's trash (or only `refs`). Returns the bytes freed. */\n purgeStorageItems(project: string, refs?: string[]): Promise<number>\n /**\n * Restore deleted documents of one workspace: their files come back from archive storage first (they are\n * listed as `restoring` meanwhile), then they reappear and are re-indexed in the background.\n */\n restoreDocuments(workspace: string, externalIds: string[]): Promise<void>\n /** Restore deleted workspaces (their owner). */\n restoreWorkspaces(externalIds: string[]): Promise<void>\n /** Move live documents to Recently deleted (the documents' usual delete). */\n deleteDocuments(externalIds: string[]): Promise<void>\n /** ARBI mail: to the Trash, or back from it. */\n updateNativeMail(messageId: string, action: 'trash' | 'restore'): Promise<void>\n /** ARBI mail: empty the Trash. Returns the messages deleted. */\n emptyMailTrash(): Promise<number>\n}\n\nexport function useStorageActions(): StorageActions {\n const arbi = useArbi()\n return useMemo(() => {\n const client = () => arbi.getClient().fetch\n return {\n async purgeDeletedDocuments(workspace, options = {}) {\n const { data, error, response } = await client().DELETE('/v1/document/deleted', {\n params: { query: { workspace_ext_id: workspace } },\n body: {\n ...(options.externalIds ? { external_ids: options.externalIds } : {}),\n include_others_private: Boolean(options.includeOthersPrivate),\n },\n })\n if (!response.ok || !data) fail('Could not delete permanently', error)\n return data.external_ids\n },\n async purgeStorageItems(project, refs) {\n const { data, error, response } = await client().DELETE('/v1/storage/items', {\n params: { query: { project, ...(refs?.length ? { refs } : {}) } },\n })\n if (!response.ok || !data) fail('Could not delete permanently', error)\n return data.bytes\n },\n async restoreDocuments(workspace, externalIds) {\n const { error, response } = await client().POST('/v1/document/restore', {\n params: { query: { workspace_ext_id: workspace } },\n body: { external_ids: externalIds },\n })\n if (!response.ok) fail('Could not restore', error)\n },\n async restoreWorkspaces(externalIds) {\n const { error, response } = await client().POST('/v1/workspace/restore', {\n body: { external_ids: externalIds },\n })\n if (!response.ok) fail('Could not restore the workspace', error)\n },\n async deleteDocuments(externalIds) {\n const { error, response } = await client().DELETE('/v1/document/', {\n body: { external_ids: externalIds },\n })\n if (!response.ok) fail('Could not delete', error)\n },\n async updateNativeMail(messageId, action) {\n const { error, response } = await client().PATCH(\n '/v1/mail/accounts/{account_id}/messages/{message_id}',\n {\n params: { path: { account_id: 'native', message_id: messageId } },\n body: { action },\n }\n )\n if (!response.ok) fail(action === 'trash' ? 'Could not delete' : 'Could not restore', error)\n },\n async emptyMailTrash() {\n const { data, error, response } = await client().DELETE(\n '/v1/mail/accounts/{account_id}/messages',\n { params: { path: { account_id: 'native' }, query: { folder: 'trash' } } }\n )\n if (!response.ok || !data) fail('Could not empty the Trash', error)\n return data.deleted\n },\n }\n }, [arbi])\n}\n","/**\n * Contacts: one address book — people on ARBI, invitations still out, and plain cards.\n *\n * Shares `arbiQueryKeys.contacts()` with the messenger's people, so a change made here refreshes\n * the conversation rail on its own. The parts that turn an email list into a request and the backend\n * outcome into a sentence live in `@arbidocs/blocks/collaboration` (`AddContactsForm`).\n */\n\nimport { useEffect, useState } from 'react'\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'\nimport type { contacts as contactsOps } from '@arbidocs/sdk/browser'\nimport { useArbi } from './useArbi'\nimport { arbiQueryKeys } from './hooks'\n\n/** Every contact: registered, invited and plain cards. */\nexport function useContacts(options?: { enabled?: boolean }) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.contacts(),\n queryFn: () => arbi.contacts.list(),\n enabled: (options?.enabled ?? true) && arbi.isLoggedIn,\n staleTime: 30_000,\n })\n}\n\nfunction useInvalidateContacts() {\n const qc = useQueryClient()\n return () => qc.invalidateQueries({ queryKey: arbiQueryKeys.contacts() })\n}\n\n/**\n * Invite (or link) people by email. An address not yet on ARBI gets an invitation. Resolves with one\n * row per address (`outcome`, `status`); map it with `toAddContactsRows` from `@arbidocs/blocks/collaboration`.\n */\nexport function useInviteContacts() {\n const arbi = useArbi()\n const invalidate = useInvalidateContacts()\n return useMutation({\n mutationFn: (emails: string[]) => arbi.contacts.invite(emails),\n onSuccess: () => invalidate(),\n })\n}\n\n/** Create a card, optionally linking `email` and inviting it (`invite: true`). */\nexport function useCreateContact() {\n const arbi = useArbi()\n const invalidate = useInvalidateContacts()\n return useMutation({\n mutationFn: (body: contactsOps.ContactCreate) => arbi.contacts.create(body),\n onSuccess: () => invalidate(),\n })\n}\n\n/** Replace a contact's card details. */\nexport function useUpdateContact() {\n const arbi = useArbi()\n const invalidate = useInvalidateContacts()\n return useMutation({\n mutationFn: ({ id, card }: { id: string; card: contactsOps.ContactCardWrite }) =>\n arbi.contacts.update(id, card),\n onSuccess: () => invalidate(),\n })\n}\n\n/**\n * Invite a contact to ARBI by `email`: a card-only contact is linked in place (its row and card kept);\n * without an id a new card is created and invited. Rejects with `DuplicateContactError` when `email`\n * already belongs to another contact. The list refreshes either way.\n */\nexport function useLinkContact() {\n const arbi = useArbi()\n const invalidate = useInvalidateContacts()\n return useMutation({\n mutationFn: ({\n contact,\n email,\n card,\n }: {\n contact: Pick<contactsOps.Contact, 'external_id'>\n email: string\n card: contactsOps.ContactCardWrite\n }) =>\n contact.external_id\n ? arbi.contacts.link(contact.external_id, email, card)\n : arbi.contacts.create({ email, card, invite: true }),\n onSettled: () => invalidate(),\n })\n}\n\n/** Import one .vcf file (Pro: 403 `pro_required` otherwise); the list refreshes after each file. */\nexport function useImportContacts() {\n const arbi = useArbi()\n const invalidate = useInvalidateContacts()\n return useMutation({\n mutationFn: (file: Blob) => arbi.contacts.import(file),\n onSettled: () => invalidate(),\n })\n}\n\n/** Delete a contact, or withdraw its invitation, by contact id. */\nexport function useDeleteContact() {\n const arbi = useArbi()\n const invalidate = useInvalidateContacts()\n return useMutation({\n mutationFn: (contactId: string) => arbi.contacts.delete(contactId),\n onSuccess: () => invalidate(),\n })\n}\n\n/**\n * People matching `q` (your contacts and the registered people you share a workspace with), for a\n * picker: debounced, nothing fetched for an empty query, the previous matches kept while typing.\n */\nexport function useSearchContacts(q: string, { debounceMs = 200 }: { debounceMs?: number } = {}) {\n const arbi = useArbi()\n const term = useDebounced(q.trim(), debounceMs)\n return useQuery({\n queryKey: [...arbiQueryKeys.contacts(), 'search', term] as const,\n queryFn: () => arbi.contacts.search(term),\n enabled: term.length > 0 && arbi.isLoggedIn,\n staleTime: 60_000,\n placeholderData: (previous) => previous,\n retry: false,\n })\n}\n\nfunction useDebounced<T>(value: T, ms: number): T {\n const [debounced, setDebounced] = useState(value)\n useEffect(() => {\n const t = setTimeout(() => setDebounced(value), ms)\n return () => clearTimeout(t)\n }, [value, ms])\n return debounced\n}\n","/**\n * People — the one place an app learns who someone is.\n *\n * Pickers and autocomplete ask {@link usePeopleSearch}: GET /v1/contacts/search (every address book you can see\n * plus registered people who share a workspace with you, one entry per address), and your own agents where an\n * agent is a valid target. Resolving an id or address seen elsewhere (a DM tab, a tag's creator, a mail\n * recipient) asks {@link usePeople}: the same population, held as a directory — your contacts, your workspace\n * co-members and your agents. Nothing is learned from notifications.\n */\n\nimport { useMemo } from 'react'\nimport type { components } from '@arbidocs/client'\nimport type { contacts as contactsOps } from '@arbidocs/sdk/browser'\nimport { useAgents, useWorkspaces } from './hooks'\nimport { useContacts, useSearchContacts } from './contacts'\nimport { useArbi } from './useArbi'\nimport { getUserDisplayName, isAgent } from './users/user-display'\n\n/** An ARBI account (or agent) as the API returns it. */\nexport type UserResponse = components['schemas']['UserResponse']\ntype Contact = contactsOps.Contact\n\n// ── The directory (pure) ────────────────────────────────────────────────────\n\nexport interface Person {\n email: string\n /** Display name: the card's name, else the account's, else the address. */\n name: string\n /** The ARBI account (or agent), when the person has one. Null: a contact who is not on ARBI. */\n user: UserResponse | null\n /** `cnt-…` when the person is one of the contacts you can see. */\n contactId: string | null\n /** `cal-…` of the address book that contact is in. */\n addressBookId: string | null\n}\n\nexport interface PeopleDirectory {\n /** Registered people and agents, sorted by name (never you). */\n users: UserResponse[]\n byId: (externalId: string | null | undefined) => UserResponse | undefined\n byEmail: (email: string | null | undefined) => Person | undefined\n}\n\n/** Index people by account id and by every address they have. Pure, so tests can build one. */\nexport function peopleDirectory(people: Person[], meId?: string | null): PeopleDirectory {\n const ids = new Map<string, UserResponse>()\n const emails = new Map<string, Person>()\n for (const p of people) {\n if (p.user && p.user.external_id !== meId && !ids.has(p.user.external_id))\n ids.set(p.user.external_id, p.user)\n const key = p.email.toLowerCase()\n if (key && !emails.has(key)) emails.set(key, p)\n }\n const users = [...ids.values()].sort((a, b) =>\n getUserDisplayName(a).localeCompare(getUserDisplayName(b))\n )\n return {\n users,\n byId: (id) => (id ? ids.get(id) : undefined),\n byEmail: (email) => (email ? emails.get(email.toLowerCase()) : undefined),\n }\n}\n\n/** A registered person (or agent) as a {@link Person}. */\nexport function personOfUser(user: UserResponse, contactId: string | null = null): Person {\n return {\n email: user.email,\n name: getUserDisplayName(user) || user.email,\n user,\n contactId,\n addressBookId: null,\n }\n}\n\n// ── The hooks ───────────────────────────────────────────────────────────────\n\nfunction cardName(contact: Contact): string {\n return (\n contact.card?.name?.trim() ||\n [contact.card?.given_name, contact.card?.family_name].filter(Boolean).join(' ')\n )\n}\n\n/** A stand-in account for a search hit whose full record the directory does not hold. */\nfunction userFromName(externalId: string, email: string, name: string | null | undefined) {\n const [given = '', ...rest] = (name || email).trim().split(/\\s+/)\n return { external_id: externalId, email, given_name: given, family_name: rest.join(' ') }\n}\n\n/** Everyone you know, for resolving an id or an address to a person. */\nexport function usePeople(): PeopleDirectory {\n const arbi = useArbi()\n const meId = arbi.isLoggedIn ? arbi.user.identity()?.externalId : undefined\n const { data: contacts = [] } = useContacts()\n const { data: workspaces = [] } = useWorkspaces()\n const { data: agents = [] } = useAgents()\n\n return useMemo(() => {\n const people: Person[] = []\n const contactOf = new Map<string, Contact>()\n for (const c of contacts) {\n if (c.status === 'failed' || (c.user && isAgent(c.user))) continue\n if (c.user) contactOf.set(c.user.external_id, c)\n const addresses = [\n c.email ?? c.user?.email,\n ...(c.card?.emails ?? []).map((e) => e.email),\n ].filter((e): e is string => !!e)\n const user = c.status === 'registered' ? (c.user ?? null) : null\n for (const email of new Set(addresses))\n people.push({\n email,\n name: cardName(c) || (user ? getUserDisplayName(user) : '') || email,\n user,\n contactId: c.external_id ?? null,\n addressBookId: c.address_book_ext_id ?? null,\n })\n }\n const addUser = (user: UserResponse) => {\n const contact = contactOf.get(user.external_id)\n people.push({\n email: user.email,\n name: getUserDisplayName(user) || user.email,\n user,\n contactId: contact?.external_id ?? null,\n addressBookId: contact?.address_book_ext_id ?? null,\n })\n }\n for (const ws of workspaces) for (const wu of ws.users ?? []) addUser(wu.user as UserResponse)\n for (const agent of agents) addUser(agent as UserResponse)\n return peopleDirectory(people, meId)\n }, [contacts, workspaces, agents, meId])\n}\n\n/**\n * People matching `query` (debounced; an empty query matches nobody), for a picker or an autocomplete.\n * `agents`: also your own agents whose name or address matches — only where an agent is a valid target.\n */\nexport function usePeopleSearch(\n query: string,\n { agents = false }: { agents?: boolean } = {}\n): { people: Person[]; isFetching: boolean } {\n const arbi = useArbi()\n const meId = arbi.isLoggedIn ? arbi.user.identity()?.externalId : undefined\n const directory = usePeople()\n const search = useSearchContacts(query)\n const term = query.trim().toLowerCase()\n const hits = search.data\n\n const people = useMemo(() => {\n if (!term) return []\n const out: Person[] = []\n const seen = new Set<string>()\n for (const hit of hits ?? []) {\n if (hit.user_id === meId || seen.has(hit.email.toLowerCase())) continue\n seen.add(hit.email.toLowerCase())\n const user = hit.user_id\n ? (directory.byId(hit.user_id) ??\n (userFromName(hit.user_id, hit.email, hit.name) as UserResponse))\n : null\n if (user && isAgent(user)) continue\n out.push({\n email: hit.email,\n name: hit.name || (user ? getUserDisplayName(user) : '') || hit.email,\n user,\n contactId: hit.contact_id ?? null,\n addressBookId: hit.address_book_ext_id ?? null,\n })\n }\n if (agents)\n for (const user of directory.users) {\n if (!isAgent(user) || seen.has(user.email.toLowerCase())) continue\n const name = getUserDisplayName(user)\n if (!`${name} ${user.email}`.toLowerCase().includes(term)) continue\n out.push({ email: user.email, name, user, contactId: null, addressBookId: null })\n }\n return out\n }, [term, hits, directory, agents, meId])\n\n return { people, isFetching: search.isFetching }\n}\n","import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'\nimport { houseTemplates } from '@arbidocs/sdk/browser'\nimport { useArbi } from './useArbi'\nimport { arbiQueryKeys } from './hooks'\n\n/**\n * The documents the open workspace may use as its Word house template: live, shared Word documents\n * of the workspace and of the deployment's public workspaces. `staleTime` 0 reads the list afresh\n * whenever the query is enabled (a picker being opened).\n */\nexport function useHouseTemplateCandidates(\n workspaceId: string | null | undefined,\n enabled: boolean,\n staleTime = 60_000\n) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.houseTemplateCandidates(workspaceId ?? ''),\n enabled: enabled && !!workspaceId && arbi.hasWorkspace,\n staleTime,\n // Read in that workspace: the server answers for the session's open one.\n queryFn: () =>\n arbi.readInWorkspace(workspaceId as string, () => arbi.houseTemplates.candidates()),\n })\n}\n\n/**\n * Make a document of the open workspace its house template (`null`: the default applies again).\n * Owners only. The workspace list (which carries the template) is read again.\n */\nexport function useSetWorkspaceHouseTemplate() {\n const arbi = useArbi()\n const queryClient = useQueryClient()\n return useMutation({\n mutationFn: (documentId: string | null) => arbi.houseTemplates.setWorkspace(documentId),\n onSuccess: () => queryClient.invalidateQueries({ queryKey: arbiQueryKeys.workspaces() }),\n })\n}\n\n/**\n * Set the deployment's default house template from a .dotx/.docx (`null` clears it). Deployment\n * admins only (`isDeploymentAdmin`).\n */\nexport function useSetDeploymentHouseTemplate() {\n const arbi = useArbi()\n return useMutation({\n mutationFn: (file: Blob | null) => arbi.houseTemplates.setDeployment(file),\n })\n}\n\n/** Whether the server stores house templates (its workspaces carry the field). */\nexport const supportsHouseTemplates = houseTemplates.supportsHouseTemplates\n/** The workspace's house template document, or null. */\nexport const workspaceHouseTemplateId = houseTemplates.workspaceHouseTemplateId\n/** Whether the signed-in user may set the deployment default. */\nexport const isDeploymentAdmin = houseTemplates.isDeploymentAdmin\n","/**\n * Model connections over the SDK (`arbi.modelConnections`): the main agent's OpenAI-compatible\n * endpoints (the box's and the user's own), the user's direct model usage, and the unlock that lets\n * this session use the personal keys. Keyed per user; a save or a removal also refreshes the\n * available models (a connection's models join the picker).\n */\n\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'\nimport type { PersonalConnectionInput } from '@arbidocs/sdk/browser'\nimport { useArbi } from './useArbi'\nimport { useArbiSession } from './session/signed-in'\nimport { arbiQueryKeys } from './query-keys'\n\n/** The box's model connections and the user's own. */\nexport function useModelConnections() {\n const arbi = useArbi()\n const userId = useArbiSession().user?.external_id ?? undefined\n return useQuery({\n queryKey: arbiQueryKeys.modelConnections(userId),\n queryFn: () => arbi.modelConnections.list(),\n enabled: arbi.isLoggedIn,\n })\n}\n\n/** The user's direct model calls of the last 30 days (billed by their provider). */\nexport function useDirectModelUsage() {\n const arbi = useArbi()\n const userId = useArbiSession().user?.external_id ?? undefined\n return useQuery({\n queryKey: arbiQueryKeys.directModelUsage(userId),\n queryFn: () => arbi.modelConnections.usage(),\n enabled: arbi.isLoggedIn,\n })\n}\n\n/** After a write: the connections and the models the picker offers are read again. */\nfunction useRefreshModelConnections() {\n const qc = useQueryClient()\n const userId = useArbiSession().user?.external_id ?? undefined\n return async () => {\n await qc.invalidateQueries({ queryKey: arbiQueryKeys.modelConnections(userId) })\n await qc.invalidateQueries({ queryKey: arbiQueryKeys.availableModels() })\n }\n}\n\n/** Add a personal connection, or replace `id`'s; its key is sealed and unlocked on this session. */\nexport function useSaveModelConnection() {\n const arbi = useArbi()\n const refresh = useRefreshModelConnections()\n return useMutation({\n mutationFn: (input: PersonalConnectionInput) => arbi.modelConnections.save(input),\n onSuccess: refresh,\n })\n}\n\nexport function useRemoveModelConnection() {\n const arbi = useArbi()\n const refresh = useRefreshModelConnections()\n return useMutation({\n mutationFn: (id: string) => arbi.modelConnections.remove(id),\n onSuccess: refresh,\n })\n}\n\n/** Let this session use the user's enabled personal keys. */\nexport function useUnlockModelConnections() {\n const arbi = useArbi()\n return useMutation({ mutationFn: () => arbi.modelConnections.unlock() })\n}\n","/**\n * Email change: ask for a code at the new address, confirm it. The SDK-bound mutations and the\n * `ProfileCard` flow controller (cooldown on re-sending the code) are separate, as in `profile.ts`.\n */\n\nimport { useCallback, useEffect, useState } from 'react'\nimport { useMutation, useQueryClient } from '@tanstack/react-query'\nimport { arbiQueryKeys } from '../hooks'\nimport { useAccountClient } from './client'\n\n// ── SDK-bound hooks ─────────────────────────────────────────────────────────\n\n/** Send the 3-word verification code to the new address (not for SSO accounts). */\nexport function useRequestEmailChange() {\n const { client } = useAccountClient()\n return useMutation({\n mutationFn: (newEmail: string) => client.requestEmailChange(newEmail),\n })\n}\n\n/** Confirm the new address with the emailed code; the profile query shows the new email. */\nexport function useConfirmEmailChange() {\n const { client } = useAccountClient()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: ({ newEmail, code }: { newEmail: string; code: string }) =>\n client.confirmEmailChange(newEmail, code),\n onSuccess: () => qc.setQueryData(arbiQueryKeys.profile(), client.profile()),\n })\n}\n\n// ── Controller (no SDK) ─────────────────────────────────────────────────────\n\nexport interface UseEmailChangeOptions {\n /** Send a code to `newEmail`. */\n requestCode: (newEmail: string) => Promise<unknown> | unknown\n /** Confirm `newEmail` with `code`. Resolve to finish the flow. */\n confirm: (args: { newEmail: string; code: string }) => Promise<unknown> | unknown\n /** Seconds before another code may be requested. Default 30. */\n cooldownSeconds?: number\n}\n\nexport interface EmailChange {\n /** The flow is open: `ProfileCard` hides the plain email row. */\n isOpen: boolean\n onStart: () => void\n step: 'enter' | 'verify'\n newEmail: string\n onNewEmailChange: (value: string) => void\n onSendCode: () => void\n isSending: boolean\n code: string\n onCodeChange: (value: string) => void\n onConfirm: () => void\n isConfirming: boolean\n cooldownSeconds: number\n onCancel: () => void\n /** The last failed send or confirm. */\n error: unknown\n}\n\n/** The two-step email-change flow of `ProfileCard`: enter address, verify code. */\nexport function useEmailChange({\n requestCode,\n confirm,\n cooldownSeconds: cooldownLength = 30,\n}: UseEmailChangeOptions): EmailChange {\n const [isOpen, setIsOpen] = useState(false)\n const [step, setStep] = useState<'enter' | 'verify'>('enter')\n const [newEmail, setNewEmail] = useState('')\n const [code, setCode] = useState('')\n const [cooldown, setCooldown] = useState(0)\n const [isSending, setIsSending] = useState(false)\n const [isConfirming, setIsConfirming] = useState(false)\n const [error, setError] = useState<unknown>(null)\n\n useEffect(() => {\n if (cooldown <= 0) return\n const timer = setTimeout(() => setCooldown((c) => c - 1), 1000)\n return () => clearTimeout(timer)\n }, [cooldown])\n\n const reset = useCallback(() => {\n setIsOpen(false)\n setStep('enter')\n setNewEmail('')\n setCode('')\n setError(null)\n }, [])\n\n const onSendCode = useCallback(() => {\n const email = newEmail.trim()\n if (!email) return\n setIsSending(true)\n setError(null)\n void Promise.resolve()\n .then(() => requestCode(email))\n .then(() => {\n setStep('verify')\n setCooldown(cooldownLength)\n })\n .catch((e: unknown) => setError(e))\n .finally(() => setIsSending(false))\n }, [newEmail, requestCode, cooldownLength])\n\n const onConfirm = useCallback(() => {\n const email = newEmail.trim()\n const entered = code.trim()\n if (!email || !entered) return\n setIsConfirming(true)\n setError(null)\n void Promise.resolve()\n .then(() => confirm({ newEmail: email, code: entered }))\n .then(reset)\n .catch((e: unknown) => setError(e))\n .finally(() => setIsConfirming(false))\n }, [newEmail, code, confirm, reset])\n\n return {\n isOpen,\n onStart: () => setIsOpen(true),\n step,\n newEmail,\n onNewEmailChange: setNewEmail,\n onSendCode,\n isSending,\n code,\n onCodeChange: setCode,\n onConfirm,\n isConfirming,\n cooldownSeconds: cooldown,\n onCancel: reset,\n error,\n }\n}\n","/**\n * Password change: a new master password for the same account identity.\n *\n * The password only wraps the identity keypair, so a change is one request that re-encrypts nothing\n * and leaves the recovery key as it was (see `Arbi.account.changePassword`). `usePasswordChange` is\n * the SDK-bound mutation. `usePasswordChangeForm` is the controller behind `PasswordChangeDialog`:\n * fields, validation, error wording and the success state. It takes the submit as a function, so an\n * app without an `arbi` in its host binds the same dialog.\n */\n\nimport { useCallback, useMemo, useState } from 'react'\nimport { useMutation } from '@tanstack/react-query'\nimport { passwordChangeErrorMessage } from '@arbidocs/client'\nimport { useAccountClient } from './client'\n\n// ── SDK-bound hook ──────────────────────────────────────────────────────────\n\nexport interface PasswordChangeVars {\n newPassword: string\n /** Omit in recovery mode (after signing in with a recovery key). */\n currentPassword?: string\n}\n\n/** Change (or, in recovery mode, set) the master password through the account client in scope. */\nexport function usePasswordChange() {\n const { client } = useAccountClient()\n return useMutation({\n mutationFn: (vars: PasswordChangeVars): Promise<void> => client.changePassword(vars),\n })\n}\n\n// ── Controller (no SDK) ─────────────────────────────────────────────────────\n\nexport interface PasswordChangeFormMessages {\n required: string\n mismatch: string\n sameAsCurrent: string\n wrongCurrent: string\n wrongRecoveryKey: string\n}\n\nexport const DEFAULT_PASSWORD_CHANGE_FORM_MESSAGES: PasswordChangeFormMessages = {\n required: 'All fields are required',\n mismatch: 'New passwords do not match',\n sameAsCurrent: 'New password must be different from current password',\n wrongCurrent: 'Current password is incorrect.',\n wrongRecoveryKey: 'Recovery key did not match this account. Try a different recovery file.',\n}\n\nexport interface UsePasswordChangeFormOptions {\n /** After recovery with a key: no current password is asked for. */\n recoveryMode?: boolean\n /** The host's password policy: the first unmet requirement, or `null` when the password is fine. */\n getUnmetRequirement: (password: string) => string | null\n /** Do the change. */\n submit: (vars: PasswordChangeVars) => Promise<void>\n /** The dialog should close (cancel, or done). */\n onClose: () => void\n /** Recovery finished: continue into the app. Recovery closes itself, with no success screen. */\n onRecoveryComplete?: () => void\n messages?: Partial<PasswordChangeFormMessages>\n}\n\nexport interface PasswordChangeForm {\n currentPassword: string\n onCurrentPasswordChange: (value: string) => void\n newPassword: string\n onNewPasswordChange: (value: string) => void\n confirmPassword: string\n onConfirmPasswordChange: (value: string) => void\n error: string | null\n isProcessing: boolean\n isSubmitDisabled: boolean\n onSubmit: () => void\n /** The change went through (normal mode): the dialog shows its success state. */\n isChanged: boolean\n /** Cancel and clear the form. */\n onCancel: () => void\n /** Leave the success screen. */\n onDone: () => void\n}\n\n/** The state machine of `PasswordChangeDialog`; spread it into the dialog's props. */\nexport function usePasswordChangeForm({\n recoveryMode = false,\n getUnmetRequirement,\n submit,\n onClose,\n onRecoveryComplete,\n messages,\n}: UsePasswordChangeFormOptions): PasswordChangeForm {\n const m = useMemo(() => ({ ...DEFAULT_PASSWORD_CHANGE_FORM_MESSAGES, ...messages }), [messages])\n const [currentPassword, setCurrentPassword] = useState('')\n const [newPassword, setNewPassword] = useState('')\n const [confirmPassword, setConfirmPassword] = useState('')\n const [error, setError] = useState<string | null>(null)\n const [isProcessing, setIsProcessing] = useState(false)\n const [isChanged, setIsChanged] = useState(false)\n\n const clear = useCallback(() => {\n setCurrentPassword('')\n setNewPassword('')\n setConfirmPassword('')\n }, [])\n\n const isSubmitDisabled =\n isProcessing ||\n (!recoveryMode && !currentPassword) ||\n !newPassword ||\n !confirmPassword ||\n getUnmetRequirement(newPassword) !== null ||\n newPassword !== confirmPassword\n\n const onSubmit = useCallback(() => {\n setError(null)\n if ((!recoveryMode && !currentPassword) || !newPassword || !confirmPassword) {\n return setError(m.required)\n }\n if (newPassword !== confirmPassword) return setError(m.mismatch)\n const unmet = getUnmetRequirement(newPassword)\n if (unmet !== null) return setError(unmet)\n if (!recoveryMode && currentPassword === newPassword) return setError(m.sameAsCurrent)\n\n setIsProcessing(true)\n void submit({ newPassword, currentPassword: recoveryMode ? undefined : currentPassword })\n .then(() => {\n clear()\n if (recoveryMode) {\n onClose()\n onRecoveryComplete?.()\n } else {\n setIsChanged(true)\n }\n })\n .catch((e: unknown) => {\n const message = passwordChangeErrorMessage(e)\n const wrongCurrent = /invalid signature|current password|401/i.test(message)\n setError(wrongCurrent ? (recoveryMode ? m.wrongRecoveryKey : m.wrongCurrent) : message)\n })\n .finally(() => setIsProcessing(false))\n }, [\n recoveryMode,\n currentPassword,\n newPassword,\n confirmPassword,\n getUnmetRequirement,\n submit,\n clear,\n onClose,\n onRecoveryComplete,\n m,\n ])\n\n return {\n currentPassword,\n onCurrentPasswordChange: setCurrentPassword,\n newPassword,\n onNewPasswordChange: setNewPassword,\n confirmPassword,\n onConfirmPasswordChange: setConfirmPassword,\n error,\n isProcessing,\n isSubmitDisabled,\n onSubmit,\n isChanged,\n onCancel: () => {\n clear()\n setError(null)\n setIsChanged(false)\n onClose()\n },\n onDone: () => {\n setIsChanged(false)\n onClose()\n },\n }\n}\n","/**\n * Per-user \"don't show this tip again\" state, persisted in the `dismissed_tips`\n * user setting (a list of tip codes). Backed by the server so it's durable and\n * cross-device. The settings PATCH merge is shallow, so we always send the\n * whole list.\n *\n * Because the whole list is sent, a write must start from the list the server\n * has: nothing is written until the settings have loaded (an empty list before\n * then is \"not known yet\", and sending it would wipe every saved code), and each\n * write starts from the cached list as it is at that moment and updates the cache\n * at once, so two codes recorded in the same tick both survive.\n *\n * This is distinct from the `show_hints` lightbulb, which is the master on/off\n * for the whole tips bar — dismissing individual tips doesn't touch it, and\n * toggling it back on doesn't un-dismiss anything (otherwise \"don't show again\"\n * wouldn't stick). \"Reset tips\" (Settings › Privacy) clears the list.\n */\n\nimport { useCallback } from 'react'\nimport { useQueryClient } from '@tanstack/react-query'\nimport { arbiQueryKeys } from '../hooks'\nimport { useUserSettings, useUpdateUserSettings } from './settings'\n\ntype DismissedTipsSettings = { dismissed_tips?: string[] | null }\n\n/** The tip codes the user hid, and the writes that keep the saved list whole. */\nexport function useDismissedTips() {\n const queryClient = useQueryClient()\n const { data: userSettings } = useUserSettings()\n const { mutate: updateUserSettings } = useUpdateUserSettings()\n\n const loaded = userSettings !== undefined\n const dismissed = userSettings?.dismissed_tips ?? []\n\n const dismissTip = useCallback(\n (code: string) => {\n const key = arbiQueryKeys.userSettings()\n const current = queryClient.getQueryData<DismissedTipsSettings>(key)\n if (!current) return\n const list = current.dismissed_tips ?? []\n if (list.includes(code)) return\n const next = [...list, code]\n queryClient.setQueryData<DismissedTipsSettings>(key, { ...current, dismissed_tips: next })\n updateUserSettings({ dismissed_tips: next })\n },\n [queryClient, updateUserSettings]\n )\n\n const resetTips = useCallback(() => {\n if (dismissed.length === 0) return\n updateUserSettings({ dismissed_tips: [] })\n }, [dismissed.length, updateUserSettings])\n\n return { dismissed, loaded, dismissTip, resetTips }\n}\n","/**\n * Notification preferences: which email categories the user wants (the `email_notifications`\n * record of the user settings). All default on. The master switch on `NotificationCategoryList`\n * is \"on while at least one category is on\" and writes every category at once.\n */\n\nimport { useCallback, useMemo } from 'react'\nimport { useMutation, useQueryClient } from '@tanstack/react-query'\nimport { useArbi } from '../useArbi'\nimport { arbiQueryKeys } from '../hooks'\nimport { useUserSettings } from './settings'\n\n/** Category key to on/off, e.g. `{ messages: true, product_updates: false }`. */\nexport type EmailPreferences = Record<string, boolean>\n\n// ── Pure core ───────────────────────────────────────────────────────────────\n\nexport interface NotificationPreferencesModel {\n /** Master switch: on while at least one category is on. */\n masterChecked: boolean\n /** Each category's state (`true` when the record says nothing: the default). */\n checked: Record<string, boolean>\n /** The PATCH body for the master switch: every category set to `value`. */\n masterPatch: (value: boolean) => EmailPreferences\n /** The PATCH body for one category. */\n categoryPatch: (key: string, value: boolean) => EmailPreferences\n}\n\n/** Derive the switch states from the stored record and the list of category keys. */\nexport function toNotificationPreferences(\n stored: EmailPreferences | null | undefined,\n keys: readonly string[]\n): NotificationPreferencesModel {\n const checked = Object.fromEntries(keys.map((key) => [key, stored?.[key] ?? true]))\n return {\n masterChecked: keys.some((key) => checked[key]),\n checked,\n masterPatch: (value) => Object.fromEntries(keys.map((key) => [key, value])),\n categoryPatch: (key, value) => ({ [key]: value }),\n }\n}\n\n// ── SDK-bound hooks ─────────────────────────────────────────────────────────\n\n/**\n * The email notification preferences and the save. `save` writes the given keys (a patch,\n * merged by the server) and updates the cached settings straight away, so the switches do not\n * wait for the round trip; a failed write rolls back.\n */\nexport function useNotificationPreferences(\n keys: readonly string[],\n options?: { enabled?: boolean }\n) {\n const arbi = useArbi()\n const qc = useQueryClient()\n const settings = useUserSettings(options)\n const stored = settings.data?.email_notifications as EmailPreferences | undefined\n\n const save = useMutation({\n mutationFn: (patch: EmailPreferences) =>\n arbi.settings.update({ email_notifications: patch } as never),\n onMutate: async (patch) => {\n await qc.cancelQueries({ queryKey: arbiQueryKeys.userSettings() })\n const previous = qc.getQueryData(arbiQueryKeys.userSettings())\n qc.setQueryData(arbiQueryKeys.userSettings(), (old: typeof settings.data) =>\n old ? { ...old, email_notifications: { ...old.email_notifications, ...patch } } : old\n )\n return { previous }\n },\n onError: (_err, _patch, context) => {\n qc.setQueryData(arbiQueryKeys.userSettings(), context?.previous)\n },\n onSettled: () => qc.invalidateQueries({ queryKey: arbiQueryKeys.userSettings() }),\n })\n\n const model = useMemo(() => toNotificationPreferences(stored, keys), [stored, keys])\n const setAll = useCallback(\n (value: boolean) => save.mutate(model.masterPatch(value)),\n [save, model]\n )\n const setCategory = useCallback(\n (key: string, value: boolean) => save.mutate(model.categoryPatch(key, value)),\n [save, model]\n )\n\n return {\n ...model,\n isLoading: settings.isLoading,\n isSaving: save.isPending,\n /** The master switch handler: every category on or off. */\n setAll,\n /** One category's handler. */\n setCategory,\n }\n}\n","/**\n * Follow and mute: the relevance lists of the user settings. A workspace member is pushed only what\n * concerns them (a mention, an assignment, a reply in a thread they take part in). Following a\n * workspace or a thread opts in to everything from it; muting a workspace silences it, mentions\n * included. Everything else is in the workspace's activity feed.\n *\n * The server takes each list whole: a save sends the full new list, worked out from the cached\n * settings, and updates the cache straight away; a failed write rolls back.\n */\n\nimport { useCallback } from 'react'\nimport { useMutation, useQueryClient } from '@tanstack/react-query'\nimport { settings as settingsOps } from '@arbidocs/sdk/browser'\nimport { useArbi } from '../useArbi'\nimport { arbiQueryKeys } from '../hooks'\nimport { useUserSettings } from './settings'\n\n/** `default` (what names or involves you), `following` (everything) or `muted` (nothing). */\nexport type WorkspaceNotificationLevel = settingsOps.WorkspaceNotificationLevel\n\n/** The lists a follow or mute write may send. */\nexport interface RelevancePatch {\n muted_workspaces?: string[]\n followed_workspaces?: string[]\n followed_threads?: string[]\n}\n\ntype Settings = NonNullable<ReturnType<typeof useUserSettings>['data']>\n\n/** A write of some of the lists, applied to the cached settings at once. */\nfunction useRelevanceSave() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: (patch: RelevancePatch) => arbi.settings.update(patch),\n onMutate: async (patch) => {\n await qc.cancelQueries({ queryKey: arbiQueryKeys.userSettings() })\n const previous = qc.getQueryData<Settings>(arbiQueryKeys.userSettings())\n qc.setQueryData<Settings>(arbiQueryKeys.userSettings(), (old) =>\n old ? { ...old, ...patch } : old\n )\n return { previous }\n },\n onError: (_err, _patch, context) => {\n qc.setQueryData(arbiQueryKeys.userSettings(), context?.previous)\n },\n onSettled: () => qc.invalidateQueries({ queryKey: arbiQueryKeys.userSettings() }),\n })\n}\n\n/**\n * How much of a workspace reaches the user: `default`, `following` (everything) or `muted`\n * (nothing). `setLevel` moves the workspace between the two lists in one write.\n */\nexport function useWorkspaceNotificationLevel(\n workspaceId: string | null | undefined,\n options?: { enabled?: boolean }\n) {\n const qc = useQueryClient()\n const settings = useUserSettings(options)\n const save = useRelevanceSave()\n const level = workspaceId\n ? settingsOps.workspaceNotificationLevel(settings.data, workspaceId)\n : 'default'\n const setLevel = useCallback(\n (next: WorkspaceNotificationLevel) => {\n if (!workspaceId) return\n const current = qc.getQueryData<Settings>(arbiQueryKeys.userSettings()) ?? settings.data\n save.mutate(settingsOps.workspaceLevelPatch(current, workspaceId, next))\n },\n [qc, save, settings.data, workspaceId]\n )\n return {\n level,\n setLevel,\n isLoading: settings.isLoading,\n isSaving: save.isPending,\n error: save.error,\n }\n}\n\n/** What the host does once a follow switch is saved or refused (e.g. a toast: nothing else shows). */\nexport interface FollowSaveCallbacks {\n onSuccess?: () => void\n onError?: (error: Error) => void\n}\n\n/** Whether the user follows a thread (pushed everything in it), and the switch. */\nexport function useFollowThread(\n conversationId: string | null | undefined,\n options?: { enabled?: boolean }\n) {\n const qc = useQueryClient()\n const settings = useUserSettings(options)\n const save = useRelevanceSave()\n const following = !!conversationId && !!settings.data?.followed_threads?.includes(conversationId)\n const setFollowing = useCallback(\n (on: boolean, callbacks?: FollowSaveCallbacks) => {\n if (!conversationId) return\n const current = qc.getQueryData<Settings>(arbiQueryKeys.userSettings()) ?? settings.data\n save.mutate(\n {\n followed_threads: settingsOps.withMembership(\n current?.followed_threads,\n conversationId,\n on\n ),\n },\n callbacks\n )\n },\n [qc, save, settings.data, conversationId]\n )\n return {\n following,\n setFollowing,\n isLoading: settings.isLoading,\n isSaving: save.isPending,\n error: save.error,\n }\n}\n","/**\n * Sessions: the list, end one, sign out, and tell which listed session is this device's. All\n * through the account client in scope (`useAccountClient`).\n */\n\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'\nimport { arbiQueryKeys } from '../hooks'\nimport { useAccountClient, type AccountSignOutOptions } from './client'\n\n/** The user's active sessions (devices and agents). */\nexport function useSessions(options?: { enabled?: boolean }) {\n const { client, enabled } = useAccountClient()\n return useQuery({\n queryKey: arbiQueryKeys.sessions(),\n queryFn: () => client.listSessions(),\n enabled: (options?.enabled ?? true) && enabled,\n })\n}\n\n/** End one of the user's sessions at once (not this device's: that is a sign-out). */\nexport function useTerminateSession() {\n const { client } = useAccountClient()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: (sessionId: string) => client.terminateSession(sessionId),\n onSuccess: () => qc.invalidateQueries({ queryKey: arbiQueryKeys.sessions() }),\n })\n}\n\n/** Sign out of this device, or (`everywhere`) of every device, this one included. */\nexport function useSignOut() {\n const { client } = useAccountClient()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: (options: AccountSignOutOptions = {}) => client.signOut(options),\n onSettled: () => qc.clear(),\n })\n}\n\n/** The id this device's session carries in the `useSessions` list, or `null`. */\nexport function useCurrentSessionId(): string | null {\n return useAccountClient().client.currentSessionId()\n}\n","/**\n * Delete account: the two-step flow behind `DeleteAccountDialog` and the backend's refusals.\n * The backend closes the account (soft delete) unless the user still has an active subscription\n * or is the sole admin of a workspace with other members; the refusal names which.\n */\n\nimport { useCallback, useState } from 'react'\nimport { useMutation } from '@tanstack/react-query'\nimport { useAccountClient } from './client'\n\n/** Why an account cannot be closed yet. */\nexport type DeleteAccountBlocker =\n { type: 'active_subscription' } | { type: 'workspace_members'; workspaces: string[] }\n\n/** Read the blockers out of a failed deletion; an empty list means it failed for another reason. */\nexport function parseDeleteAccountBlockers(error: unknown): DeleteAccountBlocker[] {\n const body = (error as { apiError?: unknown } | null)?.apiError ?? error\n const detail = (body as { detail?: unknown } | null)?.detail\n if (detail === 'active_subscription') return [{ type: 'active_subscription' }]\n if (detail && typeof detail === 'object') {\n const d = detail as { reason?: unknown; workspaces?: unknown }\n if (d.reason === 'workspace_members' && Array.isArray(d.workspaces)) {\n return [{ type: 'workspace_members', workspaces: d.workspaces.map(String) }]\n }\n }\n return []\n}\n\n/** Close the account (the account client in scope). The caller signs out afterwards. */\nexport function useDeleteAccount() {\n const { client } = useAccountClient()\n return useMutation({ mutationFn: () => client.requestDeletion() })\n}\n\nexport interface UseDeleteAccountFlowOptions {\n userEmail: string\n /** Close the account. Reject with the backend's error to surface blockers. */\n remove: () => Promise<unknown> | unknown\n /** The dialog should close. */\n onClose: () => void\n /** The account is closed (sign the user out of the app). */\n onDeleted: () => void\n /** A failure that is not a blocker. */\n onError?: (error: unknown) => void\n}\n\nexport interface DeleteAccountFlow {\n step: 'warning' | 'confirm'\n blockers: DeleteAccountBlocker[]\n confirmEmail: string\n onConfirmEmailChange: (value: string) => void\n onContinue: () => void\n onBack: () => void\n isDeleting: boolean\n onSubmit: () => void\n onClose: () => void\n}\n\n/** Step, typed-email confirmation and blockers of `DeleteAccountDialog`. */\nexport function useDeleteAccountFlow({\n userEmail,\n remove,\n onClose,\n onDeleted,\n onError,\n}: UseDeleteAccountFlowOptions): DeleteAccountFlow {\n const [step, setStep] = useState<'warning' | 'confirm'>('warning')\n const [confirmEmail, setConfirmEmail] = useState('')\n const [blockers, setBlockers] = useState<DeleteAccountBlocker[]>([])\n const [isDeleting, setIsDeleting] = useState(false)\n\n const close = useCallback(() => {\n setStep('warning')\n setConfirmEmail('')\n setBlockers([])\n onClose()\n }, [onClose])\n\n const onSubmit = useCallback(() => {\n if (confirmEmail.toLowerCase() !== userEmail.toLowerCase()) return\n setIsDeleting(true)\n void Promise.resolve()\n .then(remove)\n .then(() => {\n close()\n onDeleted()\n })\n .catch((error: unknown) => {\n const found = parseDeleteAccountBlockers(error)\n if (found.length > 0) {\n setBlockers(found)\n setStep('warning')\n } else {\n onError?.(error)\n }\n })\n .finally(() => setIsDeleting(false))\n }, [confirmEmail, userEmail, remove, close, onDeleted, onError])\n\n return {\n step,\n blockers,\n confirmEmail,\n onConfirmEmailChange: setConfirmEmail,\n onContinue: () => setStep('confirm'),\n onBack: () => setStep('warning'),\n isDeleting,\n onSubmit,\n onClose: close,\n }\n}\n","/**\n * Didit's web SDK, loaded only when a verification starts (like the app loads Stripe), and run\n * embedded in a host element. ID capture, liveness and face match all happen inside Didit's frame.\n */\n\nimport type { DiditSdk, VerificationResult } from '@didit-protocol/sdk-web'\n\nlet sdkPromise: Promise<typeof DiditSdk> | null = null\n\nfunction loadDidit(): Promise<typeof DiditSdk> {\n sdkPromise ??= import('@didit-protocol/sdk-web').then((m) => m.DiditSdk)\n // A failed chunk load may succeed on the next attempt.\n sdkPromise.catch(() => {\n sdkPromise = null\n })\n return sdkPromise\n}\n\nexport interface MountDiditOptions {\n /** The Didit session URL from the backend. */\n url: string\n /** Id of the element the verification renders into; it must have a height. */\n containerId: string\n /** The user finished, cancelled or the flow failed (`cameraAccessDenied`, `sessionExpired`, …). */\n onResult: (result: VerificationResult) => void\n}\n\n/** Start the embedded verification. Resolves with a teardown; rejects if the SDK can't load. */\nexport async function mountDiditVerification({\n url,\n containerId,\n onResult,\n}: MountDiditOptions): Promise<() => void> {\n const Sdk = await loadDidit()\n const sdk = Sdk.shared\n sdk.onComplete = onResult\n await sdk.startVerification({\n url,\n configuration: {\n embedded: true,\n embeddedContainerId: containerId,\n showCloseButton: false,\n closeModalOnComplete: true,\n },\n })\n return () => {\n sdk.onComplete = undefined\n sdk.destroy()\n }\n}\n","/**\n * Identity verification: the optional, paid ID check behind the verified tick (Pro plans only).\n *\n * Two layers, like `profile.ts`. `useIdentityVerificationFlow` owns the dialog's state and takes\n * the backend calls as functions, so an app with its own API layer (ARBI-frontend) binds the same\n * `IdentityVerificationCard` / `IdentityVerificationDialog` blocks without a provider.\n * `useIdentityVerification` binds it to the SDK (`arbi.identity`).\n *\n * Steps: pay the one-time fee (charged to the user's Pro project card) → verify inside Didit's\n * embedded frame → result (verified, declined, in review, or the name on the document differs from\n * the account name, offered as the new name). No webhooks: completing Didit's flow calls `refresh`.\n */\n\nimport { useCallback, useEffect, useId, useMemo, useRef, useState } from 'react'\nimport { useQuery, useQueryClient } from '@tanstack/react-query'\nimport { identityErrorCode } from '@arbidocs/sdk/browser'\nimport { useAccountClient } from './client'\nimport { arbiQueryKeys } from '../hooks'\nimport { mountDiditVerification } from './didit'\nimport type {\n IdentityBusy,\n IdentityProblem,\n IdentityPurchase,\n IdentityStatus,\n IdentityStep,\n IdentityVerificationFlow,\n} from './identity-types'\n\nexport type {\n IdentityBusy,\n IdentityProblem,\n IdentityPurchase,\n IdentityState,\n IdentityStatus,\n IdentityStep,\n IdentityVerificationFlow,\n} from './identity-types'\n\n/** The backend calls of the flow, as functions (see the module comment). */\nexport interface IdentityVerificationApi {\n status: () => Promise<IdentityStatus>\n purchase: () => Promise<IdentityPurchase>\n /** The Didit session URL. */\n startSession: () => Promise<string>\n refresh: () => Promise<IdentityStatus>\n acceptName: () => Promise<IdentityStatus>\n remove: () => Promise<IdentityStatus>\n}\n\nexport interface UseIdentityVerificationFlowOptions {\n /** Load the status (default true; e.g. false while signed out). */\n enabled?: boolean\n /** The tick changed (granted, renamed away, removed): update the host's copy of the user. */\n onVerifiedChange?: (verified: boolean) => void\n /** The account name became the name on the document. */\n onNameAccepted?: (name: { givenName: string; familyName: string | null }) => void\n /** The host's price format (e.g. its billing helpers); default `formatIdentityPrice`. */\n formatPrice?: (status: IdentityStatus) => string\n}\n\nfunction problemOf(error: unknown, fallback: string): IdentityProblem {\n const code = identityErrorCode(error) ?? (error as { code?: unknown } | null)?.code\n const message = error instanceof Error && error.message ? error.message : fallback\n return { code: typeof code === 'string' ? code : undefined, message }\n}\n\n/** Which step the dialog opens on for a status. */\nexport function identityStepFor(status: IdentityStatus | undefined): IdentityStep {\n if (!status) return 'pay'\n if (['name_mismatch', 'in_review', 'verified'].includes(status.state)) return 'result'\n if (status.state === 'declined') return status.attempts_left > 0 ? 'result' : 'pay'\n if (status.state === 'in_progress' || status.attempts_left > 0) return 'verify'\n return 'pay'\n}\n\n/** \"£5.00 incl. VAT\": the fee is quoted including UK VAT. */\nexport function formatIdentityPrice(status: IdentityStatus): string {\n let amount: string\n try {\n amount = new Intl.NumberFormat('en-GB', {\n style: 'currency',\n currency: status.currency,\n }).format(status.price_pence / 100)\n } catch {\n amount = `${(status.price_pence / 100).toFixed(2)} ${status.currency}`\n }\n return `${amount} incl. VAT`\n}\n\n/** The identity verification dialog's state, bound to the backend calls in `api`. */\nexport function useIdentityVerificationFlow(\n api: IdentityVerificationApi,\n {\n enabled = true,\n onVerifiedChange,\n onNameAccepted,\n formatPrice = formatIdentityPrice,\n }: UseIdentityVerificationFlowOptions = {}\n): IdentityVerificationFlow {\n const qc = useQueryClient()\n const apiRef = useRef(api)\n apiRef.current = api\n const query = useQuery({\n queryKey: arbiQueryKeys.identity(),\n queryFn: () => apiRef.current.status(),\n enabled,\n staleTime: 60_000,\n })\n const status = query.data\n\n const [isOpen, setIsOpen] = useState(false)\n const [step, setStep] = useState<IdentityStep>('pay')\n const [busy, setBusy] = useState<IdentityBusy>(null)\n const [problem, setProblem] = useState<IdentityProblem | null>(null)\n const [paymentUrl, setPaymentUrl] = useState<string | null>(null)\n const [sessionUrl, setSessionUrl] = useState<string | null>(null)\n const [container, setContainer] = useState<HTMLElement | null>(null)\n const [embedFailed, setEmbedFailed] = useState(false)\n const verifyContainerId = `didit-${useId().replace(/[^a-zA-Z0-9_-]/g, '')}`\n\n const lastVerified = useRef<boolean | undefined>(undefined)\n const apply = useCallback(\n (next: IdentityStatus) => {\n qc.setQueryData(arbiQueryKeys.identity(), next)\n if (lastVerified.current !== undefined && lastVerified.current !== next.verified) {\n onVerifiedChange?.(next.verified)\n }\n lastVerified.current = next.verified\n return next\n },\n [qc, onVerifiedChange]\n )\n useEffect(() => {\n if (status && lastVerified.current === undefined) lastVerified.current = status.verified\n }, [status])\n\n const run = useCallback(\n async <T>(kind: Exclude<IdentityBusy, null>, fallback: string, fn: () => Promise<T>) => {\n setBusy(kind)\n setProblem(null)\n try {\n return await fn()\n } catch (e) {\n setProblem(problemOf(e, fallback))\n return undefined\n } finally {\n setBusy(null)\n }\n },\n []\n )\n\n const isOpenRef = useRef(false)\n const closeRef = useRef<() => void>(() => {})\n const startVerifyRef = useRef<() => Promise<void>>(async () => {})\n\n const refresh = useCallback(async () => {\n const next = await run('refresh', 'Could not read the verification result', () =>\n apiRef.current.refresh()\n )\n if (!next) return\n apply(next)\n if (next.state === 'in_progress') return\n setSessionUrl(null)\n const nextStep = next.state === 'declined' ? 'result' : identityStepFor(next)\n // An abandoned or expired session (state none, attempts left): open a fresh one.\n if (nextStep === 'verify' && isOpenRef.current) void startVerifyRef.current()\n else setStep(nextStep)\n }, [run, apply])\n\n // A check left open (closed tab, reload, manual review): ask for its result once on load.\n const refreshedOnLoad = useRef(false)\n useEffect(() => {\n if (refreshedOnLoad.current || !status) return\n refreshedOnLoad.current = true\n if (status.state === 'in_progress' || status.state === 'in_review') void refresh()\n }, [status, refresh])\n\n const startVerify = useCallback(async () => {\n setStep('verify')\n setEmbedFailed(false)\n const url = await run('start', 'Could not start identity verification', () =>\n apiRef.current.startSession()\n )\n if (url) {\n setSessionUrl(url)\n return\n }\n // Still unpaid (a 3-D Secure payment not confirmed yet): back to the payment step.\n setStep('pay')\n }, [run])\n startVerifyRef.current = startVerify\n\n // Mount Didit once the session is open and its host element is on screen.\n useEffect(() => {\n if (!isOpen || step !== 'verify' || !sessionUrl || !container || embedFailed) return\n let teardown: (() => void) | undefined\n let cancelled = false\n mountDiditVerification({\n url: sessionUrl,\n containerId: container.id,\n onResult: (result) => {\n if (result.type === 'failed' && result.error?.type === 'cameraAccessDenied') {\n setEmbedFailed(true)\n return\n }\n if (result.type === 'cancelled') {\n closeRef.current()\n return\n }\n void refresh()\n },\n })\n .then((stop) => {\n if (cancelled) stop()\n else teardown = stop\n })\n .catch(() => setEmbedFailed(true))\n return () => {\n cancelled = true\n teardown?.()\n }\n }, [isOpen, step, sessionUrl, container, embedFailed, refresh])\n\n // Verifying in another tab: look for the result when the user comes back.\n const [waitingInTab, setWaitingInTab] = useState(false)\n useEffect(() => {\n if (!waitingInTab || typeof window === 'undefined') return\n const onFocus = () => void refresh()\n window.addEventListener('focus', onFocus)\n return () => window.removeEventListener('focus', onFocus)\n }, [waitingInTab, refresh])\n\n const open = useCallback(() => {\n isOpenRef.current = true\n setProblem(null)\n setPaymentUrl(status?.pending_payment_url ?? null)\n const first = identityStepFor(status)\n setStep(first)\n setIsOpen(true)\n if (first === 'verify') void startVerify()\n }, [status, startVerify])\n\n const close = useCallback(() => {\n isOpenRef.current = false\n setIsOpen(false)\n setSessionUrl(null)\n setWaitingInTab(false)\n setEmbedFailed(false)\n setProblem(null)\n }, [])\n closeRef.current = close\n\n const pay = useCallback(async () => {\n const result = await run('pay', 'Payment could not be completed', () =>\n apiRef.current.purchase()\n )\n if (!result) return\n if (result.status === 'requires_action') {\n setPaymentUrl(result.payment_url ?? null)\n return\n }\n setPaymentUrl(null)\n void query.refetch()\n void startVerify()\n }, [run, query, startVerify])\n\n const acceptName = useCallback(async () => {\n const offered = status\n const next = await run('accept', 'Could not change your name', () =>\n apiRef.current.acceptName()\n )\n if (!next) return\n apply(next)\n if (offered?.document_given_name) {\n onNameAccepted?.({\n givenName: offered.document_given_name,\n familyName: offered.document_family_name ?? null,\n })\n }\n }, [run, apply, status, onNameAccepted])\n\n const remove = useCallback(async () => {\n const next = await run('remove', 'Could not remove the verification', () =>\n apiRef.current.remove()\n )\n if (next) apply(next)\n }, [run, apply])\n\n const price = useMemo(() => (status ? formatPrice(status) : null), [status, formatPrice])\n\n return {\n status,\n isLoading: query.isLoading,\n price,\n isOpen,\n open,\n close,\n step,\n busy,\n problem,\n paymentUrl,\n pay: () => void pay(),\n recheckPayment: () => void startVerify(),\n verifyContainerId,\n verifyContainerRef: setContainer,\n embedFailed,\n openInNewTab: () => {\n if (!sessionUrl || typeof window === 'undefined') return\n window.open(sessionUrl, '_blank', 'noopener')\n setWaitingInTab(true)\n },\n checkResult: () => void refresh(),\n retry: () => void startVerify(),\n acceptName: () => void acceptName(),\n keepName: close,\n remove: () => void remove(),\n }\n}\n\n// ── Bound ───────────────────────────────────────────────────────────────────\n\n/**\n * The identity verification flow over the account client in scope; the profile query follows the\n * tick and name.\n */\nexport function useIdentityVerification(\n options: Omit<UseIdentityVerificationFlowOptions, 'enabled'> = {}\n): IdentityVerificationFlow {\n const { client, enabled } = useAccountClient()\n const qc = useQueryClient()\n const { onVerifiedChange, onNameAccepted, formatPrice } = options\n return useIdentityVerificationFlow(client.identity, {\n enabled,\n formatPrice,\n onVerifiedChange: (verified) => {\n void qc.invalidateQueries({ queryKey: arbiQueryKeys.profile() })\n onVerifiedChange?.(verified)\n },\n onNameAccepted: (name) => {\n void qc.invalidateQueries({ queryKey: arbiQueryKeys.profile() })\n void qc.invalidateQueries({ queryKey: arbiQueryKeys.workspaces() })\n onNameAccepted?.(name)\n },\n })\n}\n","/**\n * Saving the account's recovery key in the browser: the recovery file (`createRecoveryFile` of\n * `@arbidocs/client`, a one-link HTML page) downloaded for the current origin.\n */\n\nimport { createRecoveryFile, type RecoveryKeyParams } from '@arbidocs/client'\nimport { downloadBlob } from '../document-tools/environment'\n\n/** Download the recovery file. `origin` defaults to the page's own; `auth0Sub` SSO-wraps the key. */\nexport async function downloadRecoveryFile(\n params: Omit<RecoveryKeyParams, 'origin'> & { origin?: string }\n): Promise<void> {\n const file = await createRecoveryFile({\n ...params,\n origin: params.origin ?? window.location.origin,\n })\n downloadBlob(new Blob([file.html], { type: 'text/html' }), file.filename)\n}\n","/**\n * A workspace document as a mail attachment: its file (the current version, or an older one), on\n * the session's `Arbi`. Offline, the copy kept on this device (\"Make available offline\") is used.\n */\n\nimport { onlineManager } from '@tanstack/react-query'\nimport type { Arbi } from '@arbidocs/sdk/browser'\nimport { getDocumentTitle } from '../entities'\nimport type { WorkspaceDocument } from '../documents/documents-cache'\nimport { getOfflineDocument, loadOfflineDocument } from '../documents/offline-documents'\nimport { fileAttachment } from './client'\nimport type { MailAttachment } from './types'\n\n/** A document as a mail attachment: its current version, or `version` (an older one). */\nexport async function documentMailAttachment(\n arbi: Arbi,\n doc: WorkspaceDocument,\n maxBytes: number,\n version?: number | null\n): Promise<MailAttachment> {\n const older = version && version !== (doc.current_version ?? 1) ? version : null\n // The offline copy is the current version's.\n if (!onlineManager.isOnline() && !older) return offlineDocumentAttachment(doc, maxBytes)\n const failed = (cause?: unknown) =>\n new Error(`Could not download ${getDocumentTitle(doc, 'the document')}`, { cause })\n // The SDK rejects a refused download (non-2xx); say which document, not the HTTP status.\n const response = await arbi.documents\n .download(doc.external_id, older ?? undefined)\n .catch((error: unknown) => {\n throw failed(error)\n })\n if (!response.ok) throw failed()\n const blob = await response.blob()\n if (blob.size > maxBytes) throw new Error('Document exceeds the email attachment limit')\n const fileName = older\n ? (doc.versions?.find((v) => v.n === older)?.file_name ?? doc.file_name)\n : doc.file_name\n return fileAttachment(\n new File([blob], fileName || getDocumentTitle(doc, 'document'), { type: blob.type })\n )\n}\n\n/**\n * Offline, a workspace document can be attached when its original file is saved on this device\n * (\"Make available offline\"). Only its PDF preview being saved isn't enough for a non-PDF document:\n * the recipient would get a different file than the one chosen, so that is refused with the reason.\n */\nasync function offlineDocumentAttachment(\n doc: WorkspaceDocument,\n maxBytes: number\n): Promise<MailAttachment> {\n const title = getDocumentTitle(doc, 'This document')\n const record = await getOfflineDocument(doc.external_id)\n const isPdf = /\\.pdf$/i.test(doc.file_name ?? '')\n if (!record || (record.kind === 'pdf' && !isPdf))\n throw new Error(\n `${title} isn't available offline. Make it available offline first, or attach it when you're back online.`\n )\n const blob = await loadOfflineDocument(doc.external_id)\n if (!blob) throw new Error(`${title} isn't available offline.`)\n if (blob.size > maxBytes) throw new Error('Document exceeds the email attachment limit')\n return fileAttachment(\n new File([blob], doc.file_name || getDocumentTitle(doc, 'document'), { type: blob.type })\n )\n}\n","/**\n * Keying older native mail into conversations, lazily, in the background.\n *\n * The server keys every message it stores from now on, but it cannot key mail stored before: its\n * Message-IDs are encrypted to the owner. The owner's client can read them, so it computes the keys\n * (with the owner's thread secret) for the unkeyed messages it lists and submits them. Until then\n * such a message is a conversation of its own, online and offline alike.\n *\n * A list row carries the Message-ID and References; only a row with no References is read in full\n * (for its In-Reply-To), through the query cache, so a message already opened is not read again.\n */\n\nimport { useEffect } from 'react'\nimport { useQueryClient } from '@tanstack/react-query'\nimport { logger } from '@arbidocs/client'\nimport { mail as mailOps } from '@arbidocs/sdk/browser'\nimport { useMailOnline, useReadMailMessage } from './hooks'\nimport { useMailClient } from './useMailClient'\nimport { nativeThreadKeys } from './threads'\nimport { mailQueryKeys } from '../query-keys'\nimport type { MailAccount, MailMessage } from './types'\n\n/** Messages keyed per round: the next list read brings the next ones. */\nconst BATCH = 50\n\n/** How long a fetched thread secret is used before it is fetched again. */\nconst SECRET_FRESH_MS = 60_000\n\n/**\n * Messages tried in this page's life, across mounts: a keyed one needs no second try, and one with\n * no Message-ID never gets a key (it stays on its own). A failed round is tried again later.\n */\nconst tried = new Set<string>()\n\n/** Key the native `messages` listed that have no thread yet. Failures stay quiet. */\nexport function useNativeThreadKeys(\n account: MailAccount | undefined,\n messages: MailMessage[] | undefined\n): void {\n const { client, enabled } = useMailClient()\n const isOnline = useMailOnline()\n const queryClient = useQueryClient()\n const readMessage = useReadMailMessage()\n useEffect(() => {\n if (!enabled || !isOnline || account?.provider !== 'native' || !messages) return\n const unkeyed = messages\n .filter((m) => !m.thread_id && m.id.startsWith('eml-') && !tried.has(m.id))\n .slice(0, BATCH)\n if (!unkeyed.length) return\n for (const m of unkeyed) tried.add(m.id)\n const keyable = unkeyed.filter((m) => m.message_id)\n if (!keyable.length) return\n void (async () => {\n try {\n // Fetched again for a batch after a minute, and after any failure: a secret kept across a\n // change on the server (a tab open through a deploy) would key mail into conversations\n // nobody else's keys match, for good.\n const secret = await queryClient.fetchQuery({\n queryKey: mailQueryKeys.threadSecret(),\n queryFn: () => mailOps.getNativeThreadSecret(client.fetch),\n staleTime: SECRET_FRESH_MS,\n })\n const keys: Record<string, { thread_hmac: string; message_id_hmac?: string }> = {}\n for (const listed of keyable) {\n // Older list rows carry no In-Reply-To: one without References is read in full for it.\n const source = listed.references.length\n ? listed\n : await readMessage(account, listed.id).catch(() => undefined)\n const key = source && (await nativeThreadKeys(secret, source))\n if (key) keys[listed.id] = key\n }\n if (!Object.keys(keys).length) return\n if ((await mailOps.submitNativeThreadKeys(client.fetch, keys)) > 0) {\n await queryClient.invalidateQueries({ queryKey: mailQueryKeys.allConversations() })\n await queryClient.invalidateQueries({ queryKey: mailQueryKeys.allMessages() })\n }\n } catch (error) {\n queryClient.removeQueries({ queryKey: mailQueryKeys.threadSecret() })\n for (const m of keyable) tried.delete(m.id)\n logger.warn('[mail] could not key older mail into conversations', error)\n }\n })()\n }, [account, messages, enabled, isOnline, client, queryClient, readMessage])\n}\n","/**\n * useOfflineMailRuntime — mounted once by the host for a signed-in user with Mail switched on.\n * Wherever the user is in the app, it:\n * - binds the offline mail store to this account (another account's data on the device is removed);\n * - on reconnect (and at start, when online): sends the Outbox, applies the changes made offline\n * (read, moved, trashed, deleted), uploads offline drafts, then syncs the offline mailbox if it\n * is on for this device. Nothing goes out while the person chose \"Work offline\": that turns the\n * app's online state off, and every runner checks it before each request;\n * - keeps the mailbox in sync while online: every few minutes and shortly after new mail arrives\n * (the server's mail notification refreshes the Mail queries; that is the cue);\n * - when the user changes how much mail is kept, trims the device copy to it at once (offline too)\n * and, online, syncs fully so a longer window fills in.\n */\n\nimport { useEffect, useRef } from 'react'\nimport { onlineManager, useQueryClient } from '@tanstack/react-query'\nimport { logger } from '@arbidocs/client'\nimport { useArbi } from '../../useArbi'\nimport { useFeature } from '../../host/features'\nimport { useIsEntitled } from '../../account/entitlements'\nimport { isUnderQueryKey } from '../../query-keys'\nimport { useArbiSession } from '../../session/signed-in'\nimport { mailQueryKeys, useMailPolicy } from '../hooks'\nimport {\n flushOutbox,\n sessionUser,\n syncOfflineMailbox,\n uploadOfflineDrafts,\n type OfflineMailContext,\n} from './live'\nimport { getOfflineMailSettings, onOfflineMailChange } from './settings'\nimport { trimOfflineMailbox } from './sync'\nimport { claimOfflineMail } from './wipe'\n\nconst SYNC_INTERVAL_MS = 5 * 60 * 1000\nconst NEW_MAIL_DEBOUNCE_MS = 5_000\n\nexport interface OfflineMailRuntimeOptions {\n /** Show the Outbox, offered on the notice that a queued message could not be sent. */\n openOutbox?: () => void\n}\n\n/**\n * Whether mail is kept on this device for the signed-in user: Mail switched on for them, their plan\n * includes it, and the deployment offers mail (its native inbox or a mail provider). Entitlement\n * alone is not enough: it is granted wherever billing is off, mail or not. Nothing runs, and no\n * store is made, while this is false.\n */\nexport function useOfflineMailActive(): boolean {\n const { user, status } = useArbiSession()\n const mailEnabled = useFeature('mail')\n const entitled = useIsEntitled('mail')\n const eligible = status === 'signed-in' && !!user?.external_id && mailEnabled && entitled\n const { data: policy } = useMailPolicy({ enabled: eligible })\n return (\n eligible && !!policy?.enabled && (policy.native_enabled || policy.enabled_providers.length > 0)\n )\n}\n\nexport function useOfflineMailRuntime({ openOutbox }: OfflineMailRuntimeOptions = {}): void {\n const { user, serverSessionKey } = useArbiSession()\n const userExtId = user?.external_id\n const hasSession = !!serverSessionKey\n const active = useOfflineMailActive()\n const queryClient = useQueryClient()\n // A new `Arbi` (another workspace opened) is the same session: each run reads the current one.\n const arbi = useArbi()\n const latest = useRef<OfflineMailContext>({ arbi, queryClient, openOutbox })\n latest.current = { arbi, queryClient, openOutbox }\n\n useEffect(() => {\n if (!active || !userExtId) return\n claimOfflineMail(userExtId).catch((error) =>\n logger.warn('[offline-mail] could not bind the store', error)\n )\n }, [active, userExtId])\n\n // A shorter window (or Off) applies at once, with no network or session keys: only plaintext\n // receive times are read.\n useEffect(() => {\n if (!active || !userExtId) return\n return onOfflineMailChange((change) => {\n if (change !== 'settings') return\n trimOfflineMailbox(getOfflineMailSettings(userExtId))\n // Offline the lists come from the device: show what is left.\n .then(() =>\n latest.current.queryClient.invalidateQueries({ queryKey: mailQueryKeys.allMessages() })\n )\n .catch((error) => logger.warn('[offline-mail] could not trim the device copy', error))\n })\n }, [active, userExtId])\n\n useEffect(() => {\n if (!active || !hasSession) return\n const context = () => latest.current\n const catchUp = async () => {\n await flushOutbox(context())\n await uploadOfflineDrafts(context())\n await syncOfflineMailbox(context())\n }\n const run = () => {\n catchUp().catch((error) => logger.warn('[offline-mail] catch-up failed', error))\n }\n run()\n let wasOnline = onlineManager.isOnline()\n const offOnline = onlineManager.subscribe((online) => {\n if (online && !wasOnline) run()\n wasOnline = online\n })\n // What waits (an Outbox message or a change whose request got no answer while online) is tried\n // again with each regular sync, not only on reconnect.\n const interval = setInterval(() => {\n if (document.visibilityState === 'visible') run()\n }, SYNC_INTERVAL_MS)\n const enabled = () => getOfflineMailSettings(sessionUser(context().arbi)).enabled\n let newMailTimer: ReturnType<typeof setTimeout> | null = null\n const offCache = queryClient.getQueryCache().subscribe((event) => {\n if (event.type !== 'updated' || event.action.type !== 'invalidate') return\n if (!isUnderQueryKey(event.query.queryKey, mailQueryKeys.all()) || !enabled()) return\n if (newMailTimer) clearTimeout(newMailTimer)\n newMailTimer = setTimeout(() => void syncOfflineMailbox(context()), NEW_MAIL_DEBOUNCE_MS)\n })\n const offSettings = onOfflineMailChange((change) => {\n if (change === 'settings' && enabled()) void syncOfflineMailbox(context(), { full: true })\n if (change === 'outbox') void flushOutbox(context())\n if (change === 'changes') void flushOutbox(context())\n if (change === 'drafts') void uploadOfflineDrafts(context())\n })\n return () => {\n offOnline()\n clearInterval(interval)\n if (newMailTimer) clearTimeout(newMailTimer)\n offCache()\n offSettings()\n }\n }, [active, hasSession, queryClient])\n}\n","/**\n * React bindings for the offline mailbox: the per-device settings, sync status, the Outbox, the\n * changes made offline and the drafts kept on this device. Every hook re-reads when the store changes in this tab or another.\n */\n\nimport { useCallback, useEffect, useMemo, useState, useSyncExternalStore } from 'react'\nimport { useQueryClient } from '@tanstack/react-query'\nimport { logger } from '@arbidocs/client'\nimport { useArbi } from '../../useArbi'\nimport { useArbiSession } from '../../session/signed-in'\nimport { listLocalDrafts, type LocalDraft } from './drafts'\nimport { flushOutbox, isMailSyncRunning, syncOfflineMailbox } from './live'\nimport { listOutbox, type OutboxItem } from './outbox'\nimport { listMailChanges, type PendingMailChange } from './changes'\nimport {\n getOfflineMailSettings,\n onOfflineMailChange,\n setOfflineMailSettings,\n type OfflineMailChange,\n type OfflineMailSettings,\n} from './settings'\nimport { getOfflineMailStatus, type OfflineMailStatus } from './sync'\n\n/** Re-run `load` on mount and whenever one of `changes` happens; errors leave the last value. */\nfunction useStoreValue<T>(load: () => Promise<T>, initial: T, changes: OfflineMailChange[]): T {\n const [value, setValue] = useState<T>(initial)\n const key = changes.join(',')\n useEffect(() => {\n let alive = true\n const read = () =>\n load()\n .then((next) => alive && setValue(next))\n .catch((error) => logger.warn('[offline-mail] read failed', error))\n void read()\n const off = onOfflineMailChange((change) => {\n if (change === 'wiped') setValue(initial)\n if (change === 'wiped' || key.split(',').includes(change)) void read()\n })\n return () => {\n alive = false\n off()\n }\n }, [key, load, initial])\n return value\n}\n\nexport function useOfflineMailSettings(): [\n OfflineMailSettings,\n (patch: Partial<OfflineMailSettings>) => void,\n] {\n const userExtId = useArbiSession().user?.external_id\n const subscribe = useCallback(\n (onChange: () => void) =>\n onOfflineMailChange((change) => {\n if (change === 'settings') onChange()\n }),\n []\n )\n // Snapshot as a string so useSyncExternalStore sees a stable value between changes; the user is\n // part of it because the settings are per user.\n const raw = useSyncExternalStore(subscribe, () =>\n JSON.stringify([userExtId, getOfflineMailSettings(userExtId)])\n )\n const settings = useMemo(() => (JSON.parse(raw) as [unknown, OfflineMailSettings])[1], [raw])\n const update = useCallback(\n (patch: Partial<OfflineMailSettings>) => void setOfflineMailSettings(userExtId, patch),\n [userExtId]\n )\n return [settings, update]\n}\n\nconst EMPTY_STATUS: OfflineMailStatus = { messages: 0, bytes: 0, skipped: [] }\n\nexport function useOfflineMailStatus(): OfflineMailStatus & { syncing: boolean } {\n const status = useStoreValue(getOfflineMailStatus, EMPTY_STATUS, ['status', 'mailbox'])\n const [syncing, setSyncing] = useState(isMailSyncRunning)\n useEffect(\n () =>\n onOfflineMailChange((change) => {\n if (change === 'status') setSyncing(isMailSyncRunning())\n }),\n []\n )\n return { ...status, syncing }\n}\n\nconst NO_ITEMS: OutboxItem[] = []\n/** The Outbox, oldest first. `enabled: false` skips reading the store (Mail switched off). */\nexport function useOutbox(enabled = true): OutboxItem[] {\n const load = useCallback(() => (enabled ? listOutbox() : Promise.resolve(NO_ITEMS)), [enabled])\n return useStoreValue(load, NO_ITEMS, ['outbox'])\n}\n\nconst NO_CHANGES: PendingMailChange[] = []\n/**\n * The changes made offline that wait for a connection, oldest first. `enabled: false` skips\n * reading the store (Mail switched off).\n */\nexport function usePendingMailChanges(enabled = true): PendingMailChange[] {\n const load = useCallback(\n () => (enabled ? listMailChanges() : Promise.resolve(NO_CHANGES)),\n [enabled]\n )\n return useStoreValue(load, NO_CHANGES, ['changes'])\n}\n\nconst NO_DRAFTS: LocalDraft[] = []\nexport function useLocalDrafts(accountId: string | undefined): LocalDraft[] {\n const load = useCallback(\n () => (accountId ? listLocalDrafts(accountId) : Promise.resolve(NO_DRAFTS)),\n [accountId]\n )\n return useStoreValue(load, NO_DRAFTS, ['drafts'])\n}\n\n/** Send what waits in the Outbox now (\"Send now\"), on the session in scope. */\nexport function useFlushOutbox(): () => Promise<void> {\n const arbi = useArbi()\n const queryClient = useQueryClient()\n return useCallback(() => flushOutbox({ arbi, queryClient }), [arbi, queryClient])\n}\n\n/** One sync pass of the offline mailbox now (\"Sync now\": `{ full: true }`). */\nexport function useSyncOfflineMailbox(): (options?: { full?: boolean }) => Promise<void> {\n const arbi = useArbi()\n return useCallback((options) => syncOfflineMailbox({ arbi }, options), [arbi])\n}\n","import { listLocalDrafts } from './drafts'\nimport { listOutbox } from './outbox'\nimport { listMailChanges } from './changes'\nimport { OFFLINE_MAIL_DB } from './store'\n\n/** Whether this device has an offline mailbox at all (asked without creating one). */\nasync function storeExists(): Promise<boolean> {\n try {\n const databases = await indexedDB.databases?.()\n return databases ? databases.some((d) => d.name === OFFLINE_MAIL_DB) : true\n } catch {\n // Can't tell: look (an empty store just asks nothing).\n return true\n }\n}\n\n/** Asks the user (the blocks environment's `confirm`); resolves with their answer. */\ntype Confirm = (options: { message: string; title: string }) => Promise<boolean>\n\n/**\n * Signing out removes mail kept on this device. When that includes unsent Outbox messages or drafts\n * that never reached the server, say so and let the user stay signed in to send them first.\n */\nexport async function confirmLosingOfflineMail(confirm: Confirm): Promise<boolean> {\n // Checked whatever the mail settings say: they may not have loaded (a cold start offline), and\n // unsent mail must never go without a word. Nothing on the device: nothing to ask.\n if (!(await storeExists())) return true\n const [outbox, drafts, changes] = await Promise.all([\n listOutbox().catch(() => []),\n listLocalDrafts().catch(() => []),\n listMailChanges().catch(() => []),\n ])\n const unsent = outbox.filter((item) => item.status !== 'sent').length\n if (unsent === 0 && drafts.length === 0 && changes.length === 0) return true\n const parts = [\n unsent > 0 ? `${unsent} unsent ${unsent === 1 ? 'message' : 'messages'} in your Outbox` : '',\n drafts.length > 0\n ? `${drafts.length} ${drafts.length === 1 ? 'draft' : 'drafts'} saved only on this device`\n : '',\n changes.length > 0\n ? `${changes.length} ${changes.length === 1 ? 'change' : 'changes'} to your mail not applied yet`\n : '',\n ].filter(Boolean)\n const list =\n parts.length > 1 ? `${parts.slice(0, -1).join(', ')} and ${parts[parts.length - 1]}` : parts[0]\n const count = unsent + drafts.length + changes.length\n return confirm({\n message: `You have ${list}. Signing out deletes ${count === 1 ? 'it' : 'them'} from this device. Reconnect first to send and save them.`,\n title: 'Sign out and delete unsent mail?',\n })\n}\n","/**\n * Connectors over the SDK (`arbi.connectors`): the catalog and the user's connections, mailbox and\n * drive sync into a workspace, Slack, and the session token bridge. Every key is under\n * `['arbi', 'connectors']`, and every write refreshes all of it (a sync changes the connection\n * rows, the progress and the folders alike).\n */\n\nimport { useEffect, useRef } from 'react'\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'\nimport { ArbiApiError, isConnectorVendorVisible } from '@arbidocs/sdk/browser'\nimport { logger } from '@arbidocs/client'\nimport { useArbi } from '../useArbi'\nimport { useUserSettings } from '../account/settings'\nimport { useIsEntitled } from '../account/entitlements'\n\nexport { connectorQueryKeys } from '../query-keys'\nimport { connectorQueryKeys, mailQueryKeys } from '../query-keys'\n\n/** A write that refreshes every connector read. */\nfunction useConnectorMutation<TVars, TResult>(mutationFn: (vars: TVars) => Promise<TResult>) {\n const qc = useQueryClient()\n return useMutation({\n mutationFn,\n onSuccess: () => qc.invalidateQueries({ queryKey: connectorQueryKeys.all() }),\n })\n}\n\n// ── Catalog and connections ─────────────────────────────────────────────────\n\n/** The connectors this deployment offers. */\nexport function useConnectorCatalog() {\n const arbi = useArbi()\n return useQuery({\n queryKey: connectorQueryKeys.catalog(),\n queryFn: () => arbi.connectors.catalog(),\n staleTime: 5 * 60_000,\n enabled: arbi.isLoggedIn,\n })\n}\n\n/** The user's connections, with their sync settings. */\nexport function useMyConnectors() {\n const arbi = useArbi()\n return useQuery({\n queryKey: connectorQueryKeys.mine(),\n queryFn: () => arbi.connectors.mine(),\n staleTime: 30_000,\n enabled: arbi.isLoggedIn,\n })\n}\n\nexport function useDisconnectConnector() {\n const arbi = useArbi()\n return useConnectorMutation(({ vendorKey }: { vendorKey: string }) =>\n arbi.connectors.disconnect(vendorKey)\n )\n}\n\n/** Whether a vendor shows under the user's per-provider switches (`isConnectorVendorVisible`). */\nexport function useConnectorVendorVisibility(): (vendorKey: string) => boolean {\n const { data: settings } = useUserSettings()\n return (vendorKey) => isConnectorVendorVisible(settings, vendorKey)\n}\n\n/**\n * Where a connect's OAuth should land: back on this page, with `stay=1` (do not open the settings\n * on return) and, optionally, `reopen=accounts` (bring the \"Add from accounts\" dialog back).\n */\nexport function connectorReturnTo(reopen?: 'accounts'): string {\n const params = new URLSearchParams(window.location.search)\n params.delete('connected')\n params.delete('connect_error')\n params.set('stay', '1')\n if (reopen) params.set('reopen', reopen)\n else params.delete('reopen')\n return `${window.location.pathname}?${params.toString()}`\n}\n\n// ── Mailbox sync ────────────────────────────────────────────────────────────\n\nexport function useMailboxFolders(vendorKey: string, enabled: boolean) {\n const arbi = useArbi()\n return useQuery({\n queryKey: connectorQueryKeys.mailboxFolders(vendorKey),\n queryFn: () => arbi.connectors.mailboxFolders(vendorKey),\n enabled: enabled && arbi.isLoggedIn,\n staleTime: 60_000,\n })\n}\n\nexport interface EnableMailboxSyncVars {\n vendorKey: string\n workspaceExtId: string\n backfillWindow: number\n /** A fixed start date (ISO); overrides the window. */\n backfillSince?: string | null\n /** Folder or label ids (at least one). */\n folders: string[]\n skipDuplicates: boolean\n /** An AI title instead of \"<sender> - <subject>\". */\n autoRename?: boolean\n /** Shared with the workspace rather than private to the importer. */\n shared?: boolean\n /** Sync at sign-in, not only on \"Sync now\". */\n autoSync: boolean\n}\n\nexport function useEnableMailboxSync() {\n const arbi = useArbi()\n return useConnectorMutation((v: EnableMailboxSyncVars) =>\n arbi.connectors.enableMailboxSync(v.vendorKey, {\n workspace_ext_id: v.workspaceExtId,\n backfill_window: v.backfillWindow,\n backfill_since: v.backfillSince ?? null,\n folders: v.folders,\n skip_duplicates: v.skipDuplicates,\n auto_rename: v.autoRename ?? false,\n shared: v.shared ?? false,\n auto_sync: v.autoSync,\n })\n )\n}\n\n/** Sync now (404: no sync set up, 409: reconnect needed). */\nexport function useTriggerMailboxSync() {\n const arbi = useArbi()\n return useConnectorMutation(\n ({ vendorKey, workspaceExtId }: { vendorKey: string; workspaceExtId?: string | null }) =>\n arbi.connectors.syncMailbox(vendorKey, workspaceExtId)\n )\n}\n\n/** A running sync's progress: polled every 1.5 s while it runs, idle otherwise. */\nexport function useMailboxSyncProgress(\n vendorKey: string,\n workspaceExtId: string,\n enabled: boolean\n) {\n const arbi = useArbi()\n return useQuery({\n queryKey: connectorQueryKeys.mailboxSyncProgress(vendorKey, workspaceExtId),\n queryFn: () => arbi.connectors.mailboxSyncProgress(vendorKey, workspaceExtId),\n enabled: enabled && !!workspaceExtId && arbi.isLoggedIn,\n refetchInterval: (query) => (query.state.data?.running ? 1500 : false),\n staleTime: 0,\n })\n}\n\nexport function useCancelMailboxSync() {\n const arbi = useArbi()\n return useMutation({\n mutationFn: ({ vendorKey, workspaceExtId }: { vendorKey: string; workspaceExtId: string }) =>\n arbi.connectors.cancelMailboxSync(vendorKey, workspaceExtId),\n })\n}\n\n// ── Drive sync ──────────────────────────────────────────────────────────────\n\nexport function useDriveFolders(vendorKey: string, enabled: boolean) {\n const arbi = useArbi()\n return useQuery({\n queryKey: connectorQueryKeys.driveFolders(vendorKey),\n queryFn: () => arbi.connectors.driveFolders(vendorKey),\n enabled: enabled && arbi.isLoggedIn,\n retry: false,\n staleTime: 60_000,\n })\n}\n\n/** One level of the folder tree (`root` or a folder id), fetched as the user drills in. */\nexport function useDriveFolderChildren(vendorKey: string, itemId: string, enabled: boolean) {\n const arbi = useArbi()\n return useQuery({\n queryKey: connectorQueryKeys.driveFolderChildren(vendorKey, itemId),\n queryFn: () => arbi.connectors.driveFolderChildren(vendorKey, itemId),\n enabled: enabled && arbi.isLoggedIn,\n staleTime: 30_000,\n })\n}\n\n/** The \"(N)\" next to a folder: what selecting it would import. */\nexport function useDriveFolderDocCount(vendorKey: string, itemId: string, enabled: boolean) {\n const arbi = useArbi()\n return useQuery({\n queryKey: connectorQueryKeys.driveFolderDocCount(vendorKey, itemId),\n queryFn: () => arbi.connectors.driveFolderDocCount(vendorKey, itemId),\n enabled: enabled && arbi.isLoggedIn,\n staleTime: 5 * 60_000,\n })\n}\n\nexport interface EnableDriveSyncVars {\n vendorKey: string\n workspaceExtId: string\n folders: string[]\n skipDuplicates: boolean\n autoRename: boolean\n shared: boolean\n autoSync: boolean\n}\n\n/** Enable drive sync (409: reconnect for the files scope). */\nexport function useEnableDriveSync() {\n const arbi = useArbi()\n return useConnectorMutation((v: EnableDriveSyncVars) =>\n arbi.connectors.enableDriveSync(v.vendorKey, {\n workspace_ext_id: v.workspaceExtId,\n folders: v.folders,\n skip_duplicates: v.skipDuplicates,\n auto_rename: v.autoRename,\n shared: v.shared,\n auto_sync: v.autoSync,\n })\n )\n}\n\n/** Drive Sync now (404: none set up, 409: reconnect, 425: the session token is not bridged yet). */\nexport function useTriggerDriveSync() {\n const arbi = useArbi()\n return useConnectorMutation(({ vendorKey }: { vendorKey: string }) =>\n arbi.connectors.syncDrive(vendorKey)\n )\n}\n\nexport function useDriveSyncEstimate(vendorKey: string, enabled: boolean) {\n const arbi = useArbi()\n return useQuery({\n queryKey: connectorQueryKeys.driveSyncEstimate(vendorKey),\n queryFn: () => arbi.connectors.driveSyncEstimate(vendorKey),\n enabled: enabled && arbi.isLoggedIn,\n staleTime: 30_000,\n })\n}\n\n/** Polled while a run is active; the poll after it ends carries the run's `summary`. */\nexport function useDriveSyncProgress(vendorKey: string, enabled: boolean) {\n const arbi = useArbi()\n return useQuery({\n queryKey: connectorQueryKeys.driveSyncProgress(vendorKey),\n queryFn: () => arbi.connectors.driveSyncProgress(vendorKey),\n enabled: enabled && arbi.isLoggedIn,\n refetchInterval: (query) => (query.state.data?.running ? 1500 : false),\n staleTime: 0,\n })\n}\n\nexport function useCancelDriveSync() {\n const arbi = useArbi()\n return useMutation({\n mutationFn: ({ vendorKey }: { vendorKey: string }) =>\n arbi.connectors.cancelDriveSync(vendorKey),\n })\n}\n\n// ── Slack ───────────────────────────────────────────────────────────────────\n\nexport function useSlackConnection() {\n const arbi = useArbi()\n return useQuery({\n queryKey: connectorQueryKeys.slack(),\n queryFn: () => arbi.connectors.slack.status(),\n enabled: arbi.isLoggedIn,\n // Fresh on every visit: the OAuth return lands here before the status changed server-side.\n staleTime: 0,\n refetchOnMount: 'always',\n refetchOnWindowFocus: true,\n })\n}\n\nexport function useDisconnectSlack() {\n const arbi = useArbi()\n return useConnectorMutation<void, void>(() => arbi.connectors.slack.disconnect())\n}\n\n// ── Session ─────────────────────────────────────────────────────────────────\n\n/** Refresh the connections when a sync run ends (their \"last synced\" and counts change). */\nexport function useRefreshConnectorsOnRunEnd(running: boolean) {\n const qc = useQueryClient()\n const wasRunning = useRef(running)\n useEffect(() => {\n if (wasRunning.current && !running) {\n void qc.invalidateQueries({ queryKey: connectorQueryKeys.mine() })\n }\n wasRunning.current = running\n }, [running, qc])\n}\n\n/** The least time between two re-checks on tab focus (the server keeps its own floor). */\nconst FOCUS_RECHECK_MS = 60_000\n\n/** Run `check` now, and again when the tab comes back (at most once a minute); returns the cleanup. */\nfunction checkNowAndOnFocus(check: () => void): () => void {\n let lastCheck = Date.now()\n check()\n const onVisible = () => {\n if (document.visibilityState !== 'visible') return\n if (Date.now() - lastCheck < FOCUS_RECHECK_MS) return\n lastCheck = Date.now()\n check()\n }\n document.addEventListener('visibilitychange', onVisible)\n return () => document.removeEventListener('visibilitychange', onVisible)\n}\n\n/**\n * Start the due auto-syncs into the open workspace, and file the ARBI mail waiting for it. The\n * server starts connector syncs from the token bridge, and only for a workspace whose key is on the\n * session, so this bridges once the workspace is open\n * and again when the tab comes back (at most once a minute), then refreshes the connections and\n * progress so the import panels pick a new run up.\n */\nexport function useConnectorAutoSync(workspaceExtId: string | null | undefined, opened: boolean) {\n const arbi = useArbi()\n const qc = useQueryClient()\n // Only people with mail have an ARBI mailbox to file from (no refused calls for the others).\n const hasMail = useIsEntitled('mail')\n useEffect(() => {\n if (!opened || !workspaceExtId || !arbi.isLoggedIn) return\n return checkNowAndOnFocus(() => {\n void arbi.connectors.bridgeTokens({ autoSyncWorkspaceExtId: workspaceExtId }).then(() => {\n void qc.invalidateQueries({ queryKey: connectorQueryKeys.mine() })\n void qc.invalidateQueries({ queryKey: connectorQueryKeys.allMailboxSyncProgress() })\n void qc.invalidateQueries({ queryKey: connectorQueryKeys.allDriveSyncProgress() })\n })\n })\n }, [opened, workspaceExtId, arbi, qc])\n useEffect(() => {\n if (!opened || !workspaceExtId || !arbi.isLoggedIn || !hasMail) return\n // The ARBI mailbox files into a workspace the same way: what arrived while the user was away is\n // filed now, with this session (nothing waits for most people: one small read).\n return checkNowAndOnFocus(() => {\n void arbi.mail\n .fileWaiting(workspaceExtId)\n .then(({ filed }) => {\n if (filed) void qc.invalidateQueries({ queryKey: mailQueryKeys.allFiling() })\n })\n .catch((error: unknown) => logger.warn('[mail] could not file waiting mail', error))\n })\n }, [opened, workspaceExtId, arbi, qc, hasMail])\n}\n\n/** The HTTP status of a failed connector call (403, 404, 409, 425…), to say what went wrong. */\nexport function connectorErrorStatus(err: unknown): number | undefined {\n return err instanceof ArbiApiError ? err.status : undefined\n}\n","/**\n * What a host adds to the calendar hooks (the host configuration's `calendar`), all optional:\n * keeping the calendar on this device (offline reads and a write outbox), and where the OAuth of a\n * Google or Microsoft account comes back to. Without it the hooks read and write online only.\n * Accounts connect through the user's connectors (`arbi.connectors`) unless the host supplies its\n * own.\n */\n\nimport { useMemo } from 'react'\nimport { useQueryClient } from '@tanstack/react-query'\nimport { useArbi } from '../useArbi'\nimport { useArbiHost } from '../host/config'\nimport { connectorQueryKeys } from '../connectors/hooks'\nimport type {\n EventCreateBody,\n EventPatchBody,\n RespondParams,\n ScopedTarget,\n} from '@arbidocs/sdk/browser'\n\n/** A write the outbox can hold while offline. */\nexport type CalendarWriteOp =\n | { kind: 'create'; body: EventCreateBody }\n | { kind: 'update'; target: ScopedTarget; body: EventPatchBody }\n | { kind: 'delete'; target: ScopedTarget & { notify?: boolean } }\n | { kind: 'respond'; params: RespondParams }\n\n/** A write made offline: queued on this device and sent exactly once when back online. */\nexport interface QueuedCalendarWrite {\n queued: true\n requestId: string\n}\n\nexport function isQueuedCalendarWrite(value: unknown): value is QueuedCalendarWrite {\n return !!value && typeof value === 'object' && (value as QueuedCalendarWrite).queued === true\n}\n\n/** A write waiting in the outbox (a queued create is drawn on the grid as pending). */\nexport interface CalendarPendingWrite {\n requestId: string\n op: CalendarWriteOp\n state: string\n inDoubt?: boolean\n error?: string\n}\n\nexport interface CalendarOfflineSupport {\n /**\n * Run a read online and keep the result on this device; when the network is down, answer from\n * that copy. `key` identifies the read (its query key).\n */\n read<T>(key: readonly unknown[], fetch: () => Promise<T>): Promise<T>\n /** Send a write, or, offline, queue it and answer {@link QueuedCalendarWrite}. */\n write<T>(op: CalendarWriteOp, send: () => Promise<T>): Promise<T | QueuedCalendarWrite>\n /** The writes waiting in the outbox. */\n pending(): Promise<CalendarPendingWrite[]>\n /** Be told when the outbox changes. Returns the unsubscribe. */\n subscribe(listener: () => void): () => void\n}\n\nexport interface CalendarConnectorSupport {\n /** The URL that starts a connector's OAuth consent and comes back to `returnPath`. */\n authorize(vendor: string, returnPath: string): Promise<string>\n /** Hand this server session the connector's sealed grant (the server answered 401 without it). */\n bridge(vendor: string): Promise<void>\n /** The vendor keys of the user's connected connectors. */\n connectedVendors(): Promise<string[]>\n}\n\nexport interface CalendarSupport {\n offline?: CalendarOfflineSupport\n connectors?: CalendarConnectorSupport\n /** Where the OAuth consent returns to (default: the current page). */\n oauthReturnPath?: string\n}\n\nconst NO_SUPPORT: CalendarSupport = {}\n\nexport function useCalendarSupport(): CalendarSupport {\n const support = useArbiHost().calendar ?? NO_SUPPORT\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMemo<CalendarSupport>(\n () => ({\n ...support,\n connectors: support.connectors ?? {\n authorize: (vendor, returnPath) => arbi.connectors.authorize(vendor, returnPath),\n bridge: (vendor) => arbi.connectors.bridgeTokens({ vendor }),\n connectedVendors: async () =>\n (\n await qc.fetchQuery({\n queryKey: connectorQueryKeys.mine(),\n queryFn: () => arbi.connectors.mine(),\n staleTime: 30_000,\n })\n ).map((c) => c.vendor_key),\n },\n }),\n [support, arbi, qc]\n )\n}\n","/**\n * Native calendar hooks over `arbi.calendar`: settings, calendars, events, overlays, invitations,\n * sharing, subscriptions, holidays, rooms and scheduling. Writes refresh what they change.\n *\n * With a host `calendar` that keeps the calendar offline, the settings, calendars and\n * event reads answer from this device when the network is down, and event writes made offline are\n * queued (they resolve to a {@link QueuedCalendarWrite}).\n *\n * Requires an `ArbiHost` (with an `arbi`) and a React Query client above it.\n */\n\nimport { useEffect } from 'react'\nimport { useMutation, useQuery, useQueryClient, type QueryClient } from '@tanstack/react-query'\nimport type {\n CalendarEvent,\n CalendarSettings,\n CalendarSettingsBody,\n CalendarUpdate,\n CalendarWindow,\n EventCreateBody,\n EventPatchBody,\n FindTimeParams,\n ListEventsParams,\n OverlayLayerName,\n RespondParams,\n RoomCreateBody,\n RoomQuery,\n ScopedTarget,\n ShareRole,\n} from '@arbidocs/sdk/browser'\nimport { useArbi } from '../useArbi'\nimport { calendarQueryKeys } from './keys'\nimport { useCalendarSupport, type CalendarPendingWrite, type CalendarWriteOp } from './support'\n\n/** Refresh every event read (lists, single events, invitations, invitation lookups). */\nexport function invalidateCalendarEvents(qc: QueryClient) {\n return Promise.all([\n qc.invalidateQueries({ queryKey: calendarQueryKeys.events() }),\n qc.invalidateQueries({ queryKey: calendarQueryKeys.eventDetails() }),\n qc.invalidateQueries({ queryKey: calendarQueryKeys.invitations() }),\n qc.invalidateQueries({ queryKey: calendarQueryKeys.allLookups() }),\n ])\n}\n\n/** Refresh the calendar list and the events drawn from it. */\nexport function invalidateCalendars(qc: QueryClient) {\n return Promise.all([\n qc.invalidateQueries({ queryKey: calendarQueryKeys.calendars() }),\n qc.invalidateQueries({ queryKey: calendarQueryKeys.events() }),\n ])\n}\n\n/** A read kept on this device when the host keeps the calendar offline. */\nfunction useOfflineRead() {\n const { offline } = useCalendarSupport()\n return {\n read: <T>(key: readonly unknown[], fetch: () => Promise<T>): Promise<T> =>\n offline ? offline.read(key, fetch) : fetch(),\n // Offline-capable queries must run without the network to reach the saved copy.\n networkMode: offline ? ('always' as const) : undefined,\n }\n}\n\n/** A write queued on this device when offline (when the host keeps the calendar offline). */\nfunction useOfflineWrite() {\n const { offline } = useCalendarSupport()\n return {\n write: <T>(op: CalendarWriteOp, send: () => Promise<T>) =>\n offline ? offline.write(op, send) : send(),\n networkMode: offline ? ('always' as const) : undefined,\n }\n}\n\n// ── Reads ────────────────────────────────────────────────────────────────────\n\nexport function useCalendarSettings(enabled = true) {\n const arbi = useArbi()\n const { read, networkMode } = useOfflineRead()\n return useQuery({\n queryKey: calendarQueryKeys.settings(),\n queryFn: () => read(calendarQueryKeys.settings(), () => arbi.calendar.getSettings()),\n networkMode,\n enabled: enabled && arbi.isLoggedIn,\n staleTime: 5 * 60_000,\n retry: false,\n })\n}\n\nexport function useCalendars(enabled = true) {\n const arbi = useArbi()\n const { read, networkMode } = useOfflineRead()\n return useQuery({\n queryKey: calendarQueryKeys.calendars(),\n queryFn: () => read(calendarQueryKeys.calendars(), () => arbi.calendar.listCalendars()),\n networkMode,\n enabled: enabled && arbi.isLoggedIn,\n staleTime: 60_000,\n retry: false,\n })\n}\n\n/** Events in a window (`null`: off). The previous window's events stay while the next loads. */\nexport function useCalendarEvents(params: ListEventsParams | null) {\n const arbi = useArbi()\n const { read, networkMode } = useOfflineRead()\n return useQuery({\n queryKey: params ? calendarQueryKeys.eventList(params) : calendarQueryKeys.events(),\n queryFn: () =>\n read(calendarQueryKeys.eventList(params as ListEventsParams), () =>\n arbi.calendar.listEvents(params as ListEventsParams)\n ),\n networkMode,\n enabled: !!params && arbi.isLoggedIn,\n staleTime: 30_000,\n placeholderData: (previous) => previous,\n retry: false,\n })\n}\n\n/** One event (one occurrence with `recurrenceId`). */\nexport function useCalendarEvent(id: string | null | undefined, recurrenceId?: string | null) {\n const arbi = useArbi()\n const { read, networkMode } = useOfflineRead()\n return useQuery({\n queryKey: calendarQueryKeys.event(id ?? '', recurrenceId),\n queryFn: () =>\n read(calendarQueryKeys.event(id as string, recurrenceId), () =>\n arbi.calendar.getEvent(id as string, recurrenceId)\n ),\n networkMode,\n enabled: !!id && arbi.isLoggedIn,\n retry: false,\n })\n}\n\n/** Fetch one event through the cache, outside render (a deep link, an occurrence's series). */\nexport function useFetchCalendarEvent() {\n const arbi = useArbi()\n const qc = useQueryClient()\n const { read, networkMode } = useOfflineRead()\n return (id: string, recurrenceId?: string | null): Promise<CalendarEvent> =>\n qc.fetchQuery({\n queryKey: calendarQueryKeys.event(id, recurrenceId),\n queryFn: () =>\n read(calendarQueryKeys.event(id, recurrenceId), () =>\n arbi.calendar.getEvent(id, recurrenceId)\n ),\n networkMode,\n retry: false,\n })\n}\n\n/**\n * The open workspace's overlay layers; off without an open workspace or with no layer on. The\n * server answers for the workspace open on the session, so a read is kept only if the workspace\n * it is keyed by stayed open meanwhile, and what is shown while the next range loads is never\n * another workspace's.\n */\nexport function useCalendarOverlays(range: CalendarWindow | null, layers: OverlayLayerName[]) {\n const arbi = useArbi()\n const workspaceId = arbi.hasWorkspace ? arbi.getWorkspaceId() : null\n return useQuery({\n queryKey: calendarQueryKeys.overlays(workspaceId, range ?? undefined, layers),\n queryFn: () =>\n arbi.readInWorkspace(workspaceId as string, () =>\n arbi.calendar.listOverlays(range as CalendarWindow, layers)\n ),\n enabled: !!workspaceId && !!range && layers.length > 0,\n staleTime: 60_000,\n // ['arbi', 'calendar', 'overlays', workspaceId, window]\n placeholderData: (previous, previousQuery) =>\n previousQuery?.queryKey[3] === workspaceId ? previous : undefined,\n retry: false,\n })\n}\n\n/** The writes waiting in the offline outbox (empty without offline support). */\nexport function useCalendarOutbox() {\n const qc = useQueryClient()\n const { offline } = useCalendarSupport()\n useEffect(\n () =>\n offline?.subscribe(() => {\n void qc.invalidateQueries({ queryKey: calendarQueryKeys.outbox() })\n }),\n [offline, qc]\n )\n return useQuery({\n queryKey: calendarQueryKeys.outbox(),\n queryFn: (): Promise<CalendarPendingWrite[]> =>\n offline ? offline.pending() : Promise.resolve([]),\n networkMode: 'always',\n staleTime: Infinity,\n })\n}\n\nexport function useCalendarShares(calId: string | null) {\n const arbi = useArbi()\n return useQuery({\n queryKey: calendarQueryKeys.shares(calId ?? ''),\n queryFn: () => arbi.calendar.listShares(calId as string),\n enabled: !!calId && arbi.isLoggedIn,\n retry: false,\n })\n}\n\nexport function useHolidayCountries(enabled = true) {\n const arbi = useArbi()\n return useQuery({\n queryKey: calendarQueryKeys.holidayCountries(),\n queryFn: () => arbi.calendar.listHolidayCountries(),\n enabled: enabled && arbi.isLoggedIn,\n staleTime: Infinity,\n retry: false,\n })\n}\n\n/** Rooms (free in a window when it is given); `null`: off. */\nexport function useRooms(q: RoomQuery | null) {\n const arbi = useArbi()\n return useQuery({\n queryKey: calendarQueryKeys.rooms(q ?? {}),\n queryFn: () => arbi.calendar.listRooms(q ?? {}),\n enabled: !!q && arbi.isLoggedIn,\n staleTime: 30_000,\n placeholderData: (previous) => previous,\n retry: false,\n })\n}\n\nexport function useFreeBusy(attendees: string[], start: string | null, end: string | null) {\n const arbi = useArbi()\n return useQuery({\n queryKey: calendarQueryKeys.freebusy(attendees, start ?? '', end ?? ''),\n queryFn: () =>\n arbi.calendar.freeBusy({ attendees, start: start as string, end: end as string }),\n enabled: attendees.length > 0 && !!start && !!end && arbi.isLoggedIn,\n staleTime: 30_000,\n placeholderData: (previous) => previous,\n retry: false,\n })\n}\n\n/** Invitations and new-time proposals waiting for me, re-read every minute. */\nexport function useCalendarInvitations() {\n const arbi = useArbi()\n return useQuery({\n queryKey: calendarQueryKeys.invitations(),\n queryFn: () => arbi.calendar.listInvitations(),\n enabled: arbi.isLoggedIn,\n staleTime: 30_000,\n refetchInterval: 60_000,\n retry: false,\n })\n}\n\n/** My copy of an event by its iCalendar UID (`null` data: not in my calendar). */\nexport function useCalendarEventByUid(uid: string | null) {\n const arbi = useArbi()\n return useQuery({\n queryKey: calendarQueryKeys.lookup(uid ?? ''),\n queryFn: () => arbi.calendar.lookupByUid(uid as string),\n enabled: !!uid && arbi.isLoggedIn,\n retry: false,\n })\n}\n\n// ── Writes ───────────────────────────────────────────────────────────────────\n\nexport function useSaveCalendarSettings() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: (body: CalendarSettingsBody) => arbi.calendar.putSettings(body),\n onSuccess: (data: CalendarSettings) => qc.setQueryData(calendarQueryKeys.settings(), data),\n })\n}\n\nexport function useCreateCalendar() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: (body: Parameters<typeof arbi.calendar.createCalendar>[0]) =>\n arbi.calendar.createCalendar(body),\n onSuccess: () => invalidateCalendars(qc),\n })\n}\n\nexport function useUpdateCalendar() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: ({ id, body }: { id: string; body: CalendarUpdate }) =>\n arbi.calendar.updateCalendar(id, body),\n onSuccess: () => invalidateCalendars(qc),\n })\n}\n\nexport function useDeleteCalendar() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: (calId: string) => arbi.calendar.deleteCalendar(calId),\n onSuccess: () => invalidateCalendars(qc),\n })\n}\n\n// Event writes finish when persistence (or offline queuing) succeeds. Refresh reads immediately,\n// without making mutation callbacks and editor pending state wait for unrelated calendar queries.\nexport function useCreateEvent() {\n const arbi = useArbi()\n const qc = useQueryClient()\n const { write, networkMode } = useOfflineWrite()\n return useMutation({\n mutationFn: (body: EventCreateBody) =>\n write({ kind: 'create', body }, () => arbi.calendar.createEvent(body)),\n networkMode,\n onSuccess: () => {\n void invalidateCalendarEvents(qc)\n },\n })\n}\n\nexport function useUpdateEvent() {\n const arbi = useArbi()\n const qc = useQueryClient()\n const { write, networkMode } = useOfflineWrite()\n return useMutation({\n mutationFn: ({ target, body }: { target: ScopedTarget; body: EventPatchBody }) =>\n write({ kind: 'update', target, body }, () => arbi.calendar.updateEvent(target, body)),\n networkMode,\n onSuccess: () => {\n void invalidateCalendarEvents(qc)\n },\n })\n}\n\nexport function useDeleteEvent() {\n const arbi = useArbi()\n const qc = useQueryClient()\n const { write, networkMode } = useOfflineWrite()\n return useMutation({\n mutationFn: (target: ScopedTarget & { notify?: boolean }) =>\n write({ kind: 'delete', target }, () => arbi.calendar.deleteEvent(target)),\n networkMode,\n onSuccess: () => {\n void invalidateCalendarEvents(qc)\n },\n })\n}\n\nexport function useMoveEvent() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: ({ id, calendarId }: { id: string; calendarId: string }) =>\n arbi.calendar.moveEvent(id, calendarId),\n onSuccess: () => {\n void invalidateCalendarEvents(qc)\n },\n })\n}\n\nexport function useRespondToEvent() {\n const arbi = useArbi()\n const qc = useQueryClient()\n const { write, networkMode } = useOfflineWrite()\n return useMutation({\n mutationFn: (params: RespondParams) =>\n write({ kind: 'respond', params }, () => arbi.calendar.respond(params)),\n networkMode,\n onSuccess: () => {\n void invalidateCalendarEvents(qc)\n },\n })\n}\n\nexport function useImportCalendar() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: ({ ics, calendarId }: { ics: string; calendarId?: string | null }) =>\n arbi.calendar.importIcs(ics, calendarId),\n onSuccess: () => {\n void invalidateCalendarEvents(qc)\n },\n })\n}\n\nexport function useShareCalendar() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: ({ calId, grantee, role }: { calId: string; grantee: string; role: ShareRole }) =>\n arbi.calendar.share(calId, grantee, role),\n onSuccess: (_d, v) => qc.invalidateQueries({ queryKey: calendarQueryKeys.shares(v.calId) }),\n })\n}\n\nexport function useUnshareCalendar() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: ({ calId, userId }: { calId: string; userId: string }) =>\n arbi.calendar.unshare(calId, userId),\n onSuccess: (_d, v) => qc.invalidateQueries({ queryKey: calendarQueryKeys.shares(v.calId) }),\n })\n}\n\nexport function useSubscribeCalendar() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: (body: Parameters<typeof arbi.calendar.subscribe>[0]) =>\n arbi.calendar.subscribe(body),\n onSuccess: () => invalidateCalendars(qc),\n })\n}\n\nexport function useRefreshCalendar() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: (calId: string) => arbi.calendar.refresh(calId),\n onSuccess: () => invalidateCalendars(qc),\n })\n}\n\nexport function useAddHolidayCalendar() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: (body: Parameters<typeof arbi.calendar.addHolidays>[0]) =>\n arbi.calendar.addHolidays(body),\n onSuccess: () => invalidateCalendars(qc),\n })\n}\n\nexport function useCreateRoom() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: (body: RoomCreateBody) => arbi.calendar.createRoom(body),\n onSuccess: () => qc.invalidateQueries({ queryKey: calendarQueryKeys.allRooms() }),\n })\n}\n\nexport function useFindTime() {\n const arbi = useArbi()\n return useMutation({ mutationFn: (body: FindTimeParams) => arbi.calendar.findTime(body) })\n}\n\n/** Accept or decline a proposed new time. */\nexport function useDecideCounter() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: ({\n id,\n accept,\n comment,\n }: {\n id: string\n accept: boolean\n comment?: string | null\n }) => arbi.calendar.decideCounter(id, accept, comment),\n onSuccess: () => {\n void invalidateCalendarEvents(qc)\n },\n })\n}\n\n/** Publish an own calendar into a connected account. */\nexport function usePublishCalendar() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: ({ accountId, calendarId }: { accountId: string; calendarId: string }) =>\n arbi.calendar.publishToAccount(accountId, calendarId),\n onSuccess: () => {\n void invalidateCalendars(qc)\n // The account list says which calendars each account mirrors (the provider badge).\n void qc.invalidateQueries({ queryKey: calendarQueryKeys.accounts() })\n },\n })\n}\n","/**\n * Connected calendar accounts (Google, Microsoft, CalDAV) and booking pages.\n * A Google or Microsoft account connects through the host's connector OAuth\n * (`CalendarSupport.connectors`): the intent survives the redirect in sessionStorage and\n * {@link useResumeCalendarAccountConnect} finishes it on return.\n */\n\nimport { useEffect, useRef, useState } from 'react'\nimport { useMutation, useQuery, useQueryClient, type QueryClient } from '@tanstack/react-query'\nimport {\n ACCOUNT_VENDOR,\n ArbiApiError,\n type Arbi,\n type BookingPageWriteBody,\n type CalDavConnectBody,\n type CalendarAccount,\n type OAuthAccountKind,\n} from '@arbidocs/sdk/browser'\nimport { useArbi } from '../useArbi'\nimport { calendarQueryKeys } from './keys'\nimport { useCalendarSupport, type CalendarConnectorSupport } from './support'\n\nfunction invalidateAccounts(qc: QueryClient) {\n return Promise.all([\n qc.invalidateQueries({ queryKey: calendarQueryKeys.accounts() }),\n qc.invalidateQueries({ queryKey: calendarQueryKeys.calendars() }),\n qc.invalidateQueries({ queryKey: calendarQueryKeys.events() }),\n ])\n}\n\nexport function useCalendarAccounts(enabled = true) {\n const arbi = useArbi()\n return useQuery({\n queryKey: calendarQueryKeys.accounts(),\n queryFn: () => arbi.calendar.listAccounts(),\n enabled: enabled && arbi.isLoggedIn,\n staleTime: 30_000,\n retry: false,\n })\n}\n\nexport function useCalDavProfiles(enabled = true) {\n const arbi = useArbi()\n return useQuery({\n queryKey: calendarQueryKeys.caldavProfiles(),\n queryFn: () => arbi.calendar.listCalDavProfiles(),\n enabled: enabled && arbi.isLoggedIn,\n staleTime: 10 * 60_000,\n retry: false,\n })\n}\n\n/**\n * Mirror a Google or Microsoft account. When the server says the connector's grant is not in this\n * session yet (401), bridge it once and retry.\n */\nexport async function connectOAuthCalendarAccount(\n arbi: Arbi,\n connectors: CalendarConnectorSupport | undefined,\n kind: OAuthAccountKind,\n backgroundSync = false\n): Promise<CalendarAccount> {\n try {\n return await arbi.calendar.connectOAuthAccount(kind, backgroundSync)\n } catch (err) {\n if (!(err instanceof ArbiApiError) || err.status !== 401 || !connectors) throw err\n await connectors.bridge(ACCOUNT_VENDOR[kind])\n return arbi.calendar.connectOAuthAccount(kind, backgroundSync)\n }\n}\n\nexport function useConnectOAuthAccount() {\n const arbi = useArbi()\n const { connectors } = useCalendarSupport()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: ({ kind, backgroundSync }: { kind: OAuthAccountKind; backgroundSync?: boolean }) =>\n connectOAuthCalendarAccount(arbi, connectors, kind, !!backgroundSync),\n onSuccess: () => invalidateAccounts(qc),\n })\n}\n\nexport function useConnectCalDavAccount() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: (body: CalDavConnectBody) => arbi.calendar.connectCalDavAccount(body),\n onSuccess: () => invalidateAccounts(qc),\n })\n}\n\nexport function useUpdateCalendarAccount() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: ({ id, backgroundSync }: { id: string; backgroundSync: boolean }) =>\n arbi.calendar.updateAccount(id, backgroundSync),\n onSuccess: () => invalidateAccounts(qc),\n })\n}\n\nexport function useSyncCalendarAccount() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: (id: string) => arbi.calendar.syncAccount(id),\n onSettled: () => invalidateAccounts(qc),\n })\n}\n\nexport function useDisconnectCalendarAccount() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: (id: string) => arbi.calendar.disconnectAccount(id),\n onSuccess: () => invalidateAccounts(qc),\n })\n}\n\n// ── OAuth round trip: the intent survives the redirect ──────────────────────\n\nconst PENDING_CONNECT_KEY = 'arbi-calendar-pending-account-connect'\n\ninterface PendingConnect {\n kind: OAuthAccountKind\n backgroundSync: boolean\n at: number\n}\n\nfunction readPendingConnect(): PendingConnect | null {\n try {\n const raw = window.sessionStorage.getItem(PENDING_CONNECT_KEY)\n if (!raw) return null\n const value = JSON.parse(raw) as PendingConnect\n // Stale after 30 minutes: the consent screen was abandoned.\n if (!value || Date.now() - value.at > 30 * 60_000) return null\n return value\n } catch {\n return null\n }\n}\n\nfunction clearPendingConnect() {\n try {\n window.sessionStorage.removeItem(PENDING_CONNECT_KEY)\n } catch {\n /* storage unavailable */\n }\n}\n\n/**\n * Start a Google or Microsoft account connect: remember the intent, then go to the connector's\n * consent. `useResumeCalendarAccountConnect` finishes it after the redirect back. `undefined`\n * when the host offers no connector OAuth.\n */\nexport function useStartCalendarAccountOAuth():\n ((kind: OAuthAccountKind, backgroundSync?: boolean) => Promise<void>) | undefined {\n const { connectors, oauthReturnPath } = useCalendarSupport()\n if (!connectors) return undefined\n return async (kind, backgroundSync = false) => {\n try {\n window.sessionStorage.setItem(\n PENDING_CONNECT_KEY,\n JSON.stringify({ kind, backgroundSync, at: Date.now() } satisfies PendingConnect)\n )\n } catch {\n /* without storage, Connect is clicked once more after returning */\n }\n const returnPath = oauthReturnPath ?? `${window.location.pathname}${window.location.search}`\n window.location.assign(await connectors.authorize(ACCOUNT_VENDOR[kind], returnPath))\n }\n}\n\n/**\n * After an OAuth round trip started by `useStartCalendarAccountOAuth`, mirror the account once\n * its connector shows as connected.\n */\nexport function useResumeCalendarAccountConnect(\n onDone?: (result: { account?: CalendarAccount; error?: unknown }) => void\n) {\n const { connectors } = useCalendarSupport()\n const connect = useConnectOAuthAccount()\n const started = useRef(false)\n useEffect(() => {\n if (started.current || !connectors) return\n const pending = readPendingConnect()\n if (!pending) return\n let live = true\n void connectors\n .connectedVendors()\n .then((vendors) => {\n if (!live || started.current || !vendors.includes(ACCOUNT_VENDOR[pending.kind])) return\n started.current = true\n clearPendingConnect()\n connect.mutate(\n { kind: pending.kind, backgroundSync: pending.backgroundSync },\n {\n onSuccess: (account) => onDone?.({ account }),\n onError: (error) => onDone?.({ error }),\n }\n )\n })\n .catch(() => {})\n return () => {\n live = false\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps -- once per mount\n }, [connectors])\n return connect\n}\n\n// ── Sync on open ─────────────────────────────────────────────────────────────\n\nconst syncedThisSession = new Set<string>()\n\n/** Test hook: forget which accounts were synced this page load. */\nexport function resetCalendarAccountSyncState() {\n syncedThisSession.clear()\n}\n\n/**\n * Pull and push every connected account once per page load when the calendar opens: the server\n * syncs foreground accounts only with a live session's grant.\n */\nexport function useSyncAccountsOnOpen(enabled = true) {\n const arbi = useArbi()\n const { data: accounts } = useCalendarAccounts(enabled)\n const qc = useQueryClient()\n const [syncing, setSyncing] = useState(false)\n useEffect(() => {\n if (!enabled || !accounts?.length) return\n const due = accounts.filter((a) => !syncedThisSession.has(a.id))\n if (!due.length) return\n for (const a of due) syncedThisSession.add(a.id)\n setSyncing(true)\n void Promise.allSettled(due.map((a) => arbi.calendar.syncAccount(a.id))).then(() => {\n setSyncing(false)\n void invalidateAccounts(qc)\n })\n }, [enabled, accounts, arbi, qc])\n return { syncing }\n}\n\n// ── Booking pages ────────────────────────────────────────────────────────────\n\nexport function useBookingPages(enabled = true) {\n const arbi = useArbi()\n return useQuery({\n queryKey: calendarQueryKeys.bookingPages(),\n queryFn: () => arbi.calendar.listBookingPages(),\n enabled: enabled && arbi.isLoggedIn,\n staleTime: 30_000,\n retry: false,\n })\n}\n\nexport function useSaveBookingPage() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: (body: BookingPageWriteBody) => arbi.calendar.putBookingPage(body),\n onSuccess: () => qc.invalidateQueries({ queryKey: calendarQueryKeys.bookingPages() }),\n })\n}\n\nexport function useDeleteBookingPage() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationFn: (slug: string) => arbi.calendar.deleteBookingPage(slug),\n onSuccess: () => qc.invalidateQueries({ queryKey: calendarQueryKeys.bookingPages() }),\n })\n}\n","import type { OfflineSealer } from '@arbidocs/client'\nimport type { RecordStore } from './store'\n\n/** Forget a store's keys and delete its database. */\nexport async function wipeStore(sealer: OfflineSealer, store: RecordStore<string>): Promise<void> {\n sealer.forget()\n await store.deleteDatabase()\n}\n","/**\n * The offline calendar: an encrypted IndexedDB cache of fetched calendar data (event windows,\n * calendars, settings) and an exactly-once Outbox of writes made while offline.\n *\n * Storage is the generic encrypted record store (`../../offline-store`) under its own database\n * (`arbi-offline-calendar`) and key namespace (`arbi-offline-calendar-v1`), keyed by the user's\n * identity like the offline mailbox: nothing readable is written to disk, and another account's\n * records are unreadable (and ignored).\n *\n * Outbox semantics (the calendar API has no request-id dedupe):\n * - every write keeps the `requestId` it was given when queued, for its whole life;\n * - replay is in order and stops at the first network failure (order is kept);\n * - a refusal (4xx) is final: \"failed\", never retried automatically;\n * - a network failure or 5xx keeps the write queued. For a create that may already have reached the\n * server it is marked `inDoubt`; before re-sending an in-doubt create the executor's\n * `findCreated` is asked whether the server already has it, and if so it is marked sent instead\n * of being created twice. Updates, deletes and responses set absolute state, so a retry is safe;\n * - a write left \"sending\" (tab closed mid-request) is treated as in doubt.\n * - sent writes leave the Outbox.\n */\n\nimport { createOfflineSealer } from '@arbidocs/client'\nimport type { ScopedTarget } from '@arbidocs/sdk/browser'\nimport { createRecordStore } from '../../offline-store/store'\nimport { isBrowserOffline, isNetworkFailure } from '../../offline-store/network'\nimport { wipeStore } from '../../offline-store/wipe'\nimport type { CalendarPendingWrite, CalendarWriteOp } from '../support'\n\nexport const OFFLINE_CALENDAR_DB = 'arbi-offline-calendar'\nconst CACHE_LIMIT = 200\n\nclass OfflineCalendarLockedError extends Error {\n constructor() {\n super('Sign in to open the calendar saved on this device')\n this.name = 'OfflineCalendarLockedError'\n }\n}\n\ntype Kind = 'cache' | 'outbox'\nconst store = createRecordStore<Kind>(OFFLINE_CALENDAR_DB)\nconst sealer = createOfflineSealer('arbi-offline-calendar-v1', {\n locked: () => new OfflineCalendarLockedError(),\n})\n\n// ── network ──────────────────────────────────────────────────────────────────\n\nexport function isCalendarOffline(): boolean {\n return isBrowserOffline()\n}\n\n/** The request never got an HTTP answer (offline, host unreachable). */\nexport function isCalendarNetworkError(error: unknown): boolean {\n if (isNetworkFailure(error)) return true\n const status = (error as { status?: unknown } | null)?.status\n return typeof status !== 'number' && isBrowserOffline()\n}\n\n// ── cache ────────────────────────────────────────────────────────────────────\n\nconst cacheBucket = () => sealer.blind('bucket', 'cache')\nconst cacheKey = (key: string) => sealer.blind('cache', key)\n\nexport async function writeCalendarCache(key: string, data: unknown): Promise<void> {\n const sealed = await sealer.sealJson({ key, data })\n const now = Date.now()\n await store.putRecord({\n key: await cacheKey(key),\n kind: 'cache',\n bucket: await cacheBucket(),\n sortAt: now,\n size: sealed.length,\n lastAccess: now,\n data: sealed,\n })\n await evictCache()\n}\n\nexport async function readCalendarCache<T>(key: string): Promise<T | null> {\n try {\n const blindKey = await cacheKey(key)\n const record = await store.getRecord(blindKey)\n if (!record) return null\n const opened = await sealer.openJson<{ key: string; data: T }>(record.data)\n if (opened.key !== key) return null\n await store.putRecord({ ...record, lastAccess: Date.now() })\n return opened.data\n } catch {\n // Locked, another account's record, or tampered: treat as not cached.\n return null\n }\n}\n\nasync function evictCache(): Promise<void> {\n const rows = (await store.allRecordAccess()).filter((r) => r.kind === 'cache')\n if (rows.length <= CACHE_LIMIT) return\n rows.sort((a, b) => a.lastAccess - b.lastAccess)\n await store.deleteRecords(rows.slice(0, rows.length - CACHE_LIMIT).map((r) => r.key))\n}\n\n// ── outbox ───────────────────────────────────────────────────────────────────\n\nexport type CalendarOutboxOp = CalendarWriteOp\n\ntype CalendarOutboxState = 'queued' | 'sending' | 'sent' | 'failed'\n\ninterface CalendarOutboxItem {\n requestId: string\n op: CalendarOutboxOp\n state: CalendarOutboxState\n inDoubt?: boolean\n error?: string\n attempts: number\n createdAt: number\n seq: number\n}\n\ntype Op<K extends CalendarOutboxOp['kind']> = Extract<CalendarOutboxOp, { kind: K }>\n\nexport interface CalendarOutboxExecutor {\n create(body: Op<'create'>['body'], requestId: string): Promise<unknown>\n update(target: ScopedTarget, body: Op<'update'>['body'], requestId: string): Promise<unknown>\n delete(target: Op<'delete'>['target'], requestId: string): Promise<unknown>\n respond(params: Op<'respond'>['params'], requestId: string): Promise<unknown>\n /** Whether an in-doubt create already reached the server (no server-side dedupe). */\n findCreated?(requestId: string, body: Op<'create'>['body']): Promise<boolean>\n}\n\nconst outboxBucket = () => sealer.blind('bucket', 'outbox')\nconst outboxKey = (requestId: string) => sealer.blind('outbox', requestId)\nlet seqCounter = 0\n\nasync function writeItem(item: CalendarOutboxItem): Promise<void> {\n const sealed = await sealer.sealJson(item)\n await store.putRecord({\n key: await outboxKey(item.requestId),\n kind: 'outbox',\n bucket: await outboxBucket(),\n sortAt: item.seq,\n size: sealed.length,\n lastAccess: Date.now(),\n data: sealed,\n })\n}\n\nasync function readItems(): Promise<CalendarOutboxItem[]> {\n const records = await store.recordsInBucket(await outboxBucket())\n const items: CalendarOutboxItem[] = []\n for (const record of records) {\n try {\n items.push(await sealer.openJson<CalendarOutboxItem>(record.data))\n } catch {\n // Sealed under a different identity: not this user's; ignore.\n }\n }\n return items.sort((a, b) => a.seq - b.seq)\n}\n\nfunction newRequestId(): string {\n return typeof crypto !== 'undefined' && 'randomUUID' in crypto\n ? crypto.randomUUID()\n : `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`\n}\n\nexport async function enqueueCalendarWrite(op: CalendarOutboxOp): Promise<{ requestId: string }> {\n const now = Date.now()\n // Monotonic even when two writes are queued in the same millisecond.\n seqCounter = Math.max(seqCounter + 1, now * 1000)\n const item: CalendarOutboxItem = {\n requestId: newRequestId(),\n op,\n state: 'queued',\n attempts: 0,\n createdAt: now,\n seq: seqCounter,\n }\n await writeItem(item)\n notify('enqueued')\n return { requestId: item.requestId }\n}\n\nexport async function listCalendarOutbox(): Promise<CalendarPendingWrite[]> {\n try {\n return (await readItems()).map(({ requestId, op, state, inDoubt, error }) => ({\n requestId,\n op,\n state,\n inDoubt,\n error,\n }))\n } catch {\n return []\n }\n}\n\ntype Outcome = 'sent' | 'offline' | 'retry' | 'failed'\n\nfunction classify(error: unknown): Outcome {\n if (isCalendarNetworkError(error)) return 'offline'\n const status = (error as { status?: number } | null)?.status\n if (typeof status === 'number' && status >= 500) return 'retry'\n return 'failed'\n}\n\nfunction run(exec: CalendarOutboxExecutor, item: CalendarOutboxItem): Promise<unknown> {\n const op = item.op\n switch (op.kind) {\n case 'create':\n return exec.create(op.body, item.requestId)\n case 'update':\n return exec.update(op.target, op.body, item.requestId)\n case 'delete':\n return exec.delete(op.target, item.requestId)\n case 'respond':\n return exec.respond(op.params, item.requestId)\n }\n}\n\nlet replaying: Promise<{ sent: number; failed: number; inDoubt: number }> | null = null\n\n/**\n * Send queued writes in order. Concurrent calls in a tab share one run, and tabs take turns through a Web\n * Lock: two tabs replaying at once would both send the same queued create (exactly-once across tabs).\n */\nexport function replayCalendarOutbox(\n exec: CalendarOutboxExecutor\n): Promise<{ sent: number; failed: number; inDoubt: number }> {\n if (replaying) return replaying\n type Result = { sent: number; failed: number; inDoubt: number }\n const locks = typeof navigator !== 'undefined' ? navigator.locks : undefined\n const run: Promise<Result> = locks?.request\n ? (locks.request('arbi-calendar-outbox-replay', () =>\n replayOnce(exec)\n ) as unknown as Promise<Result>)\n : replayOnce(exec)\n const current = run.finally(() => {\n replaying = null\n })\n replaying = current\n return current\n}\n\nasync function replayOnce(\n exec: CalendarOutboxExecutor\n): Promise<{ sent: number; failed: number; inDoubt: number }> {\n const result = { sent: 0, failed: 0, inDoubt: 0 }\n for (const queued of await readItems()) {\n if (queued.state !== 'queued' && queued.state !== 'sending') continue\n if (isCalendarOffline()) break\n // Left \"sending\" by a closed tab: the request may have reached the server.\n let item: CalendarOutboxItem = {\n ...queued,\n inDoubt: queued.inDoubt || queued.state === 'sending',\n }\n if (item.op.kind === 'create' && item.inDoubt && exec.findCreated) {\n let found = false\n try {\n found = await exec.findCreated(item.requestId, item.op.body)\n } catch (error) {\n if (classify(error) === 'offline') break\n }\n if (found) {\n await store.deleteRecords([await outboxKey(item.requestId)])\n result.sent++\n continue\n }\n }\n item = { ...item, state: 'sending', attempts: item.attempts + 1 }\n await writeItem(item)\n let outcome: Outcome\n let message: string | undefined\n try {\n await run(exec, item)\n outcome = 'sent'\n } catch (error) {\n outcome = classify(error)\n message = error instanceof Error ? error.message : 'The change could not be saved'\n }\n if (outcome === 'sent') {\n await store.deleteRecords([await outboxKey(item.requestId)])\n result.sent++\n continue\n }\n if (outcome === 'failed') {\n await writeItem({ ...item, state: 'failed', error: message })\n result.failed++\n continue\n }\n // Network or server error: keep it queued. A create may have been made: in doubt.\n const inDoubt = item.inDoubt || item.op.kind === 'create'\n await writeItem({ ...item, state: 'queued', inDoubt, error: message })\n if (inDoubt) result.inDoubt++\n if (outcome === 'offline') break\n }\n notify()\n return result\n}\n\n// ── change notifications + wipe ─────────────────────────────────────────────\n\nexport type CalendarOutboxChange = 'enqueued' | 'changed'\nconst listeners = new Set<(change: CalendarOutboxChange) => void>()\nfunction notify(change: CalendarOutboxChange = 'changed') {\n for (const l of listeners) l(change)\n}\n/** Subscribe to Outbox changes ('enqueued': a new write was queued); returns the unsubscribe. */\nexport function onCalendarOutboxChange(\n listener: (change: CalendarOutboxChange) => void\n): () => void {\n listeners.add(listener)\n return () => listeners.delete(listener)\n}\n\nexport async function wipeCalendarOffline(): Promise<void> {\n await wipeStore(sealer, store)\n notify()\n}\n\n/**\n * Bind the offline calendar to the account signing in: a store another account wrote on this\n * device is removed (sealed to their key it is unreadable anyway, but its cache and queued writes\n * must not take space or linger).\n */\nexport async function claimCalendarOffline(userExtId: string): Promise<void> {\n const owner = await store.getMeta<string>('owner')\n if (owner && owner !== userExtId) await wipeCalendarOffline()\n await store.setMeta('owner', userExtId)\n}\n","/**\n * The calendar kept on this device, as the calendar hooks take it (the host's\n * `calendar.offline`): reads are remembered (encrypted) and answered from that copy when the\n * network is down; event writes made offline go to the outbox, which `useCalendarOfflineRuntime`\n * replays once back online.\n */\nimport { ArbiApiError } from '@arbidocs/sdk/browser'\nimport type { CalendarOfflineSupport } from '../support'\nimport {\n enqueueCalendarWrite,\n isCalendarNetworkError,\n isCalendarOffline,\n listCalendarOutbox,\n onCalendarOutboxChange,\n readCalendarCache,\n writeCalendarCache,\n} from './outbox'\n\nexport const calendarOfflineSupport: CalendarOfflineSupport = {\n async read(key, fetch) {\n const cacheKey = JSON.stringify(key)\n if (!isCalendarOffline()) {\n try {\n const data = await fetch()\n void writeCalendarCache(cacheKey, data).catch(() => {})\n return data\n } catch (err) {\n if (!isCalendarNetworkError(err)) throw err\n }\n }\n const cached = await readCalendarCache<Awaited<ReturnType<typeof fetch>>>(cacheKey).catch(\n () => null\n )\n if (cached != null) return cached\n throw new ArbiApiError('You are offline and this view is not saved on this device')\n },\n async write(op, send) {\n if (!isCalendarOffline()) return send()\n const { requestId } = await enqueueCalendarWrite(op)\n return { queued: true, requestId }\n },\n pending: listCalendarOutbox,\n subscribe: (listener) => onCalendarOutboxChange(() => listener()),\n}\n","/**\n * useCalendarOfflineRuntime — mounted once by the host for a signed-in user. On reconnect (and at start,\n * when online with a live session) it replays the calendar Outbox (writes made offline) in order,\n * then refreshes the calendar queries.\n */\n\nimport { useEffect } from 'react'\nimport { onlineManager, useQueryClient, type QueryClient } from '@tanstack/react-query'\nimport type { Arbi } from '@arbidocs/sdk/browser'\nimport { logger } from '@arbidocs/client'\nimport { notify } from '../../notifications/notify-store'\nimport { useArbi } from '../../useArbi'\nimport { useArbiSession } from '../../session/signed-in'\nimport { calendarQueryKeys } from '../keys'\nimport {\n claimCalendarOffline,\n onCalendarOutboxChange,\n replayCalendarOutbox,\n type CalendarOutboxExecutor,\n} from './outbox'\n\nconst day = (date: string, offset: number) => {\n const t = new Date(`${date}T00:00:00Z`)\n t.setUTCDate(t.getUTCDate() + offset)\n return t.toISOString()\n}\n\n/** Sends the queued writes on a signed-in session. */\nconst calendarOutboxExecutor = (arbi: Arbi): CalendarOutboxExecutor => ({\n create: (body) => arbi.calendar.createEvent(body),\n update: (target, body) => arbi.calendar.updateEvent(target, body),\n delete: (target) => arbi.calendar.deleteEvent(target),\n respond: (params) => arbi.calendar.respond(params),\n /** No server dedupe: an in-doubt create counts as made if an event with its title and start exists. */\n async findCreated(_requestId, body) {\n const { title, start } = body\n const date = (start?.date_time ?? start?.date ?? '').slice(0, 10)\n if (!title || !/^\\d{4}-\\d{2}-\\d{2}$/.test(date)) return false\n const events = await arbi.calendar.listEvents({\n start: day(date, -1),\n end: day(date, 2),\n })\n return events.some(\n (e) =>\n e.title === title &&\n (start?.date_time\n ? (e.start.date_time ?? '').slice(0, 16) === start.date_time.slice(0, 16)\n : e.start.date === start?.date)\n )\n },\n})\n\n/** Tabs take turns replaying (Web Lock); the one that sent tells the others to refresh. */\nconst SYNC_CHANNEL = 'arbi-calendar-outbox'\n\nfunction refreshCalendarQueries(queryClient: QueryClient) {\n // The outbox list is under the calendar keys too.\n void queryClient.invalidateQueries({ queryKey: calendarQueryKeys.all() })\n}\n\nasync function replay(arbi: Arbi, queryClient: QueryClient): Promise<void> {\n const result = await replayCalendarOutbox(calendarOutboxExecutor(arbi))\n if (result.sent || result.failed) {\n refreshCalendarQueries(queryClient)\n try {\n const channel = new BroadcastChannel(SYNC_CHANNEL)\n channel.postMessage('synced')\n channel.close()\n } catch {\n /* no BroadcastChannel: other tabs refresh on their next fetch */\n }\n }\n if (result.failed)\n notify.error(\n result.failed === 1\n ? 'A calendar change made offline could not be saved'\n : `${result.failed} calendar changes made offline could not be saved`\n )\n}\n\nexport function useCalendarOfflineRuntime(): void {\n const { status, serverSessionKey, user } = useArbiSession()\n const userExtId = user?.external_id\n const authenticated = status === 'signed-in'\n const hasSession = !!serverSessionKey\n // The writes go out on the shared session's `Arbi`, once it holds the login.\n const arbi = useArbi()\n const ready = authenticated && hasSession && arbi.isLoggedIn\n const queryClient = useQueryClient()\n\n useEffect(() => {\n if (!authenticated || !userExtId) return\n claimCalendarOffline(userExtId).catch((error) =>\n logger.warn('[offline-calendar] could not bind the store', error)\n )\n }, [authenticated, userExtId])\n\n useEffect(() => {\n if (!ready) return\n const run = () => {\n if (!onlineManager.isOnline()) return\n replay(arbi, queryClient).catch((error) =>\n logger.warn('[offline-calendar] replay failed', error)\n )\n }\n run()\n let wasOnline = onlineManager.isOnline()\n const offOnline = onlineManager.subscribe((online) => {\n if (online && !wasOnline) run()\n wasOnline = online\n })\n // A write queued while online (e.g. the request failed mid-flight) goes out on the next change.\n let queued: ReturnType<typeof setTimeout> | null = null\n const offOutbox = onCalendarOutboxChange((change) => {\n if (change !== 'enqueued') return\n if (queued) clearTimeout(queued)\n queued = setTimeout(run, 2_000)\n })\n let channel: BroadcastChannel | null = null\n try {\n channel = new BroadcastChannel(SYNC_CHANNEL)\n channel.onmessage = () => refreshCalendarQueries(queryClient)\n } catch {\n channel = null\n }\n return () => {\n channel?.close()\n offOnline()\n offOutbox()\n if (queued) clearTimeout(queued)\n }\n }, [ready, arbi, queryClient])\n}\n","/**\n * The AI engine — domain-agnostic hooks for building an AI-native app on ARBI.\n *\n * `useAiTask` runs a streaming, cited agentic query (tokens, agent steps and\n * artifacts accumulate live, with follow-up threading). `useWorkspaceDocs`\n * resolves a workspace's document ids to ground on (search lives in `../search`).\n * These wrap the low-level SDK hooks so a vertical app never re-implements the\n * streaming/accumulation plumbing.\n */\n\nimport { useCallback, useMemo, useRef, useState } from 'react'\nimport type { SSEStreamResult, ArtifactEvent } from '@arbidocs/sdk/browser'\nimport { useAssistantQuery } from '../hooks'\nimport { useDocuments } from '../documents/documents-data'\n\nexport type { ArtifactEvent }\n\n/**\n * Resolve a workspace's document set and their external ids. Pass the active\n * `workspaceId`; the kit stays agnostic about how selection is managed.\n */\nexport function useWorkspaceDocs(workspaceId?: string) {\n const { data: docs = [], isLoading, isError } = useDocuments(workspaceId)\n\n const docIds = useMemo(\n () =>\n docs.map((d: { external_id?: string }) => d.external_id).filter((id): id is string => !!id),\n [docs]\n )\n\n return { wsId: workspaceId, docs, docIds, isLoading, isError, ready: docIds.length > 0 }\n}\n\nexport type AiTaskStatus = 'idle' | 'running' | 'done' | 'error'\n\nexport interface AiRunOptions {\n /** Bind this turn to the open native Word document. */\n activeArtifactExtId?: string\n /** Continue a prior turn (follow-up questions in the same thread). */\n previousResponseId?: string | null\n model?: string\n}\n\n/**\n * Run a single streaming agentic task grounded in a set of documents.\n *\n * Returns live state (`text` accumulates tokens as they stream) plus a `run`\n * that resolves to the full {@link SSEStreamResult} — including the response id\n * needed to chain follow-ups.\n */\nexport function useAiTask() {\n const mutation = useAssistantQuery()\n const [status, setStatus] = useState<AiTaskStatus>('idle')\n const [text, setText] = useState('')\n const [stepCount, setStepCount] = useState(0)\n const [error, setError] = useState<string | null>(null)\n const [responseId, setResponseId] = useState<string | null>(null)\n const [artifacts, setArtifacts] = useState<ArtifactEvent[]>([])\n const bufferRef = useRef('')\n const artifactsRef = useRef<Map<string, ArtifactEvent>>(new Map())\n\n const reset = useCallback(() => {\n setStatus('idle')\n setText('')\n setStepCount(0)\n setError(null)\n setResponseId(null)\n setArtifacts([])\n artifactsRef.current = new Map()\n bufferRef.current = ''\n }, [])\n\n const run = useCallback(\n async (\n question: string,\n docIds: string[],\n opts?: AiRunOptions\n ): Promise<SSEStreamResult | null> => {\n setStatus('running')\n setText('')\n setStepCount(0)\n setError(null)\n setArtifacts([])\n artifactsRef.current = new Map()\n bufferRef.current = ''\n let streamError: string | null = null\n try {\n const result = await mutation.mutateAsync({\n request: {\n question,\n docIds,\n previousResponseId: opts?.previousResponseId ?? undefined,\n model: opts?.model,\n activeArtifactExtId: opts?.activeArtifactExtId,\n },\n handlers: {\n onToken: (c: string) => {\n bufferRef.current += c\n setText(bufferRef.current)\n },\n onOutputItemDone: (ev) => {\n const t = (ev.item as { type?: string }).type\n if (t === 'function_call' || t === 'reasoning') setStepCount((n) => n + 1)\n },\n onArtifact: (a: ArtifactEvent) => {\n // Artifacts are documents; keep the latest version per doc.\n artifactsRef.current.set(a.doc_ext_id, a)\n setArtifacts([...artifactsRef.current.values()])\n },\n onError: (e) => {\n // The server's report; a dropped connection rejects the ask instead.\n if (typeof e === 'string') streamError = e\n },\n },\n })\n const finalText = result.text || bufferRef.current\n setText(finalText)\n setResponseId(result.assistantMessageExtId)\n setStepCount(result.agentSteps.length || 0)\n if (result.artifacts?.length) {\n for (const a of result.artifacts) artifactsRef.current.set(a.doc_ext_id, a)\n setArtifacts([...artifactsRef.current.values()])\n }\n const err = streamError || result.errors[0] || null\n if (err && !finalText) {\n setError(err)\n setStatus('error')\n } else {\n setStatus('done')\n }\n return result\n } catch (e) {\n setError(e instanceof Error ? e.message : 'The assistant request failed.')\n setStatus('error')\n return null\n }\n },\n [mutation]\n )\n\n return {\n status,\n text,\n stepCount,\n error,\n responseId,\n artifacts,\n run,\n reset,\n isRunning: status === 'running',\n isDone: status === 'done',\n }\n}\n","/**\n * Client-side redlining — turn an original + revised text into track-changes\n * markdown (`<del>` strikethrough deletions, `<ins>` insertions). Rendered by\n * {@link AiMarkdown} (via rehype-raw) and the {@link ArtifactCanvas}.\n */\nimport { diffWords } from 'diff'\nimport type { ArtifactEvent } from '@arbidocs/sdk/browser'\n\n/** Produce inline `<del>/<ins>` redline markdown from two document versions. */\nexport function toRedlineMarkdown(original: string, revised: string): string {\n const parts = diffWords(original ?? '', revised ?? '')\n return parts\n .map((p) => {\n if (p.added) return `<ins>${p.value}</ins>`\n if (p.removed) return `<del>${p.value}</del>`\n return p.value\n })\n .join('')\n}\n\n/** Count added/removed words between two versions (for a redline summary). */\nexport function redlineStats(original: string, revised: string) {\n let added = 0\n let removed = 0\n for (const p of diffWords(original ?? '', revised ?? '')) {\n const words = p.value.trim() ? p.value.trim().split(/\\s+/).length : 0\n if (p.added) added += words\n else if (p.removed) removed += words\n }\n return { added, removed }\n}\n\n/** Wrap arbitrary text/markdown as a synthetic artifact for the canvas. */\nexport function textToArtifact(\n title: string,\n content: string,\n opts?: { mode?: ArtifactEvent['mode']; isComplete?: boolean; version?: number; id?: string }\n): ArtifactEvent {\n return {\n type: 'arbi.artifact',\n doc_ext_id: opts?.id ?? `local-${title.replace(/\\W+/g, '-').toLowerCase()}`,\n title,\n mode: opts?.mode ?? 'markdown',\n content,\n // Content-backed (markdown/text/html) artifacts carry no blob; file_type is\n // required on ArtifactEvent and defaults to \"\" for non-image artifacts.\n file_type: '',\n is_complete: opts?.isComplete ?? true,\n version: opts?.version ?? 1,\n message_ext_id: null,\n t: null,\n }\n}\n","import { useState } from 'react'\nimport { Sparkles, Loader2, AlertTriangle, Copy, Check, ShieldCheck } from 'lucide-react'\nimport { cn } from '../lib/utils'\nimport type { AiTaskStatus } from './engine'\nimport { AiMarkdown } from './AiMarkdown'\n\n/**\n * Renders the live state of a single agentic task: streaming tokens, a \"thinking\"\n * indicator with the running step count, errors, and a grounded/cited footer with\n * copy-to-clipboard. Shared by every AI feature so streaming looks identical\n * everywhere. Copy is customisable via `groundedNote` / `runningHint`.\n */\nexport function AiAnswer({\n status,\n text,\n stepCount,\n error,\n className,\n emptyHint,\n groundedNote = 'Grounded in the live workspace · verify citations before relying on it',\n runningHint = 'Reading the documents…',\n testId = 'ai-answer',\n}: {\n status: AiTaskStatus\n text: string\n stepCount?: number\n error?: string | null\n className?: string\n emptyHint?: string\n groundedNote?: string\n runningHint?: string\n testId?: string\n}) {\n const [copied, setCopied] = useState(false)\n const running = status === 'running'\n const hasText = text.trim().length > 0\n\n const copy = async () => {\n await navigator.clipboard.writeText(text)\n setCopied(true)\n setTimeout(() => setCopied(false), 1600)\n }\n\n if (status === 'idle' && !hasText) {\n return emptyHint ? (\n <p className={cn('text-sm text-muted-foreground', className)} data-testid={`${testId}-empty`}>\n {emptyHint}\n </p>\n ) : null\n }\n\n return (\n <div className={cn('space-y-3', className)} data-testid={testId} data-status={status}>\n {running && (\n <div\n className=\"flex items-center gap-2 text-xs font-medium text-ai-accent\"\n data-testid={`${testId}-thinking`}\n >\n <Loader2 className=\"size-3.5 animate-spin\" />\n {stepCount && stepCount > 0\n ? `Working — ${stepCount} step${stepCount === 1 ? '' : 's'}…`\n : 'Thinking…'}\n </div>\n )}\n\n {status === 'error' && !hasText && (\n <div\n className=\"flex items-start gap-2 rounded-lg border border-destructive/30 bg-destructive/5 p-3 text-sm text-destructive\"\n data-testid={`${testId}-error`}\n >\n <AlertTriangle className=\"mt-0.5 size-4 shrink-0\" />\n <span>{error ?? 'The assistant request failed.'}</span>\n </div>\n )}\n\n {hasText && (\n <>\n <AiMarkdown isStreaming={running}>{text}</AiMarkdown>\n {!running && (\n <div className=\"flex items-center justify-between border-t border-border pt-2.5\">\n <span className=\"inline-flex items-center gap-1.5 text-xs text-muted-foreground\">\n <ShieldCheck className=\"size-3.5 text-ai-accent\" />\n {groundedNote}\n </span>\n <button\n type=\"button\"\n onClick={copy}\n className=\"inline-flex items-center gap-1 text-xs font-medium text-muted-foreground hover:text-foreground\"\n data-testid={`${testId}-copy`}\n >\n {copied ? (\n <Check className=\"size-3.5 text-ai-accent\" />\n ) : (\n <Copy className=\"size-3.5\" />\n )}\n {copied ? 'Copied' : 'Copy'}\n </button>\n </div>\n )}\n </>\n )}\n\n {running && !hasText && (\n <div className=\"flex items-center gap-1.5 text-sm text-muted-foreground\">\n <Sparkles className=\"size-4 animate-pulse text-ai-accent\" /> {runningHint}\n </div>\n )}\n </div>\n )\n}\n","import { useEffect, useState } from 'react'\nimport {\n FileText,\n Download,\n Copy,\n Check,\n Loader2,\n GitCompareArrows,\n AlertTriangle,\n} from 'lucide-react'\nimport { motion, AnimatePresence } from 'framer-motion'\nimport { Badge } from '../ui/badge'\nimport { cn } from '../lib/utils'\nimport type { ArtifactEvent } from './engine'\nimport { AiMarkdown } from './AiMarkdown'\n\n/**\n * The artifacts canvas — renders agent-produced documents (drafts, redlines,\n * memos) as first-class artifacts in a paper-styled panel. Markdown mode supports\n * redlines (`<del>` deletions / `<ins>` additions). Streams live: content grows\n * and `is_complete` flips when finished. Token-neutral: the \"paper\" surface is\n * the kit's `ai-surface` colour.\n */\nexport function ArtifactCanvas({\n artifacts,\n className,\n emptyHint = 'Draft artifacts produced by the agent will open here.',\n busy = false,\n busyHint = 'The agent is working through the documents…',\n stepCount,\n error = null,\n}: {\n artifacts: ArtifactEvent[]\n className?: string\n emptyHint?: string\n /** A run failed before producing content — show it instead of the empty hint. */\n error?: string | null\n /**\n * The agent is running but hasn't produced streamable content yet. Agentic\n * drafts spend a while planning/retrieving before the first token, so show a\n * live working state instead of the empty hint — otherwise the canvas reads\n * as broken during a perfectly normal multi-step run.\n */\n busy?: boolean\n busyHint?: string\n /** Agent steps completed so far, surfaced in the working state when > 0. */\n stepCount?: number\n}) {\n const [activeId, setActiveId] = useState<string | null>(null)\n const [copied, setCopied] = useState(false)\n\n // Follow the most recent artifact as they stream in.\n useEffect(() => {\n if (artifacts.length && (!activeId || !artifacts.some((a) => a.doc_ext_id === activeId))) {\n setActiveId(artifacts[artifacts.length - 1].doc_ext_id)\n }\n }, [artifacts, activeId])\n\n if (artifacts.length === 0) {\n // A failed run with no partial content — surface the error, not a dead hint.\n if (error && !busy) {\n return (\n <div\n className={cn(\n 'flex h-full min-h-[280px] flex-col items-center justify-center rounded-xl border border-destructive/30 bg-destructive/5 p-8 text-center',\n className\n )}\n data-testid=\"artifact-canvas-error\"\n >\n <AlertTriangle className=\"size-8 text-destructive/70\" />\n <p className=\"mt-3 max-w-md text-sm text-foreground\">{error}</p>\n </div>\n )\n }\n // Running-but-empty: the agent is planning/retrieving before it streams.\n if (busy) {\n return (\n <div\n className={cn(\n 'flex h-full min-h-[280px] flex-col items-center justify-center rounded-xl border border-border bg-ai-surface/40 p-8 text-center',\n className\n )}\n data-testid=\"artifact-canvas-busy\"\n >\n <Loader2 className=\"size-8 animate-spin text-ai-accent\" />\n <p className=\"mt-4 max-w-xs text-sm font-medium text-foreground\">{busyHint}</p>\n {typeof stepCount === 'number' && stepCount > 0 && (\n <p className=\"mt-1 text-xs text-muted-foreground\" data-testid=\"artifact-canvas-steps\">\n {stepCount} {stepCount === 1 ? 'step' : 'steps'} so far\n </p>\n )}\n </div>\n )\n }\n return (\n <div\n className={cn(\n 'flex h-full min-h-[280px] flex-col items-center justify-center rounded-xl border border-dashed border-border bg-secondary/30 p-8 text-center',\n className\n )}\n data-testid=\"artifact-canvas-empty\"\n >\n <FileText className=\"size-8 text-muted-foreground/50\" />\n <p className=\"mt-3 max-w-xs text-sm text-muted-foreground\">{emptyHint}</p>\n </div>\n )\n }\n\n const active = artifacts.find((a) => a.doc_ext_id === activeId) ?? artifacts[artifacts.length - 1]\n const isRedline = /~~|<ins|<del|<mark/i.test(active.content)\n\n const copy = async () => {\n await navigator.clipboard.writeText(active.content)\n setCopied(true)\n setTimeout(() => setCopied(false), 1600)\n }\n\n const download = () => {\n const ext = active.mode === 'html' ? 'html' : active.mode === 'text' ? 'txt' : 'md'\n const blob = new Blob([active.content], { type: 'text/plain' })\n const url = URL.createObjectURL(blob)\n const a = document.createElement('a')\n a.href = url\n a.download = `${active.title.replace(/[^\\w.-]+/g, '_') || 'artifact'}.${ext}`\n a.click()\n URL.revokeObjectURL(url)\n }\n\n return (\n <div\n className={cn(\n 'flex h-full flex-col overflow-hidden rounded-xl border border-border bg-card',\n className\n )}\n data-testid=\"artifact-canvas\"\n >\n {/* Header */}\n <div className=\"flex items-center gap-2 border-b border-border bg-secondary/40 px-4 py-2.5\">\n <FileText className=\"size-4 shrink-0 text-ai-accent\" />\n <span\n className=\"min-w-0 flex-1 truncate text-sm font-medium text-foreground\"\n data-testid=\"artifact-title\"\n >\n {active.title}\n </span>\n {isRedline && (\n <Badge variant=\"accent\" className=\"gap-1\">\n <GitCompareArrows className=\"size-3\" /> Redline\n </Badge>\n )}\n <Badge variant=\"secondary\">v{active.version}</Badge>\n {!active.is_complete ? (\n <span\n className=\"inline-flex items-center gap-1 text-xs text-ai-accent\"\n data-testid=\"artifact-streaming\"\n >\n <Loader2 className=\"size-3 animate-spin\" /> drafting\n </span>\n ) : (\n <div className=\"flex items-center gap-1\">\n <button\n onClick={copy}\n className=\"rounded p-1 text-muted-foreground hover:bg-accent hover:text-foreground\"\n title=\"Copy\"\n data-testid=\"artifact-copy\"\n >\n {copied ? (\n <Check className=\"size-3.5 text-ai-accent\" />\n ) : (\n <Copy className=\"size-3.5\" />\n )}\n </button>\n <button\n onClick={download}\n className=\"rounded p-1 text-muted-foreground hover:bg-accent hover:text-foreground\"\n title=\"Download\"\n data-testid=\"artifact-download\"\n >\n <Download className=\"size-3.5\" />\n </button>\n </div>\n )}\n </div>\n\n {/* Tabs when multiple artifacts */}\n {artifacts.length > 1 && (\n <div className=\"flex gap-1 overflow-x-auto border-b border-border bg-card px-2 py-1.5\">\n {artifacts.map((a) => (\n <button\n key={a.doc_ext_id}\n onClick={() => setActiveId(a.doc_ext_id)}\n className={cn(\n 'shrink-0 rounded-md px-2.5 py-1 text-xs font-medium',\n a.doc_ext_id === active.doc_ext_id\n ? 'bg-ai-accent-soft text-ai-accent'\n : 'text-muted-foreground hover:bg-accent'\n )}\n >\n {a.title.slice(0, 28)}\n </button>\n ))}\n </div>\n )}\n\n {/* Paper body */}\n <div className=\"flex-1 overflow-y-auto bg-ai-surface/40 p-6\">\n <AnimatePresence mode=\"wait\">\n <motion.div\n key={active.doc_ext_id}\n initial={{ opacity: 0, y: 6 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ duration: 0.2 }}\n className=\"mx-auto max-w-2xl rounded-lg bg-card p-8 shadow-sm ring-1 ring-border\"\n >\n {active.mode === 'html' ? (\n <div className=\"text-sm\" dangerouslySetInnerHTML={{ __html: active.content }} />\n ) : active.mode === 'text' ? (\n <pre className=\"whitespace-pre-wrap font-mono text-xs text-foreground\">\n {active.content}\n </pre>\n ) : (\n <AiMarkdown>{active.content}</AiMarkdown>\n )}\n </motion.div>\n </AnimatePresence>\n </div>\n </div>\n )\n}\n","import React from 'react'\nimport { AppWindow, FileText, Image as ImageIcon } from 'lucide-react'\nimport { Card } from '../ui/card'\n\n/**\n * The minimal artifact shape this card renders. A structural subset of the\n * ARBI app's `StreamingDocument`, defined here so the light package doesn't\n * depend on the app store — any object carrying these fields is accepted.\n */\nexport interface MessageArtifact {\n /** External id of the drafted document; opened in the docked viewer. */\n docExtId: string\n /** Display title; falls back when empty. */\n title: string\n /** Whether generation has finished. */\n isComplete: boolean\n /**\n * Content mode. `markdown` / `text` are document drafts, which the server stores as Word\n * documents (.docx); `html` / `react` are live UI artifacts; `image` is a generated image.\n */\n mode: 'markdown' | 'html' | 'text' | 'react' | 'image'\n}\n\nconst LABELS = {\n document: {\n Icon: FileText,\n busy: 'Drafting…',\n ready: 'Draft ready',\n action: 'Open in Editor',\n untitled: 'Untitled draft',\n },\n live: {\n Icon: AppWindow,\n busy: 'Building…',\n ready: 'Preview ready',\n action: 'Open preview',\n untitled: 'Untitled app',\n },\n image: {\n Icon: ImageIcon,\n busy: 'Generating…',\n ready: 'Image ready',\n action: 'View image',\n untitled: 'Generated image',\n },\n} as const\n\nfunction labelsFor(mode: MessageArtifact['mode']) {\n if (mode === 'image') return LABELS.image\n if (mode === 'html' || mode === 'react') return LABELS.live\n return LABELS.document\n}\n\ninterface MessageArtifactCardProps {\n /** The streaming/drafted document linked to this assistant message. */\n artifact: MessageArtifact\n /** Opens the drafted document (docExtId) in the docked viewer. */\n onOpen: (docExtId: string) => void\n}\n\n/**\n * Inline \"Open in Editor\" (document drafts) / \"Open preview\" / \"View image\" affordance shown inside the assistant message that\n * produced a drafted document — so the artifact lives in the conversation\n * narrative (dyad-style) instead of only a hidden docked panel.\n *\n * Clean-ARBI contract: flat outline card, one chat type size, brand\n * accent on the action, tap-friendly (a real button — no hover-only).\n */\nexport function MessageArtifactCard({\n artifact,\n onOpen,\n}: MessageArtifactCardProps): React.JSX.Element {\n const { docExtId, title, isComplete, mode } = artifact\n const labels = labelsFor(mode)\n const Icon = labels.Icon\n return (\n <Card\n variant=\"outline\"\n className=\"mt-3 flex items-center gap-3 px-3 py-2.5\"\n data-testid={`message-artifact-card-${docExtId}`}\n >\n <Icon className=\"h-4 w-4 shrink-0 text-muted-foreground\" aria-hidden />\n <div className=\"min-w-0 flex-1\">\n <div\n className=\"truncate text-chat font-semibold text-foreground\"\n data-testid=\"artifact-title\"\n >\n {title || labels.untitled}\n </div>\n <div className=\"text-sm text-muted-foreground\" data-testid=\"artifact-status\">\n {isComplete ? labels.ready : labels.busy}\n </div>\n </div>\n <button\n type=\"button\"\n onClick={() => onOpen(docExtId)}\n className=\"shrink-0 rounded-md bg-secondary/15 px-3 py-1.5 text-sm font-semibold text-secondary transition-colors hover:bg-secondary/25\"\n data-testid={`view-artifact-button-${docExtId}`}\n >\n {labels.action}\n </button>\n </Card>\n )\n}\n","import React, { useMemo, useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\nimport ReactMarkdown, { Components } from 'react-markdown'\nimport type { components } from '@arbidocs/client'\nimport { MarkMenu, returnFocusToMark, type MarkMenuItem } from '../ui/mark-menu'\nimport { cn } from '../lib/utils'\nimport { normalizeCitationMarkup } from './normalize-citations'\n\n/**\n * Presentational core of the ARBI citation renderer — promoted from the monolith\n * as the callback-injection reference for the AI family. It owns all the hard-won\n * citation behaviour (numbering, per-doc grouping, hover/active highlighting,\n * click/open flows, emphasis-safe markdown parsing) but knows NOTHING about the\n * app's store, router or React Query. Every app coupling is injected:\n *\n * - `renderMarkdown` — the app's `MarkdownRenderer` (KaTeX / Mermaid / doc-entity\n * pills all stay app-side; the core just hands it the citation `a` override).\n * - `ExternalLink` — the app's confirm-before-open external-link component.\n * - `onOpenCitation` / `onActivateChunk` — replace the two store writes that used\n * to fire when a citation opens / a chunk card is clicked.\n * - `useCitationState` — an injected hook the popover calls to read the reactive\n * active-citation / viewing-passage / active-page state (kept as a hook so the\n * subscription stays local to each popover, exactly as before — the top-level\n * renderer never re-renders on citation state changes, so the markdown is never\n * re-parsed mid-interaction).\n * - `onCloseCitation` / `onDismissCitation` — the two distinct close flows.\n */\n\n// Renders markdown inline (no block wrappers) for single-line truncated display\nconst INLINE_MD_COMPONENTS = {\n p: ({ children }: { children?: React.ReactNode }) => <>{children}</>,\n strong: ({ children }: { children?: React.ReactNode }) => (\n <strong className=\"font-semibold\">{children}</strong>\n ),\n em: ({ children }: { children?: React.ReactNode }) => <em>{children}</em>,\n code: ({ children }: { children?: React.ReactNode }) => (\n <code className=\"font-mono\">{children}</code>\n ),\n a: ({ children }: { children?: React.ReactNode }) => <>{children}</>,\n ul: ({ children }: { children?: React.ReactNode }) => <>{children}</>,\n ol: ({ children }: { children?: React.ReactNode }) => <>{children}</>,\n li: ({ children }: { children?: React.ReactNode }) => <span>{children} </span>,\n h1: ({ children }: { children?: React.ReactNode }) => <>{children}</>,\n h2: ({ children }: { children?: React.ReactNode }) => <>{children}</>,\n h3: ({ children }: { children?: React.ReactNode }) => <>{children}</>,\n h4: ({ children }: { children?: React.ReactNode }) => <>{children}</>,\n h5: ({ children }: { children?: React.ReactNode }) => <>{children}</>,\n h6: ({ children }: { children?: React.ReactNode }) => <>{children}</>,\n blockquote: ({ children }: { children?: React.ReactNode }) => <>{children}</>,\n pre: ({ children }: { children?: React.ReactNode }) => <>{children}</>,\n}\n\n// Structural citation types, sourced from the canonical OpenAPI schema so the\n// core stays in lockstep with the app's `Chunk` / `ToolResponses` shapes.\nexport type Chunk = components['schemas']['Chunk']\nexport interface ToolResponses {\n [docId: string]: Chunk[]\n}\n\n/** Reactive citation state the popover reads (injected as a hook by the app). */\nexport interface CitationState {\n activeCitationKey: string | null\n viewingPassageId: string | null\n isOnConversationPage: boolean\n}\n\n/** Payload handed to the app when a chunk card is clicked / a citation opens. */\nexport interface ChunkActivation {\n messageId: string\n citationNum: string\n chunkIds: string[]\n chunk: Chunk\n citationData?: ToolResponses\n}\n\n/** Renders the citation content as markdown — the app supplies its MarkdownRenderer. */\nexport type RenderMarkdown = (args: {\n components: Partial<Components>\n isStreaming: boolean\n children: string\n}) => React.ReactNode\n\nexport interface CitationRendererProps {\n content: string\n citations?: Record<string, string[]>\n citationData?: ToolResponses\n className?: string\n messageId: string\n isStreaming?: boolean\n // ── injected app bindings ──────────────────────────────────────────────────\n renderMarkdown: RenderMarkdown\n ExternalLink: React.ComponentType<React.ComponentPropsWithoutRef<'a'>>\n onOpenCitation: (citationKey: string) => void\n onActivateChunk: (activation: ChunkActivation) => void\n useCitationState: () => CitationState\n onCloseCitation: () => void\n onDismissCitation: () => void\n /** Tells the user a citation was copied (or could not be). Optional: copying is silent without it. */\n notify?: (message: string, kind?: 'success' | 'error' | 'info') => void\n /** Display names keyed by doc_ext_id. A chunk's `doc_title` is the raw upload name, which can\n * differ from the name the workspace shows; when a name is given here it is used instead. */\n docTitles?: ReadonlyMap<string, string>\n}\n\nconst CitationRendererComponent: React.FC<CitationRendererProps> = ({\n content,\n citations,\n citationData,\n className,\n messageId,\n isStreaming = false,\n renderMarkdown,\n ExternalLink,\n onOpenCitation,\n onActivateChunk,\n useCitationState,\n onCloseCitation,\n onDismissCitation,\n notify,\n docTitles,\n}) => {\n const chunkMap = useMemo(() => {\n const map = new Map<string, Chunk>()\n if (citationData) {\n Object.entries(citationData as ToolResponses).forEach(([, docChunks]) => {\n if (docChunks && Array.isArray(docChunks)) {\n docChunks.forEach((chunk: Chunk) => {\n if (chunk.metadata && chunk.metadata.chunk_ext_id) {\n const displayTitle = chunk.metadata.doc_ext_id\n ? docTitles?.get(chunk.metadata.doc_ext_id)\n : undefined\n map.set(\n chunk.metadata.chunk_ext_id,\n displayTitle\n ? { ...chunk, metadata: { ...chunk.metadata, doc_title: displayTitle } }\n : chunk\n )\n }\n })\n }\n })\n }\n return map\n }, [citationData, docTitles])\n\n const getChunkDetails = useCallback(\n (chunkIds: string[]): Chunk[] =>\n [...new Set(chunkIds)]\n .map((id) => chunkMap.get(id))\n .filter((c): c is Chunk => c !== undefined),\n [chunkMap]\n )\n\n const handleChunkClick = useCallback(\n (citationNum: string, chunkIds: string[], chunk: Chunk) => {\n onActivateChunk({ messageId, citationNum, chunkIds, chunk, citationData })\n },\n [messageId, citationData, onActivateChunk]\n )\n\n // What the citation links read. It reaches them through context, not through the markdown\n // components, so the components keep one identity and a new copy of the answer (a refetch, a\n // cache write, new document titles) re-renders the citations instead of remounting them: a\n // remount drops the mark an open citation dialog returns focus to.\n const anchorContext = useMemo<CitationAnchorContextValue>(\n () => ({\n citations,\n messageId,\n isStreaming,\n getChunkDetails,\n handleChunkClick,\n onOpenCitation,\n ExternalLink,\n useCitationState,\n onCloseCitation,\n onDismissCitation,\n notify,\n }),\n [\n citations,\n messageId,\n isStreaming,\n getChunkDetails,\n handleChunkClick,\n onOpenCitation,\n ExternalLink,\n useCitationState,\n onCloseCitation,\n onDismissCitation,\n notify,\n ]\n )\n\n // Citation markers `[text](#cite-N)` are already valid markdown link syntax.\n // We let react-markdown parse them natively (the `a` override above keys on the\n // `#cite-` href) instead of pre-converting to raw HTML — so emphasis inside the\n // cited text (**bold**, *italic*, `code`) and literal `*`/`_` characters survive\n // intact, and link boundaries can never split an emphasis span.\n return (\n <CitationAnchorContext.Provider value={anchorContext}>\n <div className={cn('citation-container', className)} data-testid=\"citation-renderer\">\n {renderMarkdown({\n components: CITATION_MARKDOWN_COMPONENTS,\n isStreaming,\n children: normalizeCitationMarkup(content),\n })}\n </div>\n </CitationAnchorContext.Provider>\n )\n}\n\n// ── CitationAnchor ───────────────────────────────────────────────────────────\n\ninterface CitationAnchorContextValue {\n citations?: Record<string, string[]>\n messageId: string\n isStreaming: boolean\n getChunkDetails: (chunkIds: string[]) => Chunk[]\n handleChunkClick: (citationNum: string, chunkIds: string[], chunk: Chunk) => void\n onOpenCitation: (citationKey: string) => void\n ExternalLink: React.ComponentType<React.ComponentPropsWithoutRef<'a'>>\n useCitationState: () => CitationState\n onCloseCitation: () => void\n onDismissCitation: () => void\n notify?: CitationRendererProps['notify']\n}\n\nconst CitationAnchorContext = React.createContext<CitationAnchorContextValue | null>(null)\n\n/** Every link in an answer: `#cite-N` is a citation, anything else a plain or external link. */\nfunction CitationAnchor({\n href,\n children,\n ...rest\n}: React.ComponentPropsWithoutRef<'a'> & { node?: unknown }) {\n // react-markdown's syntax-tree node is not a DOM attribute.\n const { node, ...props } = rest\n void node\n const ctx = React.useContext(CitationAnchorContext)\n if (!ctx || !href?.startsWith('#cite-')) {\n if (!ctx || !href || href.startsWith('#')) {\n return (\n <a className=\"text-primary underline underline-offset-2\" href={href} {...props}>\n {children}\n </a>\n )\n }\n const { ExternalLink } = ctx\n return (\n <ExternalLink href={href} {...props}>\n {children}\n </ExternalLink>\n )\n }\n\n const citationNum = href.slice(6)\n const { messageId, citations, getChunkDetails, handleChunkClick, onOpenCitation } = ctx\n const citationKey = `${messageId}-${citationNum}`\n const chunkIds = citations?.[citationNum] || []\n const chunks = getChunkDetails(chunkIds)\n\n return (\n <CitationPopover\n key={citationKey}\n citationNum={citationNum}\n messageId={messageId}\n chunks={chunks}\n isStreaming={ctx.isStreaming}\n onOpen={() => onOpenCitation(citationKey)}\n onChunkClick={(chunk) => handleChunkClick(citationNum, chunkIds, chunk)}\n useCitationState={ctx.useCitationState}\n onCloseCitation={ctx.onCloseCitation}\n onDismissCitation={ctx.onDismissCitation}\n notify={ctx.notify}\n >\n {children}\n </CitationPopover>\n )\n}\n\n/** One identity for the life of the module: see `anchorContext`. */\nconst CITATION_MARKDOWN_COMPONENTS: Partial<Components> = { a: CitationAnchor }\n\n// ── CitationPopover ──────────────────────────────────────────────────────────\n\n/** Space between the docked popover and the composer below it (and the screen top above it). */\nconst DOCK_GAP_PX = 8\n\ninterface CitationPopoverProps {\n citationNum: string\n messageId: string\n chunks: Chunk[]\n isStreaming: boolean\n onOpen: () => void\n onChunkClick: (chunk: Chunk) => void\n useCitationState: () => CitationState\n onCloseCitation: () => void\n onDismissCitation: () => void\n notify?: CitationRendererProps['notify']\n children: React.ReactNode\n}\n\nconst CitationPopover: React.FC<CitationPopoverProps> = ({\n citationNum,\n messageId,\n chunks,\n isStreaming,\n onOpen,\n onChunkClick,\n useCitationState,\n onCloseCitation,\n onDismissCitation,\n notify,\n children,\n}) => {\n const { activeCitationKey, viewingPassageId, isOnConversationPage } = useCitationState()\n const isActive = activeCitationKey === `${messageId}-${citationNum}`\n // Gate on the app's navigation state, not useLocation(): in-app navigation\n // rewrites the hash via history.replaceState, which react-router never\n // observes, so its location stays frozen at the page-load value.\n const open = isActive && isOnConversationPage\n\n // The popover belongs to the conversation view. If the user leaves it (another page, or a\n // full-screen panel over it) while it is open, drop the active key so it neither floats over\n // the new view nor reappears when they come back.\n useEffect(() => {\n if (isActive && !isOnConversationPage) onDismissCitation()\n }, [isActive, isOnConversationPage, onDismissCitation])\n\n const triggerRef = useRef<HTMLElement>(null)\n const dialogRef = useRef<HTMLDivElement>(null)\n // Set when the user closes it (Escape / the X): focus then goes back to the citation they came\n // from. A close caused by something else (another citation, leaving the page) leaves focus alone.\n const restoreFocusRef = useRef(false)\n\n const dismiss = useCallback(() => {\n restoreFocusRef.current = true\n onDismissCitation()\n }, [onDismissCitation])\n\n // The popover is portalled to the end of <body>, so a keyboard or screen-reader user who\n // opened it would otherwise have to Tab through the whole page to reach it. Move focus into the\n // dialog on open (taps do not focus a span on iOS, so this is not gated on the trigger) and\n // return it to the citation when the user dismisses.\n useEffect(() => {\n if (!open) return\n dialogRef.current?.focus({ preventScroll: true })\n return () => {\n if (!restoreFocusRef.current) return\n restoreFocusRef.current = false\n if (triggerRef.current) returnFocusToMark(triggerRef.current)\n }\n }, [open])\n\n // Escape closes like the X: the popover goes, the passage stays in the viewer.\n useEffect(() => {\n if (!open) return\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') dismiss()\n }\n document.addEventListener('keydown', onKeyDown)\n return () => document.removeEventListener('keydown', onKeyDown)\n }, [open, dismiss])\n\n // The popover docks to the top edge of the composer (full chat width) instead of the cited\n // word, so it never covers the answer paragraph being cited. The edge is measured while it is\n // open, and again whenever the composer changes size: opening a citation also opens the document\n // viewer, which narrows the chat column after the first measurement.\n const [dock, setDock] = useState({ left: 0, top: 0, width: 0 })\n\n // Measured whenever it opens, however it was opened (click, keyboard, a source chip).\n useLayoutEffect(() => {\n if (!open) return\n // The composer is exactly the chat column (the main element also spans a docked viewer).\n const edge =\n document.querySelector('[data-testid=\"message-input-container\"]') ??\n document.querySelector('main[data-testid^=\"conversation-\"]') ??\n document.body\n const measure = () => {\n const rect = edge.getBoundingClientRect()\n setDock({ left: rect.left, top: rect.top, width: rect.width })\n }\n measure()\n const observer = new ResizeObserver(measure)\n observer.observe(edge)\n window.addEventListener('resize', measure)\n return () => {\n observer.disconnect()\n window.removeEventListener('resize', measure)\n }\n }, [open])\n\n const handleOpen = useCallback(() => {\n onOpen()\n if (chunks.length > 0) {\n onChunkClick(chunks[0])\n }\n }, [onOpen, onChunkClick, chunks])\n\n const byDoc = useMemo(() => {\n const map = new Map<string, { title: string; chunks: Chunk[] }>()\n chunks.forEach((chunk) => {\n const docId = chunk.metadata.doc_ext_id ?? 'unknown'\n const title = chunk.metadata.doc_title ?? docId\n if (!map.has(docId)) map.set(docId, { title, chunks: [] })\n map.get(docId)!.chunks.push(chunk)\n })\n return Array.from(map.entries()).map(([docId, val]) => ({ docId, ...val }))\n }, [chunks])\n\n const first = chunks[0]\n const firstText = first ? first.content.replace(/\\n+/g, ' ').trim() : ''\n const firstTitle = first ? (first.metadata.doc_title ?? first.metadata.doc_ext_id ?? '') : ''\n const firstPage = first?.metadata.page_number\n\n const copyCitation = useCallback(async () => {\n const source = [firstTitle, firstPage != null ? `p.${firstPage}` : null]\n .filter(Boolean)\n .join(', ')\n try {\n await navigator.clipboard.writeText(source ? `“${firstText}” (${source})` : firstText)\n notify?.('Citation copied', 'success')\n } catch {\n notify?.('Could not copy the citation', 'error')\n }\n }, [firstText, firstTitle, firstPage, notify])\n\n const items: MarkMenuItem[] =\n isStreaming || chunks.length === 0\n ? []\n : [\n {\n id: 'open',\n label: 'Open in viewer',\n primary: true,\n onSelect: handleOpen,\n testId: `citation-open-${citationNum}`,\n },\n {\n id: 'copy',\n label: 'Copy citation',\n onSelect: () => void copyCitation(),\n testId: `citation-copy-${citationNum}`,\n },\n ]\n\n // The cited passage itself: quoted text, its source and page, before anything is opened.\n const preview = first ? (\n <div className=\"max-w-xs\" data-testid={`citation-preview-${citationNum}`}>\n <span className=\"block text-xs font-medium text-foreground\">{firstTitle}</span>\n {firstPage != null && (\n <span className=\"block text-xs text-muted-foreground\">Page {firstPage}</span>\n )}\n <span className=\"mt-1 line-clamp-4 block text-sm text-foreground\">\n <ReactMarkdown components={INLINE_MD_COMPONENTS}>{firstText}</ReactMarkdown>\n </span>\n {chunks.length > 1 && (\n <span className=\"mt-1 block text-xs text-muted-foreground\">\n +{chunks.length - 1} more passage{chunks.length > 2 ? 's' : ''}\n </span>\n )}\n </div>\n ) : undefined\n\n return (\n <>\n <CitationLink\n triggerRef={triggerRef}\n citationNum={citationNum}\n isActive={isActive}\n isStreaming={isStreaming}\n items={items}\n preview={preview}\n >\n {children}\n </CitationLink>\n {open &&\n createPortal(\n <div\n className=\"pointer-events-none fixed z-[42] flex justify-center px-2\"\n style={{\n left: dock.left,\n width: dock.width,\n bottom: window.innerHeight - dock.top + DOCK_GAP_PX,\n }}\n >\n <div\n ref={dialogRef}\n role=\"dialog\"\n tabIndex={-1}\n aria-label={`Citation ${citationNum}`}\n // Never taller than the room above the composer (it sits 8px above it, and keeps 8px\n // from the top of the screen): on a landscape phone 45vh is more than that room, and\n // the header rose off the top of the screen.\n style={{ maxHeight: `min(45vh, ${Math.max(dock.top - 2 * DOCK_GAP_PX, 0)}px)` }}\n className=\"pointer-events-auto z-[42] outline-none w-[min(100%,48rem)] min-w-0 overflow-y-auto rounded-md border border-border bg-popover p-0 text-popover-foreground shadow-xl\"\n data-testid={`citation-popover-${citationNum}`}\n >\n <div className=\"px-3 py-2 pointer-coarse:py-0 border-b border-border sticky top-0 bg-popover z-10 flex items-center justify-between gap-2\">\n <span className=\"text-xs font-semibold text-muted-foreground tracking-wide\">\n Citation {citationNum} ({chunks.length} passage{chunks.length !== 1 ? 's' : ''})\n </span>\n <button\n onClick={dismiss}\n // A bare 12px glyph is a tiny target — easy to miss, so closing takes\n // several tries. Pad it out to a comfortable ~28px tap area (negative\n // margin keeps the icon where it sat, so the header layout is\n // unchanged) and give it a hover background so it reads as a button.\n className=\"-m-1.5 flex shrink-0 items-center justify-center rounded p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground pointer-coarse:m-0 pointer-coarse:size-11 pointer-coarse:p-0\"\n aria-label=\"Close\"\n data-testid={`citation-popover-close-${citationNum}`}\n >\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M1 1L11 11M11 1L1 11\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n />\n </svg>\n </button>\n </div>\n {byDoc.map(({ docId, title, chunks: docChunks }) => (\n <div key={docId} className=\"px-3 py-2 border-b border-border last:border-0\">\n <p className=\"text-sm font-semibold text-foreground mb-1 truncate\" title={title}>\n {title}\n </p>\n {docChunks.map((chunk) => {\n const isSelected = viewingPassageId === chunk.metadata.chunk_ext_id\n return (\n <button\n key={chunk.metadata.chunk_ext_id}\n data-testid={`citation-chunk-${chunk.metadata.chunk_ext_id}`}\n onClick={() => onChunkClick(chunk)}\n className={cn(\n 'w-full text-left text-sm rounded-md px-2 py-1.5 pointer-coarse:min-h-11 pointer-coarse:py-3 transition-colors flex items-start gap-2 mb-1 last:mb-0',\n isSelected\n ? 'bg-ai-soft text-foreground ring-1 ring-ai-accent/40'\n : 'text-muted-foreground hover:text-primary hover:bg-muted'\n )}\n >\n <span className=\"min-w-0 flex-1\">\n {chunk.metadata.page_number != null && (\n <span className=\"block text-xs text-muted-foreground\">\n Page {chunk.metadata.page_number}\n </span>\n )}\n <span className=\"line-clamp-3 italic\">\n <ReactMarkdown components={INLINE_MD_COMPONENTS}>\n {chunk.content.replace(/\\n+/g, ' ').trim()}\n </ReactMarkdown>\n </span>\n </span>\n </button>\n )\n })}\n </div>\n ))}\n </div>\n </div>,\n document.body\n )}\n </>\n )\n}\n\n// ── CitationLink ─────────────────────────────────────────────────────────────\n\ninterface CitationLinkProps {\n citationNum: string\n isActive: boolean\n isStreaming: boolean\n items: MarkMenuItem[]\n preview: React.ReactNode\n triggerRef: React.Ref<HTMLElement>\n children: React.ReactNode\n}\n\n/**\n * The cited words with a faint wash and a superscript number: quiet text, not a badge.\n * Its one menu (preview of the passage, Open in viewer, Copy citation) is the shared `MarkMenu`.\n */\nconst CitationLink: React.FC<CitationLinkProps> = ({\n citationNum,\n isActive,\n isStreaming,\n items,\n preview,\n triggerRef,\n children,\n}) => (\n <MarkMenu\n triggerRef={triggerRef}\n items={items}\n preview={isStreaming ? undefined : preview}\n menuLabel={`Citation ${citationNum}`}\n testId={`citation-link-${citationNum}`}\n tabIndex={isStreaming ? -1 : 0}\n data-mark-kind=\"citation\"\n className={cn(\n 'cited-text relative rounded-sm px-0.5 transition-colors',\n // 44px touch hit area without changing the text layout. `touch-hit` grows only up to\n // 44px (never past the mark's own width), so it doesn't reach over the neighbouring\n // citation: a fixed inset let citation 2's area cover citation 1, and a tap on [1]\n // opened [2].\n 'touch-hit',\n isStreaming ? 'cursor-default' : 'cursor-pointer',\n isActive ? 'bg-ai-soft text-foreground' : 'bg-ai-soft/30 hover:bg-ai-soft/70'\n )}\n >\n {children}\n {/* Readable floor: never below the text-xs token, bold, so the number is easy to spot.\n `top-0` cancels preflight's `sup { top: -0.5em }`, which would raise the number a second\n time and push it up into the line above (most visible in table cells). */}\n <sup className=\"ml-px top-0 align-super text-[max(0.8em,var(--text-xs))] font-bold leading-none tabular-nums text-ai-ink\">\n {citationNum}\n </sup>\n </MarkMenu>\n)\n\nexport const CitationRenderer = React.memo(CitationRendererComponent)\n","/**\n * Search documents for passages: retrieval only, no LLM answer. One implementation for every\n * search surface (the search page, the ⌘K palette, a compact doc search).\n */\nimport { useCallback, useEffect, useState, useSyncExternalStore } from 'react'\nimport { searchChunks, type SearchChunk } from '@arbidocs/sdk/browser'\nimport { useArbi } from '../useArbi'\nimport {\n clearSearchSession,\n createSearchSession,\n type SearchSession,\n type SearchSessionState,\n type SearchStatus,\n} from './session'\n\nexport type SearchMode = 'semantic' | 'keyword' | 'hybrid'\n\nexport interface SemanticSearchOptions {\n /** The assistant configuration the search runs with; default the server's. */\n model?: string\n /**\n * Where the search lives. Default: this component's own (gone when it unmounts). Pass\n * `sharedSearchSession` for a page whose results outlive it.\n */\n session?: SearchSession\n /**\n * The workspace searched (default: the current one). The request names it; a session holding\n * another workspace's search starts over.\n */\n workspaceId?: string | null\n}\n\nexport interface SemanticSearch {\n /** The query last searched. */\n query: string\n /** Its passages, best first. */\n results: SearchChunk[]\n /** A search has finished with results to show (they stay while the next one runs). */\n searched: boolean\n status: SearchStatus\n error: string | null\n isRunning: boolean\n /** Search; an empty query clears. */\n search: (query: string, mode?: SearchMode) => Promise<void>\n /** Back to nothing searched. */\n clear: () => void\n session: SearchSession\n}\n\nconst IDLE: Pick<SearchSessionState, 'query' | 'results' | 'searched' | 'status' | 'error'> = {\n query: '',\n results: [],\n searched: false,\n status: 'idle',\n error: null,\n}\n\n/**\n * Search `docIds` (none: the whole workspace) and return the matching passages. The reply is\n * ranked by the SDK's `searchChunks`; nothing is kept server-side.\n */\nexport function useSemanticSearch(\n docIds: string[] = [],\n options: SemanticSearchOptions = {}\n): SemanticSearch {\n const arbi = useArbi()\n const [ownSession] = useState(createSearchSession)\n const session = options.session ?? ownSession\n const { model, workspaceId } = options\n const state = useSyncExternalStore(session.subscribe, session.getState, session.getState)\n\n // Another workspace's search is not this one's: start over.\n const foreign = !!workspaceId && !!state.workspaceId && state.workspaceId !== workspaceId\n useEffect(() => {\n if (!workspaceId) return\n const current = session.getState().workspaceId\n if (current !== workspaceId) {\n if (current) clearSearchSession(workspaceId, session)\n else session.setState({ workspaceId })\n }\n }, [session, workspaceId])\n\n const search = useCallback(\n async (query: string, mode: SearchMode = 'hybrid') => {\n const trimmed = query.trim()\n if (!trimmed) {\n clearSearchSession(undefined, session)\n return\n }\n const run = session.getState().run + 1\n // The workspace searched, captured now: the request names it (opened for this session if it\n // is not the current one), so a switch while it runs cannot answer it from another workspace.\n const searched = workspaceId ?? session.getState().workspaceId ?? undefined\n session.setState((s) => ({\n query: trimmed,\n status: 'running',\n error: null,\n run,\n workspaceId: workspaceId ?? s.workspaceId,\n }))\n try {\n const result = await arbi.assistant.retrieve(trimmed, docIds, {\n searchMode: mode,\n store: false,\n ...(model ? { model } : {}),\n ...(searched ? { workspaceId: searched } : {}),\n })\n if (session.getState().run !== run) return\n session.setState({ results: searchChunks(result), searched: true, status: 'done' })\n } catch (error) {\n if (session.getState().run !== run) return\n session.setState({\n status: 'error',\n error: error instanceof Error ? error.message : 'Search failed',\n })\n }\n },\n [arbi, docIds, model, session, workspaceId]\n )\n\n const clear = useCallback(() => clearSearchSession(undefined, session), [session])\n\n const shown = foreign ? IDLE : state\n return {\n query: shown.query,\n results: shown.results,\n searched: shown.searched,\n status: shown.status,\n error: shown.error,\n isRunning: shown.status === 'running',\n search,\n clear,\n session,\n }\n}\n","/**\n * Apple Icon Component. Promoted from the ARBI app for SDK reuse.\n */\n\nimport React from 'react'\n\ninterface AppleIconProps {\n size?: number\n className?: string\n 'aria-label'?: string\n 'aria-hidden'?: boolean\n}\n\nexport const AppleIcon: React.FC<AppleIconProps> = ({\n size = 20,\n className = '',\n 'aria-label': ariaLabel,\n 'aria-hidden': ariaHidden = true,\n}) => {\n return (\n <svg\n className={className}\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n aria-label={ariaLabel}\n aria-hidden={ariaHidden}\n >\n <path d=\"M17.05 20.28c-.98.95-2.05.8-3.08.35-1.09-.46-2.09-.48-3.24 0-1.44.62-2.2.44-3.06-.35C2.79 15.25 3.51 7.59 9.05 7.31c1.35.07 2.29.74 3.08.8 1.18-.24 2.31-.93 3.57-.84 1.51.12 2.65.72 3.4 1.8-3.12 1.87-2.38 5.98.48 7.13-.57 1.5-1.31 2.99-2.54 4.09l.01-.01zM12.03 7.25c-.15-2.23 1.66-4.07 3.74-4.25.29 2.58-2.34 4.5-3.74 4.25z\" />\n </svg>\n )\n}\n","/**\n * GitHub Icon Component. Promoted from the ARBI app for SDK reuse.\n */\n\nimport React from 'react'\n\ninterface GitHubIconProps {\n size?: number\n className?: string\n 'aria-label'?: string\n 'aria-hidden'?: boolean\n}\n\nexport const GitHubIcon: React.FC<GitHubIconProps> = ({\n size = 20,\n className = '',\n 'aria-label': ariaLabel,\n 'aria-hidden': ariaHidden = true,\n}) => {\n return (\n <svg\n className={className}\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n aria-label={ariaLabel}\n aria-hidden={ariaHidden}\n >\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z\"\n />\n </svg>\n )\n}\n","/**\n * LinkedIn Icon Component. Promoted from the ARBI app for SDK reuse.\n */\n\nimport React from 'react'\n\ninterface LinkedInIconProps {\n size?: number\n className?: string\n 'aria-label'?: string\n 'aria-hidden'?: boolean\n}\n\nexport const LinkedInIcon: React.FC<LinkedInIconProps> = ({\n size = 20,\n className = '',\n 'aria-label': ariaLabel,\n 'aria-hidden': ariaHidden = true,\n}) => {\n return (\n <svg\n className={className}\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"#0A66C2\"\n aria-label={ariaLabel}\n aria-hidden={ariaHidden}\n >\n <path d=\"M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z\" />\n </svg>\n )\n}\n","/**\n * Notification-type presentation primitives — the brand-neutral icon, colour and\n * label maps for every `NotificationType`, plus the workspace-membership phrasing\n * helpers. Kept in their own module (not a component file) so both the monolith's\n * AG-Grid notification centre and lightweight consumers (e.g. clarum's activity\n * feed) share one source of truth for \"what does this notification type mean\",\n * and so component files stay fast-refresh friendly.\n *\n * Deliberately decoupled: no store, no app `@/` imports — just lucide icon\n * components + semantic Tailwind token class names. Callers render the icon\n * themselves (`<Icon className={iconClassName} />`).\n */\n\nimport {\n Activity,\n AtSign,\n FileText,\n Gauge,\n Gift,\n HardDrive,\n Info,\n MessageCircleMore,\n PartyPopper,\n PenLine,\n Reply,\n UserCheck,\n UserPlus,\n} from 'lucide-react'\nimport { getEntityIcon, type EntityIconComponent } from '../entities/registry'\n\n/** Icon component, its colour class, and a short human label for a notification type. */\nexport interface NotificationTypeMeta {\n Icon: EntityIconComponent\n /** Semantic Tailwind colour class for the glyph. */\n iconClassName: string\n /** Short category label (e.g. \"Added\", \"Usage 90%\"). */\n label: string\n}\n\n/**\n * Resolve the icon + colour + short label for a notification type.\n *\n * Workspace-membership events all share the workspace glyph — the specific role\n * lives in the Event sentence (see {@link getWorkspaceSentPhrase}), so the label\n * stays short (\"Added\", not \"Added as collaborator\"). Unknown types fall back to\n * an info glyph and the raw type string.\n */\nexport function getNotificationTypeMeta(type: string | null | undefined): NotificationTypeMeta {\n // Resolve the workspace glyph live (not at module load) so a deployment's\n // configureEntityRegistry() injection is always reflected, regardless of import order.\n const WorkspaceIcon = getEntityIcon('WORKSPACE') as EntityIconComponent\n switch (type) {\n case 'support_ticket_received':\n case 'support_ticket_reviewed':\n case 'support_ticket_resolved':\n return { Icon: MessageCircleMore, iconClassName: 'text-primary', label: 'Support' }\n case 'agent_input_requested':\n return { Icon: MessageCircleMore, iconClassName: 'text-primary', label: 'Input needed' }\n case 'workspaceuser_added_owner':\n case 'workspaceuser_added_collaborator':\n case 'workspaceuser_added_guest':\n return { Icon: WorkspaceIcon, iconClassName: 'text-primary', label: 'Added' }\n case 'workspaceuser_removed':\n return { Icon: WorkspaceIcon, iconClassName: 'text-primary', label: 'Removed' }\n case 'workspaceuser_updated_owner':\n case 'workspaceuser_updated_collaborator':\n case 'workspaceuser_updated_guest':\n return { Icon: WorkspaceIcon, iconClassName: 'text-primary', label: 'Role changed' }\n case 'docx_mention':\n case 'mention':\n return { Icon: AtSign, iconClassName: 'text-primary', label: 'Mention' }\n case 'file_shared':\n return { Icon: FileText, iconClassName: 'text-primary', label: 'Shared file' }\n case 'signature_requested':\n return { Icon: PenLine, iconClassName: 'text-primary', label: 'Signature' }\n case 'signature_completed':\n return { Icon: PenLine, iconClassName: 'text-green-600', label: 'Signed' }\n case 'signature_declined':\n return { Icon: PenLine, iconClassName: 'text-orange-500', label: 'Declined' }\n case 'thread_reply':\n return { Icon: Reply, iconClassName: 'text-primary', label: 'Reply' }\n case 'document_activity':\n return { Icon: FileText, iconClassName: 'text-primary', label: 'Document' }\n case 'contact_accepted':\n return { Icon: UserCheck, iconClassName: 'text-green-500', label: 'Invitation' }\n case 'deployment_user_invited':\n case 'deployment_user_registered':\n return { Icon: UserPlus, iconClassName: 'text-primary', label: 'Users' }\n case 'signup_reward':\n return { Icon: PartyPopper, iconClassName: 'text-green-600', label: 'Signup bonus' }\n case 'referral_reward':\n return { Icon: Gift, iconClassName: 'text-green-600', label: 'Reward earned' }\n case 'project_quota_warning':\n return { Icon: Gauge, iconClassName: 'text-orange-500', label: 'Usage warning' }\n case 'project_retention':\n return { Icon: Gauge, iconClassName: 'text-orange-500', label: 'Project retention' }\n case 'quota_threshold_50':\n return { Icon: Gauge, iconClassName: 'text-blue-500', label: 'Usage 50%' }\n case 'quota_threshold_90':\n return { Icon: Gauge, iconClassName: 'text-orange-500', label: 'Usage 90%' }\n case 'quota_threshold_100':\n return { Icon: Gauge, iconClassName: 'text-red-500', label: 'Usage limit' }\n case 'storage_quota_exceeded':\n return { Icon: HardDrive, iconClassName: 'text-red-500', label: 'Storage full' }\n case 'activity':\n // Durable to-self activity line — the specific event lives in `content`.\n // Callers that have the content should prefer describeActivity() for a\n // precise glyph/label; this is the type-only fallback.\n return { Icon: Activity, iconClassName: 'text-muted-foreground', label: 'Activity' }\n default:\n return { Icon: Info, iconClassName: 'text-blue-500', label: type || 'Notification' }\n }\n}\n\n/** Whether a notification type is a workspace-membership event. */\nexport function isWorkspaceNotificationType(type: string): boolean {\n return type.startsWith('workspaceuser_')\n}\n\n/**\n * Recipient-perspective action text (\"you received\"). Renders after the sender\n * pill: \"[sender] added you as collaborator\". The workspace renders in its own\n * column, so there's no trailing preposition.\n */\nexport function getWorkspaceActionText(type: string): string {\n switch (type) {\n case 'workspaceuser_added_owner':\n return 'added you as owner'\n case 'workspaceuser_added_collaborator':\n return 'added you as collaborator'\n case 'workspaceuser_added_guest':\n return 'added you as read only'\n case 'workspaceuser_removed':\n return 'removed you'\n case 'workspaceuser_updated_owner':\n return 'changed your role to owner'\n case 'workspaceuser_updated_collaborator':\n return 'changed your role to collaborator'\n case 'workspaceuser_updated_guest':\n return 'changed your role to read only'\n default:\n return 'updated your access'\n }\n}\n\n/**\n * Sender-perspective phrasing (\"you did this\"). Renders around the affected\n * member pill — `{before} [member] {after}` — so it reads as an active sentence:\n * \"You added [Jane] as collaborator\" rather than the ambiguous \"Added as\n * collaborator: Jane\".\n */\nexport function getWorkspaceSentPhrase(type: string): { before: string; after: string } {\n switch (type) {\n case 'workspaceuser_added_owner':\n return { before: 'You added', after: 'as owner' }\n case 'workspaceuser_added_collaborator':\n return { before: 'You added', after: 'as collaborator' }\n case 'workspaceuser_added_guest':\n return { before: 'You added', after: 'as read only' }\n case 'workspaceuser_removed':\n return { before: 'You removed', after: '' }\n case 'workspaceuser_updated_owner':\n return { before: 'You set', after: 'as owner' }\n case 'workspaceuser_updated_collaborator':\n return { before: 'You set', after: 'as collaborator' }\n case 'workspaceuser_updated_guest':\n return { before: 'You set', after: 'as read only' }\n default:\n return { before: 'You updated access for', after: '' }\n }\n}\n","/**\n * Activity-event presentation — decodes the compact `{\"event\": ..., ...fields}`\n * JSON payload carried by durable `activity` notifications (recorded backend-side\n * by `log_activity`) into a glyph + human sentence.\n *\n * Distinct from `notification-types.ts`: that maps the notification *type* (a DM,\n * a workspace-membership change, a reward); this maps the *event* recorded on a\n * to-self activity line (\"opened a workspace\", \"processed a document\"). Entity\n * glyphs are sourced from the shared entity registry — one source of truth.\n */\n\nimport {\n Activity,\n FileCheck2,\n FileX2,\n FolderPlus,\n Pencil,\n SquareArrowOutUpRight,\n Trash2,\n} from 'lucide-react'\nimport { getEntityIcon, type EntityIconComponent } from '../entities/registry'\n\n/** Parsed activity payload — always has `event`, plus event-specific fields. */\nexport interface ActivityContent {\n event: string\n [field: string]: unknown\n}\n\n/** Rendered description of an activity line. */\nexport interface ActivityDescription {\n Icon: EntityIconComponent\n /** Semantic Tailwind colour class for the glyph. */\n iconClassName: string\n /** Human-readable one-line summary of what happened. */\n title: string\n}\n\n/** Parse an activity notification's `content` JSON into `{event, ...fields}`, or null. */\nexport function parseActivityContent(content: string | null | undefined): ActivityContent | null {\n if (!content) return null\n try {\n const parsed = JSON.parse(content)\n if (parsed && typeof parsed === 'object' && typeof parsed.event === 'string') {\n return parsed as ActivityContent\n }\n } catch {\n // Not JSON (e.g. a legacy plain-string activity line) — no structured event.\n }\n return null\n}\n\nfunction str(v: unknown): string | undefined {\n return typeof v === 'string' && v ? v : undefined\n}\n\n/**\n * Describe an activity line for display. Accepts either the raw `content` string\n * or an already-parsed {@link ActivityContent}. Unknown/unparseable events fall\n * back to a generic activity glyph and a humanised event name.\n */\nexport function describeActivity(\n content: string | ActivityContent | null | undefined\n): ActivityDescription {\n const parsed =\n typeof content === 'string' || content == null ? parseActivityContent(content) : content\n\n if (!parsed) {\n return { Icon: Activity, iconClassName: 'text-muted-foreground', title: 'Activity' }\n }\n\n const fileName = str(parsed.file_name)\n\n switch (parsed.event) {\n case 'workspace_opened':\n return {\n Icon: SquareArrowOutUpRight,\n iconClassName: 'text-primary',\n title: 'Opened a workspace',\n }\n case 'workspace_created':\n return { Icon: FolderPlus, iconClassName: 'text-green-600', title: 'Created a workspace' }\n case 'workspace_updated':\n return { Icon: Pencil, iconClassName: 'text-primary', title: 'Updated workspace settings' }\n case 'workspace_deleted':\n return { Icon: Trash2, iconClassName: 'text-red-500', title: 'Deleted a workspace' }\n case 'document_processing': {\n const failed = str(parsed.status) === 'failed'\n const noun = fileName ? `“${fileName}”` : 'a document'\n return failed\n ? { Icon: FileX2, iconClassName: 'text-red-500', title: `Failed to process ${noun}` }\n : { Icon: FileCheck2, iconClassName: 'text-green-600', title: `Processed ${noun}` }\n }\n default:\n // Humanise an unrecognised event slug: \"some_new_event\" → \"Some new event\".\n return {\n Icon: parsed.workspace_ext_id\n ? (getEntityIcon('WORKSPACE') as EntityIconComponent)\n : Activity,\n iconClassName: 'text-muted-foreground',\n title: humaniseEvent(parsed.event),\n }\n }\n}\n\n/** \"workspace_opened\" → \"Workspace opened\" — a readable fallback for new events. */\nfunction humaniseEvent(event: string): string {\n const words = event.replace(/[_-]+/g, ' ').trim()\n return words ? words.charAt(0).toUpperCase() + words.slice(1) : 'Activity'\n}\n","/**\n * ActivityFeed — a presentational, self-fetching list of the current user's\n * durable activity (the to-self \"you opened a workspace / processed a document\"\n * log). Renders each line via the shared {@link describeActivity} descriptor, so\n * the glyph/label knowledge stays in one place and any app (clarum's dashboard,\n * a monolith panel) can drop this in.\n *\n * Pure semantic Tailwind tokens; no store, no app `@/` imports. Data comes from\n * the shared {@link useActivity} query.\n */\n\nimport { Activity } from 'lucide-react'\nimport { useActivity } from '../hooks'\nimport { cn } from '../lib/utils'\nimport { describeActivity } from './activity-types'\n\n/** Relative time like \"just now\", \"3m\", \"2h\", \"5d\"; falls back to a date. */\nfunction formatRelative(iso: string): string {\n const then = new Date(iso).getTime()\n if (Number.isNaN(then)) return ''\n const secs = Math.round((Date.now() - then) / 1000)\n if (secs < 45) return 'just now'\n const mins = Math.round(secs / 60)\n if (mins < 60) return `${mins}m`\n const hours = Math.round(mins / 60)\n if (hours < 24) return `${hours}h`\n const days = Math.round(hours / 24)\n if (days < 7) return `${days}d`\n return new Date(iso).toLocaleDateString()\n}\n\nexport interface ActivityFeedProps {\n /** Max entries to fetch/show. Default 20. */\n limit?: number\n /** Extra classes for the outer container. */\n className?: string\n /** Message shown when there's no activity yet. */\n emptyLabel?: string\n /** Whether to fetch — defaults to enabled when logged in. */\n enabled?: boolean\n 'data-testid'?: string\n}\n\n/**\n * Renders the activity feed. Handles its own loading/empty/error states so a\n * consumer can place it directly (e.g. inside a dashboard card).\n */\nexport function ActivityFeed({\n limit = 20,\n className,\n emptyLabel = 'No recent activity',\n enabled,\n 'data-testid': testId = 'activity-feed',\n}: ActivityFeedProps) {\n const { data, isLoading, isError } = useActivity({ limit, enabled })\n\n if (isLoading) {\n return (\n <div className={cn('space-y-2', className)} data-testid={testId} aria-busy=\"true\">\n {Array.from({ length: 3 }).map((_, i) => (\n <div key={i} className=\"flex items-center gap-3 py-1.5\">\n <div className=\"h-4 w-4 shrink-0 animate-pulse rounded-full bg-muted\" />\n <div className=\"h-3 flex-1 animate-pulse rounded bg-muted\" />\n </div>\n ))}\n </div>\n )\n }\n\n if (isError) {\n return (\n <div className={cn('text-sm text-muted-foreground', className)} data-testid={testId}>\n Couldn’t load activity.\n </div>\n )\n }\n\n const items = data ?? []\n if (items.length === 0) {\n return (\n <div\n className={cn('flex items-center gap-2 text-sm text-muted-foreground', className)}\n data-testid={testId}\n >\n <Activity className=\"h-4 w-4 shrink-0\" />\n <span>{emptyLabel}</span>\n </div>\n )\n }\n\n return (\n <ul className={cn('divide-y divide-border', className)} data-testid={testId}>\n {items.map((item) => {\n const desc = describeActivity(item.content)\n return (\n <li\n key={item.external_id}\n className=\"flex items-center gap-3 py-2\"\n data-testid=\"activity-feed-item\"\n >\n <desc.Icon className={cn('h-4 w-4 shrink-0', desc.iconClassName)} />\n <span className=\"min-w-0 flex-1 truncate text-sm text-foreground\">{desc.title}</span>\n <time className=\"shrink-0 text-xs tabular-nums text-muted-foreground\">\n {formatRelative(item.created_at)}\n </time>\n </li>\n )\n })}\n </ul>\n )\n}\n","/**\n * Persisted notifications (`/v1/notifications`): the list (both what you received and what you\n * sent, newest first), deleting, and read receipts. Every write refreshes every list; rows\n * arriving live are applied by `ArbiWebSocketProvider` (`applyNotificationRow`).\n */\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'\nimport { useArbi } from '../useArbi'\nimport { arbiQueryKeys } from '../hooks'\n\n/** The newest `limit` (default 100) notifications. Live under an `<ArbiWebSocketProvider>`. */\nexport function useNotifications(options: { limit?: number; enabled?: boolean } = {}) {\n const arbi = useArbi()\n const limit = options.limit ?? 100\n return useQuery({\n queryKey: arbiQueryKeys.notifications(limit),\n queryFn: () => arbi.notifications.list({ limit }),\n enabled: (options.enabled ?? true) && arbi.isLoggedIn,\n })\n}\n\n/** Delete notifications for yourself (the other side keeps its copy). */\nexport function useDeleteNotifications() {\n const arbi = useArbi()\n const queries = useQueryClient()\n return useMutation({\n mutationFn: (ids: string[]) => arbi.notifications.delete(ids),\n onSuccess: () => queries.invalidateQueries({ queryKey: arbiQueryKeys.allNotifications() }),\n })\n}\n\n/** Mark notifications addressed to you read. */\nexport function useMarkNotificationsRead() {\n const arbi = useArbi()\n const queries = useQueryClient()\n return useMutation({\n mutationFn: (ids: string[]) => arbi.notifications.markRead(ids),\n onSuccess: () => queries.invalidateQueries({ queryKey: arbiQueryKeys.allNotifications() }),\n })\n}\n","/**\n * What a server-persisted notification (`NotificationResponse`) says and where it leads — the one\n * type→presentation mapping every surface reads (the arrival toast, the bell entry, the\n * notification centre), so wording cannot drift between them or between hosts.\n *\n * Titles derive from `type`, the sender and plaintext routing metadata only: the E2E-encrypted\n * content is never needed. Where an entry leads is data ({@link NotificationTarget}); the host\n * owns navigation and turns a target into its own route.\n */\n\nimport type { components } from '@arbidocs/client'\nimport { mailDraftIdFromContent } from '../mail/client'\nimport type { NotifyVariant } from './notify-store'\n\ntype NotificationResponse = components['schemas']['NotificationResponse']\ntype NotificationUser = NotificationResponse['sender']\n\n/** Where a notification leads. The host maps each kind onto its routes. */\nexport type NotificationTarget =\n /** A workspace's own page (a membership change). */\n | { kind: 'workspace'; workspaceId: string }\n /** A thread, scrolled to a message when given. */\n | { kind: 'conversation'; workspaceId?: string; conversationId: string; messageId?: string }\n /** A document: at a version, on a comment, or on a viewer tab when given. */\n | {\n kind: 'document'\n workspaceId?: string\n documentId: string\n version?: number\n commentId?: string\n tab?: 'pdf'\n }\n /** The mailbox, on a draft when given. */\n | { kind: 'mail'; draftId?: string }\n /** The workflows page, on a workflow (in its workspace) when given. */\n | { kind: 'workflows'; workflowId?: string; workspaceId?: string }\n /** Projects and their AI usage. */\n | { kind: 'projects' }\n | { kind: 'support'; ticketId: number }\n /** Storage settings. */\n | { kind: 'storage' }\n /** Where seats are added (the Box's licence page). */\n | { kind: 'seats' }\n /** Review a workspace access request (choose a workspace and a role). */\n | { kind: 'access-request'; notification: NotificationResponse }\n /** Call the sender back. */\n | { kind: 'call-back'; user: NotificationUser }\n /** An external page, opened in a new tab. */\n | { kind: 'url'; url: string }\n /** The calendar, on an event when given; `join`: join the event's online meeting. */\n | { kind: 'calendar'; eventId?: string; recurrenceId?: string | null; join?: boolean }\n\n/** A server notification's presentation: its sentence, severity, and where it leads. */\nexport interface ServerNotificationDescription {\n title: string\n variant: NotifyVariant\n /** The label of the action that opens {@link target} (\"Review and sign\"); default \"View\". */\n actionLabel?: string\n target?: NotificationTarget\n}\n\nexport interface DescribeServerNotificationOptions {\n /** The sender's display name; default their given and family name, else their email. */\n senderName?: string\n /** The name of a document the notification is about, when the host knows it (names are\n * encrypted, so a notification carries only the id). */\n documentName?: (workspaceId: string | null | undefined, documentId: string) => string | undefined\n /** The portal origins a deployment-user notice may link to. */\n portalOrigins?: readonly string[]\n}\n\n/** A person's display name: given and family name, else their email. */\nexport function notificationUserName(user: NotificationUser): string {\n return [user.given_name, user.family_name].filter(Boolean).join(' ') || user.email\n}\n\nconst CONVERSATION_ID = /^con-[a-zA-Z0-9]+$/\nconst WORKFLOW_ID = /^wfl-[a-zA-Z0-9]+$/\nconst DOCUMENT_ID = /^doc-[a-zA-Z0-9]+$/\n\nfunction parse(content: string | null | undefined): Record<string, unknown> | null {\n try {\n const value = JSON.parse(content || '{}') as unknown\n return value && typeof value === 'object' ? (value as Record<string, unknown>) : null\n } catch {\n return null\n }\n}\n\n/** Deadline metadata is intentionally plaintext; the confidential question stays in the thread. */\nexport function inputRequestTitle(content: string | null | undefined): string {\n const metadata = parse(content)\n if (!metadata) return 'ARBI needs your input — open the thread to reply'\n const timeout = typeof metadata.timeout_seconds === 'number' ? metadata.timeout_seconds : 300\n const minutes = Math.ceil(timeout / 60)\n const deadline = typeof metadata.expires_at === 'string' ? new Date(metadata.expires_at) : null\n if (deadline && Number.isFinite(deadline.getTime())) {\n return `ARBI needs your input — ${minutes} min to reply (until ${deadline.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })})`\n }\n return `ARBI needs your input — ${minutes} min to reply`\n}\n\n/**\n * The plaintext routing content of a `document_activity` notification: `{doc_ext_id, event,\n * reason, version}`. Opaque ids and a closed vocabulary only; never the file name.\n */\nexport function documentActivityMeta(content: string | null | undefined): {\n documentId?: string\n reason?: string\n version?: number\n} {\n const meta = parse(content)\n if (!meta) return {}\n const documentId =\n typeof meta.doc_ext_id === 'string' && DOCUMENT_ID.test(meta.doc_ext_id)\n ? meta.doc_ext_id\n : undefined\n const version =\n typeof meta.version === 'number' && Number.isInteger(meta.version) && meta.version > 0\n ? meta.version\n : undefined\n const reason = typeof meta.reason === 'string' ? meta.reason : undefined\n return { documentId, reason, version }\n}\n\n/** What a `document_activity` says after its sender: \"signed a document\", \"saved version 3 of a document\". */\nexport function documentActivityPhrase(content: string | null | undefined): string {\n const { reason, version } = documentActivityMeta(content)\n if (reason === 'signed') return 'signed a document'\n return version ? `saved version ${version} of a document` : 'saved a new version of a document'\n}\n\n/** The document and comment a `docx_mention` points at (routing ids only). */\nexport function docxMentionMeta(content: string | null | undefined): {\n documentId?: string\n commentId?: string\n} {\n const meta = parse(content)\n if (!meta || typeof meta.document_id !== 'string' || !DOCUMENT_ID.test(meta.document_id))\n return {}\n return {\n documentId: meta.document_id,\n commentId: typeof meta.comment_id === 'string' && meta.comment_id ? meta.comment_id : undefined,\n }\n}\n\n/**\n * The plaintext routing content of a signature-request notification: `{request_id, document_id,\n * signed_version?}`. Opaque ids only: the document's name is encrypted, so it is never in a\n * notification.\n */\nexport function signatureRequestMeta(content: string | null | undefined): {\n documentId?: string\n version?: number\n} {\n const meta = parse(content)\n if (!meta) return {}\n const documentId =\n typeof meta.document_id === 'string' && DOCUMENT_ID.test(meta.document_id)\n ? meta.document_id\n : undefined\n const version =\n typeof meta.signed_version === 'number' && Number.isInteger(meta.signed_version)\n ? meta.signed_version\n : undefined\n return { documentId, version }\n}\n\n/** The notification types of a signature request. */\nexport const SIGNATURE_NOTIFICATION_TYPES = [\n 'signature_requested',\n 'signature_completed',\n 'signature_declined',\n] as const\nexport type SignatureNotificationType = (typeof SIGNATURE_NOTIFICATION_TYPES)[number]\n\nexport function isSignatureNotificationType(\n type: string | null | undefined\n): type is SignatureNotificationType {\n return (SIGNATURE_NOTIFICATION_TYPES as readonly string[]).includes(type ?? '')\n}\n\n/**\n * What a signature notification says, around the person's name and the document's:\n * `{lead} [person] {verb} [document]{tail}`. The recipient reads it about the sender\n * (\"Priya Shah asked you to sign NDA.pdf\"); the sender, in their own activity, about what they did\n * (\"You asked Sam Lee to sign NDA.pdf\"), with the person left out when the sentence needs none.\n */\nexport function signatureNotificationPhrase(\n type: SignatureNotificationType,\n incoming: boolean\n): { lead: string; showPerson: boolean; verb: string; tail: string } {\n if (incoming) {\n switch (type) {\n case 'signature_requested':\n return { lead: '', showPerson: true, verb: 'asked you to sign', tail: '' }\n case 'signature_completed':\n return { lead: '', showPerson: true, verb: 'signed', tail: ' — everyone has now signed' }\n case 'signature_declined':\n return { lead: '', showPerson: true, verb: 'declined to sign', tail: '' }\n }\n }\n switch (type) {\n case 'signature_requested':\n return { lead: 'You asked', showPerson: true, verb: 'to sign', tail: '' }\n case 'signature_completed':\n return { lead: 'You signed', showPerson: false, verb: '', tail: ' — everyone has now signed' }\n case 'signature_declined':\n return { lead: 'You declined to sign', showPerson: false, verb: '', tail: '' }\n }\n}\n\n/**\n * Plaintext routing metadata on call notifications (`call_missed`): `{call_ext_id}`. Never a\n * title — titles are encrypted under the call's key.\n */\nexport function callNotificationMeta(content: string | null | undefined): { callExtId?: string } {\n const meta = parse(content)\n return {\n callExtId:\n typeof meta?.call_ext_id === 'string' && /^call-[a-zA-Z0-9]{8}$/.test(meta.call_ext_id)\n ? meta.call_ext_id\n : undefined,\n }\n}\n\n/** A Box had no seat for a new internal user: the inviter's invitation was not sent. Central\n * emails the inviter and the Box admins; this is the inviter's own notice. */\nexport const BOX_SEAT_REFUSED = 'box_seat_refused'\nexport const BOX_SEAT_REFUSED_TITLE =\n 'Invitation not sent: your Box has no seat left. Your Box admins have been notified and can add users in the ARBI portal.'\nexport const BOX_SEAT_REFUSED_ACTION = 'Open the ARBI portal'\n\n/** A deployment admin's notice about the Box's users (`deployment_user_invited` / `_registered`):\n * an invitation sent (sender = the inviter) or an account created (sender = the new user). */\nexport function isDeploymentUserNotification(type: string | null | undefined): boolean {\n return type === 'deployment_user_invited' || type === 'deployment_user_registered'\n}\n\n/** The portal origins a \"Manage users\" link may open by default. Anything else gets no button. */\nexport const ALLOWED_PORTAL_ORIGINS: readonly string[] = ['https://portal.arbicity.com']\n\n/** The portal link, only when it is https on an allowed portal origin. */\nexport function safePortalUrl(\n value: unknown,\n origins: readonly string[] = ALLOWED_PORTAL_ORIGINS\n): string | undefined {\n if (typeof value !== 'string') return undefined\n try {\n const url = new URL(value)\n if (url.protocol !== 'https:' || !origins.includes(url.origin)) return undefined\n return url.href\n } catch {\n return undefined\n }\n}\n\n/** Plaintext content of a deployment-user notification: `{email, user_type, portal_url}`. */\nexport function deploymentUserMeta(\n content: string | null | undefined,\n origins: readonly string[] = ALLOWED_PORTAL_ORIGINS\n): { email?: string; external: boolean; portalUrl?: string } {\n const meta = parse(content)\n if (!meta) return { external: false }\n const email = typeof meta.email === 'string' && meta.email.trim() ? meta.email.trim() : undefined\n return {\n email,\n external: meta.user_type === 'external',\n portalUrl: safePortalUrl(meta.portal_url, origins),\n }\n}\n\n/** A document's display name, as a document list shows it (its title, else its file name). */\nexport function documentDisplayName(\n doc:\n | { file_name?: string | null; doc_metadata?: { title?: string | null } | null }\n | null\n | undefined\n): string | undefined {\n return doc?.doc_metadata?.title || doc?.file_name || undefined\n}\n\n/** What the work notifications say in a list, where the sender has a column of their own. */\nexport const WORK_NOTIFICATION_LABELS: Readonly<Record<string, string>> = {\n conversation_ready: 'A task is ready',\n conversation_done: 'A task was marked done',\n conversation_notified: 'You were notified in a thread',\n workflow_failed: 'A workflow failed to run',\n}\n\nfunction conversationTarget(n: NotificationResponse): NotificationTarget | undefined {\n if (!n.conversation_ext_id || !CONVERSATION_ID.test(n.conversation_ext_id)) return undefined\n return {\n kind: 'conversation',\n workspaceId: n.workspace_ext_id ?? undefined,\n conversationId: n.conversation_ext_id,\n ...(n.message_ext_id ? { messageId: n.message_ext_id } : {}),\n }\n}\n\n/** The workflows page on the notification's workflow (`{workflow_ext_id}` in its content). */\nfunction workflowTarget(n: NotificationResponse): NotificationTarget {\n const workflowId = parse(n.content)?.workflow_ext_id\n return {\n kind: 'workflows',\n ...(typeof workflowId === 'string' && WORKFLOW_ID.test(workflowId) ? { workflowId } : {}),\n ...(n.workspace_ext_id ? { workspaceId: n.workspace_ext_id } : {}),\n }\n}\n\nfunction signatureTitle(\n n: NotificationResponse,\n senderName: string,\n documentName: DescribeServerNotificationOptions['documentName']\n): string {\n const type = n.type as SignatureNotificationType\n const { documentId } = signatureRequestMeta(n.content)\n const name = documentId ? documentName?.(n.workspace_ext_id, documentId) : undefined\n const fallback = type === 'signature_requested' ? 'a document' : 'your document'\n const { verb, tail } = signatureNotificationPhrase(type, true)\n return `${senderName} ${verb} ${name ?? fallback}${tail}`\n}\n\nfunction quotaPercent(type: string): number | null {\n if (type === 'quota_threshold_100') return 100\n if (type === 'quota_threshold_90') return 90\n if (type === 'quota_threshold_50') return 50\n return null\n}\n\n/**\n * One server notification → what it says to its recipient and where it leads, or null for\n * types without a sentence here (calendar events, sync completions: they have their own\n * surfaces).\n */\nexport function describeServerNotification(\n n: NotificationResponse,\n options: DescribeServerNotificationOptions = {}\n): ServerNotificationDescription | null {\n const senderName = options.senderName ?? notificationUserName(n.sender)\n const workspace: NotificationTarget | undefined = n.workspace_ext_id\n ? { kind: 'workspace', workspaceId: n.workspace_ext_id }\n : undefined\n const type = n.type as string\n\n if (type === BOX_SEAT_REFUSED) {\n return {\n title: BOX_SEAT_REFUSED_TITLE,\n variant: 'warning',\n actionLabel: BOX_SEAT_REFUSED_ACTION,\n target: { kind: 'seats' },\n }\n }\n const pct = quotaPercent(type)\n if (pct !== null) {\n return {\n title: `You have used ${pct}% of your daily AI limit for this project.`,\n variant: pct === 100 ? 'error' : pct === 90 ? 'warning' : 'info',\n target: { kind: 'projects' },\n }\n }\n\n switch (type) {\n case 'support_ticket_received':\n case 'support_ticket_reviewed':\n case 'support_ticket_resolved': {\n const ticketId = parse(n.content)?.ticket_id\n if (typeof ticketId !== 'number' || !Number.isSafeInteger(ticketId) || ticketId < 1)\n return null\n const suppliedReference = parse(n.content)?.ticket_reference\n const reference =\n typeof suppliedReference === 'string' &&\n /^[a-z0-9-]+-[0-9]+$/.test(suppliedReference) &&\n suppliedReference.endsWith(`-${ticketId}`)\n ? suppliedReference\n : `#${ticketId}`\n return {\n title:\n type === 'support_ticket_received'\n ? `We received support request ${reference}`\n : type === 'support_ticket_reviewed'\n ? `We have reviewed support request ${reference}`\n : `Support request ${reference} is resolved`,\n variant: 'success',\n actionLabel: type === 'support_ticket_resolved' ? 'View outcome' : 'View request',\n target: { kind: 'support', ticketId },\n }\n }\n case 'file_shared': {\n const meta = parse(n.content)\n const id = meta?.file_share_id\n if (typeof id !== 'string' || !/^fsh-[0-9a-f]{32}$/.test(id)) return null\n return {\n title: meta?.declined\n ? `${senderName} declined to sign a file`\n : meta?.completed\n ? 'Everyone has signed. Your PDF is ready.'\n : meta?.signature\n ? `${senderName} asked you to sign a file`\n : `${senderName} shared a file with you`,\n variant: meta?.declined ? 'warning' : meta?.completed ? 'success' : 'info',\n actionLabel: meta?.signature && !meta?.completed ? 'Review and sign' : 'Open file',\n target: { kind: 'url', url: `/shared-files/${id}` },\n }\n }\n case 'call_missed':\n return {\n title: `Missed call from ${senderName}`,\n variant: 'warning',\n actionLabel: 'Call back',\n target: { kind: 'call-back', user: n.sender },\n }\n case 'native_mail_received':\n return {\n title: 'New email in your encrypted inbox',\n variant: 'info',\n target: { kind: 'mail' },\n }\n case 'mail_draft_ready': {\n const draftId = mailDraftIdFromContent(n.content)\n return {\n title: `${senderName} left a draft email for you to review`,\n variant: 'info',\n target: { kind: 'mail', ...(draftId ? { draftId } : {}) },\n }\n }\n case 'workspaceuser_added_owner':\n return { title: `${senderName} added you as owner`, variant: 'info', target: workspace }\n case 'workspaceuser_added_collaborator':\n return {\n title: `${senderName} added you as collaborator`,\n variant: 'info',\n target: workspace,\n }\n case 'workspaceuser_added_guest':\n return { title: `${senderName} added you as read only`, variant: 'info', target: workspace }\n case 'workspaceuser_removed':\n return { title: `${senderName} removed you from a workspace`, variant: 'warning' }\n case 'workspaceuser_updated_owner':\n return {\n title: `${senderName} changed your role to owner`,\n variant: 'info',\n target: workspace,\n }\n case 'workspaceuser_updated_collaborator':\n return {\n title: `${senderName} changed your role to collaborator`,\n variant: 'info',\n target: workspace,\n }\n case 'workspaceuser_updated_guest':\n return {\n title: `${senderName} changed your role to read only`,\n variant: 'info',\n target: workspace,\n }\n case 'signature_requested':\n case 'signature_completed':\n case 'signature_declined': {\n const { documentId, version } = signatureRequestMeta(n.content)\n return {\n title: signatureTitle(n, senderName, options.documentName),\n variant:\n type === 'signature_completed'\n ? 'success'\n : type === 'signature_declined'\n ? 'warning'\n : 'info',\n actionLabel: type === 'signature_requested' ? 'Review and sign' : 'Open',\n // A request opens the current version on its PDF, where the banner offers \"Review and\n // sign\"; a completed request opens the signed copy.\n target: documentId\n ? {\n kind: 'document',\n workspaceId: n.workspace_ext_id ?? undefined,\n documentId,\n ...(version ? { version } : {}),\n tab: 'pdf',\n }\n : undefined,\n }\n }\n case 'docx_mention': {\n const { documentId, commentId } = docxMentionMeta(n.content)\n return {\n title: `${senderName} mentioned you in a document comment`,\n variant: 'info',\n target: documentId\n ? {\n kind: 'document',\n workspaceId: n.workspace_ext_id ?? undefined,\n documentId,\n ...(commentId ? { commentId } : {}),\n }\n : undefined,\n }\n }\n case 'agent_input_requested':\n return { title: inputRequestTitle(n.content), variant: 'info', target: conversationTarget(n) }\n case 'mention':\n return {\n title: `${senderName} mentioned you in a conversation`,\n variant: 'info',\n target: conversationTarget(n),\n }\n case 'thread_reply':\n return {\n title: `${senderName} replied in a thread`,\n variant: 'info',\n target: conversationTarget(n),\n }\n case 'document_activity': {\n const { documentId, version } = documentActivityMeta(n.content)\n return {\n title: `${senderName} ${documentActivityPhrase(n.content)}`,\n variant: 'info',\n target: documentId\n ? {\n kind: 'document',\n workspaceId: n.workspace_ext_id ?? undefined,\n documentId,\n ...(version ? { version } : {}),\n }\n : undefined,\n }\n }\n // Each of these opens the thread, so the person it is for finds it. One about your own thread\n // (you started the work) says so.\n case 'conversation_ready':\n return {\n title:\n n.sender.external_id === n.recipient.external_id\n ? 'Your thread is ready'\n : `${senderName}’s thread is ready`,\n variant: 'info',\n target: conversationTarget(n),\n }\n case 'conversation_notified':\n return {\n title: `${senderName} notified you in a thread`,\n variant: 'info',\n target: conversationTarget(n),\n }\n case 'conversation_done':\n return {\n title: `${senderName} marked a thread done`,\n variant: 'success',\n target: conversationTarget(n),\n }\n case 'workflow_completed':\n return { title: 'A workflow completed', variant: 'success', target: workflowTarget(n) }\n // The failed run's thread when it has one (its error is there), else the workflow.\n case 'workflow_failed':\n return {\n title: 'A workflow failed to start',\n variant: 'error',\n target: conversationTarget(n) ?? workflowTarget(n),\n }\n case 'deployment_user_invited':\n case 'deployment_user_registered': {\n const { email, external, portalUrl } = deploymentUserMeta(n.content, options.portalOrigins)\n const suffix = external ? ' · External' : ''\n return {\n title:\n type === 'deployment_user_invited'\n ? `${senderName} invited ${email ?? 'a new user'}${suffix}`\n : `${email ?? senderName} joined${suffix}`,\n variant: 'info',\n ...(portalUrl && {\n actionLabel: 'Manage users',\n target: { kind: 'url' as const, url: portalUrl },\n }),\n }\n }\n case 'contact_accepted':\n return { title: `${senderName} joined the platform`, variant: 'success', target: workspace }\n case 'workspace_access_request':\n return {\n title: `${senderName} asked for workspace access`,\n variant: 'info',\n // Straight into the review — granting needs a workspace choice and a role, so a bare\n // \"grant\" action could never be right here.\n target: { kind: 'access-request', notification: n },\n }\n case 'project_quota_warning': {\n let resource = 'usage'\n let percentage: number | null = null\n let upgrade = ''\n let impending = false\n try {\n const data = JSON.parse(n.content ?? '{}')\n resource = data.resource === 'storage_gb' ? 'storage' : 'AI credits'\n if (data.limit > 0) percentage = Math.round((data.used / data.limit) * 100)\n if (data.stage === 'before_upgrade') {\n impending = true\n const charge = new Intl.NumberFormat('en-GB', {\n style: 'currency',\n currency: data.currency || 'GBP',\n }).format(data.charge_ex_vat_pence / 100)\n upgrade = `An automatic ${resource} upgrade will now be attempted: ${charge} ex VAT.`\n } else if (data.automatic_upgrade === true) {\n upgrade =\n ' An automatic upgrade is available within your limit and will be attempted when needed, subject to payment.'\n } else if (data.automatic_upgrade === false) {\n upgrade =\n data.upgrade_reason === 'limit'\n ? ' No automatic upgrade fits your remaining limit. Increase it or add allowances to keep working.'\n : data.upgrade_reason === 'payment'\n ? ' Automatic upgrades are paused. Resolve your payment issue to keep working.'\n : ' Automatic upgrades are unavailable. Upgrade your plan or reduce usage to keep working.'\n }\n } catch {\n /* An old or malformed notice still opens project usage. */\n }\n return {\n title: impending\n ? upgrade\n : `Your project is approaching its ${resource} limit${percentage != null ? ` (${percentage}% used)` : ''}.${upgrade}`,\n variant: 'warning',\n target: { kind: 'projects' },\n }\n }\n case 'project_retention': {\n let deadline = ''\n try {\n const data = JSON.parse(n.content ?? '{}')\n if (data.deletion_at) deadline = new Date(data.deletion_at).toLocaleDateString('en-GB')\n } catch {\n /* display the recovery notice without a date */\n }\n return {\n title: `Your project subscription has ended. Export or resubscribe${deadline ? ` before ${deadline}` : ''} to keep its data.`,\n variant: 'warning',\n target: { kind: 'projects' },\n }\n }\n case 'storage_quota_exceeded':\n return {\n title:\n 'Your storage is full. Mail still arrives, but new uploads and attachments are paused until you free space or add storage.',\n variant: 'error',\n target: { kind: 'storage' },\n }\n case 'signup_reward':\n return {\n title: n.content ? `🎉 Signup bonus — ${n.content}` : '🎉 You earned a signup bonus!',\n variant: 'success',\n target: { kind: 'projects' },\n }\n case 'referral_reward':\n return {\n title: n.content ? `🎁 Reward — ${n.content}` : '🎁 You earned a reward!',\n variant: 'success',\n target: { kind: 'projects' },\n }\n default:\n return null\n }\n}\n","/**\n * What a native calendar notification (`calendar_*`) says and where it leads. Its content is\n * plaintext routing metadata only (`{uid, organizer_id|attendee_id, starts_at, partstat?,\n * event_id?, calendar_id?, recurrence_id?, has_conference, call_id?, time_zone?}`), so a title\n * never needs the encrypted event. Times show in the user's calendar time zone (the reminder's\n * `time_zone`, else the one the host passes), never the browser's.\n */\nimport type { components } from '@arbidocs/client'\nimport type { ServerNotificationDescription } from './server-notifications'\n\ntype NotificationResponse = components['schemas']['NotificationResponse']\n\nexport interface CalendarNotificationMeta {\n eventId?: string\n recurrenceId?: string | null\n startsAt?: Date\n partstat?: string\n hasConference: boolean\n timeZone?: string\n}\n\nfunction validZone(zone: unknown): string | undefined {\n if (typeof zone !== 'string' || !zone) return undefined\n try {\n new Intl.DateTimeFormat('en', { timeZone: zone })\n return zone\n } catch {\n return undefined\n }\n}\n\n/** The routing metadata of a calendar notification. */\nexport function calendarNotificationMeta(\n content: string | null | undefined\n): CalendarNotificationMeta {\n try {\n const m = JSON.parse(content || '{}') as Record<string, unknown>\n const startsAt = typeof m.starts_at === 'string' ? new Date(m.starts_at) : undefined\n return {\n eventId:\n typeof m.event_id === 'string' && /^evt-[A-Za-z0-9]{8}$/.test(m.event_id)\n ? m.event_id\n : undefined,\n recurrenceId: typeof m.recurrence_id === 'string' ? m.recurrence_id : null,\n startsAt: startsAt && Number.isFinite(startsAt.getTime()) ? startsAt : undefined,\n partstat: typeof m.partstat === 'string' ? m.partstat : undefined,\n hasConference: m.has_conference === true,\n timeZone: validZone(m.time_zone),\n }\n } catch {\n return { hasConference: false }\n }\n}\n\nfunction when(date: Date | undefined, timeZone: string | undefined): string {\n if (!date) return ''\n return ` (${date.toLocaleString([], { weekday: 'short', day: 'numeric', month: 'short', hour: '2-digit', minute: '2-digit', timeZone })})`\n}\n\nconst PARTSTAT_WORDS: Record<string, string> = {\n accepted: 'accepted',\n declined: 'declined',\n tentative: 'tentatively accepted',\n delegated: 'delegated',\n}\n\nexport interface DescribeCalendarNotificationOptions {\n /** The sender's display name. */\n senderName: string\n /** The user's calendar time zone (their calendar settings), when the notification has none. */\n timeZone?: string | null\n}\n\n/**\n * A calendar notification → its sentence and the calendar (on its event) it opens, or null for\n * another type. A reminder of an online meeting joins it (`join`).\n */\nexport function describeCalendarNotification(\n n: NotificationResponse,\n { senderName, timeZone }: DescribeCalendarNotificationOptions\n): ServerNotificationDescription | null {\n const type: string = n.type\n if (!type.startsWith('calendar_')) return null\n const meta = calendarNotificationMeta(n.content)\n const zone = meta.timeZone ?? validZone(timeZone)\n const at = when(meta.startsAt, zone)\n const target = {\n kind: 'calendar' as const,\n ...(meta.eventId && { eventId: meta.eventId, recurrenceId: meta.recurrenceId }),\n }\n switch (type) {\n case 'calendar_invite':\n return { title: `${senderName} invited you to an event${at}`, variant: 'info', target }\n case 'calendar_update':\n return { title: `${senderName} updated an event${at}`, variant: 'info', target }\n case 'calendar_cancel':\n return { title: `${senderName} cancelled an event${at}`, variant: 'warning', target }\n case 'calendar_reply': {\n const word = PARTSTAT_WORDS[meta.partstat ?? ''] ?? 'replied to'\n return {\n title: `${senderName} ${word} your invitation${at}`,\n variant: meta.partstat === 'declined' ? 'warning' : 'info',\n target,\n }\n }\n case 'calendar_share':\n return { title: `${senderName} shared a calendar with you`, variant: 'info', target }\n case 'calendar_counter':\n return { title: `${senderName} proposed a new time${at}`, variant: 'info', target }\n case 'calendar_reminder': {\n const title = meta.startsAt\n ? `An event starts at ${meta.startsAt.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', timeZone: zone })}`\n : 'An event starts soon'\n if (meta.hasConference && meta.eventId)\n return { title, variant: 'info', actionLabel: 'Join', target: { ...target, join: true } }\n return { title, variant: 'info', actionLabel: 'Open', target }\n }\n default:\n return { title: 'Calendar update', variant: 'info', target }\n }\n}\n","/**\n * One server notification as a bell (and arrival toast) entry: what it says (the shared\n * `describeServerNotification`, or `describeCalendarNotification`) and what selecting it does.\n * The host's routing comes in as `open` (blocks: `useOpenNotificationTarget`) and `hrefFor`.\n */\nimport type { components } from '@arbidocs/client'\nimport { describeCalendarNotification } from './calendar-notifications'\nimport type { AppNotification } from './notify-store'\nimport {\n describeServerNotification,\n notificationUserName,\n type DescribeServerNotificationOptions,\n type NotificationTarget,\n} from './server-notifications'\n\ntype NotificationResponse = components['schemas']['NotificationResponse']\n\nexport interface ServerNotificationBellOptions extends Pick<\n DescribeServerNotificationOptions,\n 'documentName' | 'portalOrigins'\n> {\n /** Open where an entry leads. */\n open: (target: NotificationTarget) => void\n /** A workspace's link (an entry about a workspace is a link, not an action). */\n workspaceHref?: (workspaceId: string) => string | undefined\n /** The user's calendar time zone, for calendar notifications that carry none. */\n calendarTimeZone?: string | null\n}\n\n/**\n * The bell entry of a notification row, or null for a row the bell does not carry. `actionLabel`\n * names the toast's action (\"Review and sign\"); a workspace's own page is a link (`href`), every\n * other target an action (`onSelect`).\n */\nexport function serverNotificationBellEntry(\n n: NotificationResponse,\n { open, workspaceHref, calendarTimeZone, ...describe }: ServerNotificationBellOptions\n): AppNotification | null {\n const senderName = notificationUserName(n.sender)\n const described =\n describeCalendarNotification(n, { senderName, timeZone: calendarTimeZone }) ??\n describeServerNotification(n, { senderName, ...describe })\n if (!described) return null\n const { title, variant, actionLabel, target } = described\n return {\n id: n.external_id,\n ts: Date.parse(n.created_at),\n read: n.read ?? false,\n title,\n variant,\n href: target?.kind === 'workspace' ? workspaceHref?.(target.workspaceId) : undefined,\n ...(target && { actionLabel: actionLabel ?? 'Open', onSelect: () => open(target) }),\n }\n}\n","/** Small presentation helpers for the DM kit. */\n\nimport type { DmUser } from './types'\n\n/** Initials from a user's name (falls back to the email local-part). */\nexport function userInitials(user: Pick<DmUser, 'given_name' | 'family_name' | 'email'>): string {\n const parts = [user.given_name, user.family_name].filter(Boolean) as string[]\n if (parts.length) {\n return parts\n .map((p) => p[0]?.toUpperCase() ?? '')\n .join('')\n .slice(0, 2)\n }\n const local = user.email?.split('@')[0] ?? ''\n return local.slice(0, 2).toUpperCase() || '?'\n}\n\n/** Full display name (falls back to the email local-part). */\nexport function userDisplayName(\n user: Pick<DmUser, 'given_name' | 'family_name' | 'email'>\n): string {\n const name = [user.given_name, user.family_name].filter(Boolean).join(' ').trim()\n return name || user.email?.split('@')[0] || 'Unknown'\n}\n\n/**\n * Whether a peer is an agent rather than a person.\n *\n * Derived from the `agt-` external-id prefix, which is the platform's own\n * convention and already assumed elsewhere in the kit (entity colours are keyed\n * off the same ids). Deriving it once here is what lets every DM surface mark\n * agents without each consumer having to resolve and pass a flag.\n */\nexport function isAgentUser(user: Pick<DmUser, 'external_id'>): boolean {\n return user.external_id.startsWith('agt-')\n}\n\nexport { formatRelativeTime } from '../lib/format-relative-time'\n","/**\n * A peer avatar in a DM surface.\n *\n * This used to be its own small avatar that knew nothing about agents or\n * presence, which is why the ARBI app replaced it on every row with a\n * hand-rolled variant of its own. It is now a thin adapter over\n * {@link UserEntity} — the one presentational person component — so a DM row, a\n * members table and a document owner all draw a person the same way.\n *\n * The name and props are unchanged: it is exported from the package, and\n * consumers should not have to care that the implementation collapsed.\n */\n\nimport { UserEntity, type PresenceDisplayStatus } from '../entities/UserEntity'\nimport { getEntityColorStyles } from '../entities/colors'\nimport type { EntitySize } from '../entities/EntityPill'\nimport { useArbiWsStore } from '../websocket/store'\nimport type { DmUser } from './types'\nimport { userDisplayName, userInitials, isAgentUser } from './utils'\n\nexport interface DmAvatarProps {\n user: DmUser\n className?: string\n /** Defaults to the 40px row avatar this component has always drawn. */\n size?: EntitySize\n}\n\nexport function DmAvatar({ user, className, size = 'lg' }: DmAvatarProps) {\n // Presence comes from the shared WS store, which stays empty until an app\n // mounts ArbiWebSocketProvider. That is deliberate: with no socket we know\n // nothing about who is online, and `undefined` hides the dot rather than\n // asserting that everyone is offline.\n const presence = useArbiWsStore((s) => s.presence[user.external_id])\n const displayStatus: PresenceDisplayStatus | undefined =\n presence === undefined ? undefined : presence === 'online' ? 'connected' : 'disconnected'\n\n return (\n <UserEntity\n variant=\"icon\"\n size={size}\n className={className}\n interactive={false}\n showTooltip={false}\n initials={userInitials(user)}\n displayName={userDisplayName(user)}\n picture={user.picture}\n // Deterministic tint from the user's id so the fallback is stable + distinct.\n avatarStyle={getEntityColorStyles(user.external_id)}\n isAgent={isAgentUser(user)}\n displayStatus={displayStatus}\n />\n )\n}\n","/**\n * The left rail: a scrollable list of conversations (1:1 or group), each showing\n * an avatar, name or title, last-message preview, relative time, and an unread pill.\n */\n\nimport { Check, CheckCheck } from 'lucide-react'\nimport { Badge } from '../ui/badge'\nimport { cn } from '../lib/utils'\nimport type { DmClassNames, DmConversation } from './types'\nimport { formatRelativeTime, userDisplayName, isAgentUser } from './utils'\nimport { DmAvatar } from './DmAvatar'\nimport { AgentBadge } from '../entities/AgentMarkers'\n\nexport interface ConversationListProps {\n conversations: DmConversation[]\n /** The selected row's id (`id ?? peer.external_id`). */\n selectedPeerId: string | null\n /** Receives the row's id (`id ?? peer.external_id`). */\n onSelect: (id: string) => void\n classNames?: Pick<DmClassNames, 'unreadBadge'>\n /** Rendered when there are no conversations. */\n emptyState?: React.ReactNode\n /**\n * Replaces the default \"Conversations / N colleagues\" heading — e.g. with a\n * call to action. Pass `null` for no heading at all.\n */\n header?: React.ReactNode\n /**\n * Overrides the rail's own sizing. The default is a fixed-width column beside\n * a thread; a consumer showing the list on its own needs it to fill instead,\n * and cannot get there by wrapping (a narrower wrapper clips rather than\n * shrinks).\n */\n className?: string\n}\n\nexport function ConversationList({\n conversations,\n selectedPeerId,\n onSelect,\n classNames,\n emptyState,\n header,\n className,\n}: ConversationListProps) {\n return (\n <aside\n className={cn(\n 'flex min-h-0 flex-col border-b border-border md:w-80 md:shrink-0 md:border-b-0 md:border-r',\n className\n )}\n data-testid=\"arbi-dm-list\"\n >\n {header === undefined ? (\n <div className=\"border-b border-border px-4 py-3\">\n <p className=\"text-sm font-semibold text-foreground\">Conversations</p>\n <p className=\"text-xs text-muted-foreground\">\n {conversations.length} {conversations.length === 1 ? 'colleague' : 'colleagues'}\n </p>\n </div>\n ) : (\n header\n )}\n <div className=\"min-h-0 flex-1 overflow-y-auto\">\n {conversations.length === 0 ? (\n <div className=\"px-4 py-6 text-xs text-muted-foreground\">\n {emptyState ?? 'No conversations yet.'}\n </div>\n ) : (\n <ul className=\"w-full\">\n {conversations.map((c, i) => {\n const { peer, lastMessage, unreadCount } = c\n const rowId = c.id ?? peer.external_id\n // The heading renders once, above the first row of its group.\n const newSection =\n c.sectionLabel && c.sectionLabel !== conversations[i - 1]?.sectionLabel\n const active = rowId === selectedPeerId\n const preview = lastMessage?.body ?? 'No messages yet — say hello'\n // Unread rows carry weight, which is the signal you catch scanning\n // a list — the count alone is a detail you have to go looking for.\n const unread = unreadCount > 0\n const body = (\n <>\n {c.leading ?? <DmAvatar user={peer} />}\n <div className=\"min-w-0 flex-1\">\n {/* Count sits with the name; the time sits with the message\n it belongs to. They were the other way round, which put\n \"just now\" beside a name it said nothing about. */}\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"flex min-w-0 items-center gap-1.5\">\n <span\n className={cn(\n 'truncate text-sm text-foreground',\n unread ? 'font-bold' : 'font-semibold'\n )}\n >\n {c.title ?? userDisplayName(peer)}\n </span>\n {/* An agent is marked by default — a consumer only\n supplies `badge` to say something else. */}\n {c.badge ?? (isAgentUser(peer) ? <AgentBadge /> : null)}\n </span>\n {c.statusLabel ? (\n <Badge\n variant=\"outline\"\n className=\"shrink-0 rounded-full px-2 py-0 text-xs font-medium text-muted-foreground\"\n >\n {c.statusLabel}\n </Badge>\n ) : unreadCount > 0 ? (\n // Quiet by default: a filled brand pill with a shadow\n // shouted louder than the message it was counting.\n // Enough to catch the eye scanning the list, no more.\n <Badge\n variant=\"accent\"\n className={cn(\n 'min-w-[1.125rem] justify-center rounded-full px-1 py-0 text-xs font-medium leading-[1.125rem] shadow-none',\n classNames?.unreadBadge\n )}\n >\n {unreadCount}\n </Badge>\n ) : null}\n </div>\n <div className=\"mt-1 flex items-center gap-1.5\">\n {/* Your own last message is marked with the same tick the\n bubble carries — one delivered, two read. It says who\n spoke last AND whether it landed, which a \"You:\" prefix\n cannot, and costs no preview width. */}\n {lastMessage?.isMine ? (\n lastMessage.read ? (\n <CheckCheck\n className=\"size-3.5 shrink-0 text-ai-accent\"\n aria-label=\"Read\"\n />\n ) : (\n <Check\n className=\"size-3.5 shrink-0 text-muted-foreground\"\n aria-label=\"Sent\"\n />\n )\n ) : null}\n <p\n className={cn(\n 'min-w-0 flex-1 truncate text-xs',\n unread ? 'font-medium text-foreground' : 'text-muted-foreground'\n )}\n >\n {c.subtitle ?? preview}\n </p>\n <span className=\"shrink-0 text-xs text-muted-foreground\">\n {lastMessage ? formatRelativeTime(lastMessage.createdAt) : ''}\n </span>\n </div>\n </div>\n </>\n )\n\n // An invitation that nobody has accepted has no thread to open, so\n // it is listed but not offered as something to click.\n const rowClass = cn(\n // Each row is its own opaque surface. Left transparent it takes\n // the panel's colour, and the chips stop reading as cards at all\n // — which is the whole point of them.\n 'flex w-full items-start gap-3 border-b border-border/60 bg-card px-4 py-3 text-left transition-colors',\n c.disabled ? 'cursor-default' : active ? 'bg-ai-accent-soft' : 'hover:bg-accent/40'\n )\n\n return (\n <li key={rowId}>\n {newSection && (\n <p\n className=\"bg-muted/40 px-4 py-1.5 text-xs font-medium uppercase tracking-wide text-muted-foreground\"\n data-testid=\"arbi-dm-section\"\n >\n {c.sectionLabel}\n </p>\n )}\n {c.disabled ? (\n <div data-testid={`arbi-dm-conversation-${rowId}`} className={rowClass}>\n {body}\n {c.trailing}\n </div>\n ) : (\n <button\n type=\"button\"\n onClick={() => onSelect(rowId)}\n data-testid={`arbi-dm-conversation-${rowId}`}\n className={rowClass}\n >\n {body}\n </button>\n )}\n </li>\n )\n })}\n </ul>\n )}\n </div>\n </aside>\n )\n}\n","/**\n * The message composer: an auto-sizing textarea + send button. Enter sends,\n * Shift+Enter inserts a newline.\n *\n * With `allowAttachments`, files can be added with the paperclip, pasted (an\n * image copied to the clipboard) or dropped onto the composer. They show as\n * removable chips and are handed to `onSend` alongside the text; the host\n * encrypts and uploads them. The DM limits (10 files, 15 MB each) are checked\n * here so an oversized file is refused before any work starts.\n */\n\nimport { useRef, useState } from 'react'\nimport { Loader2, Paperclip, Send, X } from 'lucide-react'\nimport { chats, formatFileSize } from '@arbidocs/sdk/browser'\nimport { Button } from '../ui/button'\nimport { Textarea } from '../ui/textarea'\nimport { cn } from '../lib/utils'\nimport type { DmClassNames } from './types'\n\nexport interface DmComposerProps {\n /** Placeholder, e.g. \"Message Eleanor…\". */\n placeholder?: string\n disabled?: boolean\n /**\n * A send is in flight: swaps the icon for a spinner and blocks a second\n * submit, so a slow encrypt-and-post can't be fired twice by an impatient\n * Enter.\n */\n busy?: boolean\n /**\n * Called with the trimmed text and any attached files when the user sends.\n * The text may be empty when files are attached. May reject if the send\n * fails, in which case the text and files are given back.\n */\n onSend: (text: string, files: File[]) => void | Promise<void>\n /** Offer attaching files (button, paste, drag-and-drop). Off by default. */\n allowAttachments?: boolean\n /** Shown under the box when the last send failed. */\n error?: string | null\n /** Extra content between the box and the border (e.g. a peer-specific action). */\n children?: React.ReactNode\n classNames?: Pick<DmClassNames, 'sendButton'>\n}\n\nexport function DmComposer({\n placeholder,\n disabled,\n busy,\n onSend,\n allowAttachments,\n error,\n children,\n classNames,\n}: DmComposerProps) {\n const [draft, setDraft] = useState('')\n const [files, setFiles] = useState<File[]>([])\n const [attachError, setAttachError] = useState<string | null>(null)\n const [dragging, setDragging] = useState(false)\n const inputRef = useRef<HTMLTextAreaElement>(null)\n const fileInputRef = useRef<HTMLInputElement>(null)\n\n const addFiles = (added: File[]) => {\n if (!allowAttachments || added.length === 0) return\n const next = [...files, ...added]\n try {\n chats.checkChatAttachmentLimits(next)\n setFiles(next)\n setAttachError(null)\n } catch (err) {\n setAttachError(err instanceof Error ? err.message : 'Could not attach the file')\n }\n }\n\n const removeFile = (index: number) => {\n setFiles((current) => current.filter((_, i) => i !== index))\n setAttachError(null)\n }\n\n const submit = async () => {\n const text = draft.trim()\n if ((!text && files.length === 0) || disabled || busy) return\n const sending = files\n setDraft('')\n setFiles([])\n setAttachError(null)\n try {\n await onSend(text, sending)\n // Keep the caret in the box so a reply can follow straight on.\n inputRef.current?.focus()\n } catch {\n // The send failed (the error surfaces via `error`) — give the text and\n // files back rather than losing what the user wrote.\n setDraft(text)\n setFiles(sending)\n }\n }\n\n const onKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n void submit()\n }\n }\n\n const onPaste = (e: React.ClipboardEvent<HTMLTextAreaElement>) => {\n if (!allowAttachments) return\n const pasted = Array.from(e.clipboardData?.files ?? [])\n if (pasted.length === 0) return\n e.preventDefault()\n addFiles(pasted)\n }\n\n const hasFiles = (e: React.DragEvent) => Array.from(e.dataTransfer?.types ?? []).includes('Files')\n\n const dropHandlers = allowAttachments\n ? {\n onDragOver: (e: React.DragEvent) => {\n if (!hasFiles(e) || disabled) return\n e.preventDefault()\n setDragging(true)\n },\n onDragLeave: (e: React.DragEvent) => {\n if (e.currentTarget.contains(e.relatedTarget as Node | null)) return\n setDragging(false)\n },\n onDrop: (e: React.DragEvent) => {\n setDragging(false)\n const dropped = Array.from(e.dataTransfer?.files ?? [])\n if (dropped.length === 0 || disabled) return\n e.preventDefault()\n addFiles(dropped)\n },\n }\n : {}\n\n return (\n <div\n className={cn(\n 'border-t border-border p-3',\n dragging && 'bg-muted/60 outline-dashed outline-2 -outline-offset-4 outline-primary'\n )}\n data-testid=\"arbi-dm-composer\"\n {...dropHandlers}\n >\n {children}\n {files.length > 0 && (\n <ul className=\"mb-2 flex flex-wrap gap-2\" aria-label=\"Attached files\">\n {files.map((f, index) => (\n <li\n key={`${f.name}-${index}`}\n data-testid=\"arbi-dm-attachment-chip\"\n className=\"flex max-w-full items-center gap-2 rounded-md border border-border/70 bg-muted/30 px-2.5 py-1.5 text-xs\"\n >\n <Paperclip className=\"size-3 shrink-0\" aria-hidden=\"true\" />\n <span className=\"truncate\">{f.name}</span>\n <span className=\"shrink-0 text-muted-foreground\">{formatFileSize(f.size)}</span>\n <button\n type=\"button\"\n disabled={busy}\n aria-label={`Remove ${f.name}`}\n onClick={() => removeFile(index)}\n className=\"shrink-0 rounded focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n >\n <X className=\"size-3\" />\n </button>\n </li>\n ))}\n </ul>\n )}\n <div className=\"flex items-end gap-2\">\n {allowAttachments && (\n <>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n disabled={disabled || busy}\n onClick={() => fileInputRef.current?.click()}\n aria-label=\"Attach files\"\n title=\"Attach files (or paste / drop them here)\"\n data-testid=\"arbi-dm-attach\"\n className=\"min-h-[44px] shrink-0\"\n >\n <Paperclip className=\"size-4\" />\n </Button>\n <input\n ref={fileInputRef}\n type=\"file\"\n multiple\n hidden\n data-testid=\"arbi-dm-file-input\"\n onChange={(e) => {\n addFiles(Array.from(e.target.files ?? []))\n // Let the same file be picked again after it was removed.\n e.target.value = ''\n }}\n />\n </>\n )}\n <Textarea\n ref={inputRef}\n value={draft}\n onChange={(e) => setDraft(e.target.value)}\n onKeyDown={onKeyDown}\n onPaste={onPaste}\n placeholder={placeholder}\n rows={1}\n disabled={disabled}\n className=\"max-h-40 min-h-[44px] resize-none\"\n data-testid=\"arbi-dm-input\"\n />\n <Button\n type=\"button\"\n onClick={() => void submit()}\n disabled={disabled || busy || (!draft.trim() && files.length === 0)}\n className={cn(classNames?.sendButton)}\n data-testid=\"arbi-dm-send\"\n aria-label=\"Send message\"\n >\n {busy ? <Loader2 className=\"size-4 animate-spin\" /> : <Send className=\"size-4\" />} Send\n </Button>\n </div>\n {attachError && (\n <p\n className=\"mt-2 text-xs text-destructive\"\n role=\"alert\"\n data-testid=\"arbi-dm-attach-error\"\n >\n {attachError}\n </p>\n )}\n {error && (\n <p className=\"mt-2 text-xs text-destructive\" data-testid=\"arbi-dm-error\">\n {error}\n </p>\n )}\n </div>\n )\n}\n","/**\n * Chat hooks on the one chat cache (`chat-cache.ts`): my chats, unread totals, decrypted list\n * previews, one open thread, and the writes (send, delete, read, groups). Everything runs on the\n * SDK's end-to-end encrypted `arbi.chats`; nothing here touches keys or ciphertext.\n */\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'\nimport { chats as chatOps } from '@arbidocs/sdk/browser'\nimport { useArbi } from '../useArbi'\nimport { arbiQueryKeys } from '../hooks'\nimport {\n appendToThread,\n deleteChatMessage,\n dropFromThread,\n myChatId,\n removeChat,\n upsertChat,\n type AgentDmStatus,\n type ChatMemberKey,\n type ChatResponse,\n type ChatThreadData,\n type ChatThreadMessage,\n} from './chat-cache'\n\n/** My chats (raw), most recently active first. */\nexport function useChats(options: { enabled?: boolean } = {}) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.chatList(),\n queryFn: () => arbi.chats.list(),\n enabled: (options.enabled ?? true) && arbi.isLoggedIn,\n })\n}\n\n/** My own agent's latest progress on a message I sent it, live from the chat events. */\nexport function useAgentDmStatus(agentExtId: string | null | undefined): AgentDmStatus | undefined {\n const { data } = useQuery<AgentDmStatus | null>({\n queryKey: arbiQueryKeys.agentDmStatus(agentExtId ?? ''),\n // Written by the events only: nothing to fetch.\n queryFn: () => null,\n enabled: false,\n staleTime: Infinity,\n })\n return agentExtId ? (data ?? undefined) : undefined\n}\n\n/** Unread messages across all my chats (the badge on the messages entry points). */\nexport function useChatUnreadTotal(): number {\n const { data = [] } = useChats()\n return useMemo(() => data.reduce((sum, c) => sum + (c.unread_count ?? 0), 0), [data])\n}\n\n/** Unread count per direct-chat peer (`usr-`/`agt-` id), for per-person badges and filters. */\nexport function useUnreadByPeer(): Map<string, number> {\n const arbi = useArbi()\n const { data = [] } = useChats()\n const me = myChatId(arbi)\n return useMemo(() => {\n const out = new Map<string, number>()\n for (const c of data) {\n if (c.kind !== 'direct' || !c.unread_count) continue\n const peer = c.members.find((m) => m.user.external_id !== me)?.user.external_id ?? me\n if (peer) out.set(peer, (out.get(peer) ?? 0) + c.unread_count)\n }\n return out\n }, [data, me])\n}\n\nexport interface ChatSummary {\n /** Decrypted group title (null for direct chats or one that does not open). */\n title: string | null\n /** Decrypted last message, one line. */\n preview: string | null\n}\n\n/**\n * Decrypted titles and last-message previews for a list of chats. Only the newest message of\n * each chat is decrypted — a thread decrypts in full when it is opened, and its copy is used.\n */\nexport function useChatSummaries(chats: ChatResponse[]): Record<string, ChatSummary> {\n const arbi = useArbi()\n const queryClient = useQueryClient()\n const [summaries, setSummaries] = useState<Record<string, ChatSummary>>({})\n const runId = useRef(0)\n const key = chats\n .map(\n (c) =>\n `${c.external_id}:${c.key_version}:${c.title ?? ''}:${c.last_message?.external_id ?? ''}:${c.last_message?.deleted ? 'x' : ''}`\n )\n .join('|')\n\n useEffect(() => {\n if (!chats.length || !arbi.isLoggedIn) return\n const id = ++runId.current\n void (async () => {\n const next: Record<string, ChatSummary> = {}\n for (const chat of chats) {\n const title = await arbi.chats.title(chat).catch(() => null)\n // A tombstone is never a preview (nor decrypted): the refetched chat brings the one before.\n const last = chat.last_message?.deleted ? null : chat.last_message\n let preview: string | null = null\n // The open thread's copy: my own post reaches the list already decrypted (as the send\n // returns it), and plaintext does not decrypt.\n const open = queryClient\n .getQueryData<ChatThreadData>(arbiQueryKeys.chatThread(chat.external_id))\n ?.messages.find((m) => m.external_id === last?.external_id)\n if (open) preview = chatOps.chatMessagePreview(open)\n else if (last) {\n preview = await arbi.chats\n .decrypt(chat, last)\n .then(chatOps.chatMessagePreview)\n .catch(() => chatOps.ENCRYPTED_PREVIEW)\n }\n next[chat.external_id] = { title, preview }\n }\n if (id === runId.current) setSummaries(next)\n })()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [key, arbi])\n\n return summaries\n}\n\n/**\n * One open thread: the newest page decrypted (oldest first), kept live by the chat events, with\n * `loadOlder` paging backwards.\n */\nexport function useChatThread(chat: ChatResponse | null) {\n const arbi = useArbi()\n const queryClient = useQueryClient()\n const chatExtId = chat?.external_id ?? ''\n const chatRef = useRef(chat)\n chatRef.current = chat\n const query = useQuery<ChatThreadData>({\n queryKey: arbiQueryKeys.chatThread(chatExtId),\n queryFn: () => arbi.chats.page(chatRef.current!),\n enabled: !!chat && arbi.isLoggedIn,\n staleTime: Infinity,\n })\n const [loadingOlder, setLoadingOlder] = useState(false)\n\n const loadOlder = useCallback(async () => {\n const key = arbiQueryKeys.chatThread(chatExtId)\n const current = queryClient.getQueryData<ChatThreadData>(key)\n const oldest = current?.messages.find((m) => !m.optimistic)\n if (!chatRef.current || !current?.hasMore || !oldest) return\n setLoadingOlder(true)\n try {\n const page = await arbi.chats.page(chatRef.current, { before: oldest.external_id })\n queryClient.setQueryData<ChatThreadData>(key, (old) =>\n old\n ? {\n hasMore: page.hasMore,\n messages: [\n ...page.messages.filter(\n (m) => !old.messages.some((o) => o.external_id === m.external_id)\n ),\n ...old.messages,\n ],\n }\n : old\n )\n } finally {\n setLoadingOlder(false)\n }\n }, [arbi, queryClient, chatExtId])\n\n return {\n messages: query.data?.messages ?? [],\n hasMore: query.data?.hasMore ?? false,\n isLoading: query.isLoading && !!chat,\n loadOlder,\n loadingOlder,\n }\n}\n\n/** What to post: text, files and (PA chat only) the agent's workspace or a context note. */\nexport interface ChatPost {\n text: string\n files?: File[]\n /** PA chat only: the workspace my agent acts in. */\n workspaceExtId?: string\n /** PA chat only: a note the agent records without replying. */\n contextOnly?: boolean\n}\n\n/**\n * Post to a chat, rendering an optimistic copy at once and swapping in the server's row. With no\n * chat yet, `peerExtId`'s direct chat is opened (created) first. Files are encrypted with their\n * own keys and travel in a manifest under the chat key. A failure drops the optimistic row,\n * refreshes the list (a stale epoch re-keys on the next try) and rethrows.\n */\nexport function useChatPost() {\n const arbi = useArbi()\n const queryClient = useQueryClient()\n return useCallback(\n async (\n target: { chat: ChatResponse | null; peerExtId?: string | null },\n post: ChatPost\n ): Promise<{ chat: ChatResponse; message: chatOps.DecryptedChatMessage }> => {\n const me = myChatId(arbi)\n if (!me) throw new Error('No active session')\n let chat = target.chat\n if (!chat) {\n if (!target.peerExtId) throw new Error('Could not resolve the conversation')\n chat = await arbi.chats.openDirect(target.peerExtId)\n upsertChat(queryClient, chat)\n queryClient.setQueryData<ChatThreadData>(\n arbiQueryKeys.chatThread(chat.external_id),\n (old) => old ?? { messages: [], hasMore: false }\n )\n }\n const files = post.files ?? []\n const optimisticId = `optimistic-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`\n const now = new Date().toISOString()\n const optimistic: ChatThreadMessage = {\n external_id: optimisticId,\n chat_ext_id: chat.external_id,\n sender_ext_id: me,\n kind: 'text',\n content: post.text,\n key_version: chat.key_version,\n deleted: false,\n context_only: !!post.contextOnly,\n workspace_ext_id: post.workspaceExtId ?? null,\n created_at: now,\n updated_at: now,\n optimistic: true,\n }\n appendToThread(queryClient, chat.external_id, optimistic)\n try {\n let attachments: chatOps.ChatAttachmentFile[] = []\n if (files.length) {\n // Refuse before reading any file into memory.\n chatOps.checkChatAttachmentLimits(files)\n attachments = await arbi.chats.uploadAttachments(\n await Promise.all(\n files.map(async (file) => ({\n name: file.name,\n type: file.type,\n bytes: new Uint8Array(await file.arrayBuffer()),\n }))\n )\n )\n }\n const message = await arbi.chats.send(chat, post.text, {\n attachments,\n ...(post.workspaceExtId ? { workspaceExtId: post.workspaceExtId } : {}),\n contextOnly: !!post.contextOnly,\n })\n appendToThread(queryClient, chat.external_id, message, optimisticId)\n upsertChat(queryClient, {\n ...chat,\n last_message: message,\n last_message_at: message.created_at,\n })\n return { chat, message }\n } catch (err) {\n dropFromThread(queryClient, chat.external_id, optimisticId)\n void queryClient.invalidateQueries({ queryKey: arbiQueryKeys.chatList() })\n throw err\n }\n },\n [arbi, queryClient]\n )\n}\n\n/** Delete one of my messages: a tombstone in place at once, rolled back if the delete fails. */\nexport function useDeleteChatMessage() {\n const arbi = useArbi()\n const queryClient = useQueryClient()\n return useCallback(\n (chatExtId: string, messageExtId: string) =>\n deleteChatMessage(arbi, queryClient, chatExtId, messageExtId),\n [arbi, queryClient]\n )\n}\n\n/**\n * Move my read watermark in a chat to a message (or to now). The list shows it read at once; a\n * failure is ignored (the next open tries again).\n */\nexport function useMarkChatRead() {\n const arbi = useArbi()\n const queryClient = useQueryClient()\n return useCallback(\n (chat: ChatResponse, messageExtId?: string) => {\n upsertChat(queryClient, { ...chat, unread_count: 0 })\n return arbi.chats.markRead(chat.external_id, messageExtId).then(\n () => undefined,\n () => undefined\n )\n },\n [arbi, queryClient]\n )\n}\n\n/** Create a group (members need encryption keys; agents are refused) and add it to the list. */\nexport function useCreateGroupChat() {\n const arbi = useArbi()\n const queryClient = useQueryClient()\n return useMutation({\n mutationFn: (params: { title?: string | null; members: ChatMemberKey[] }) =>\n arbi.chats.createGroup(params),\n onSuccess: (chat) => upsertChat(queryClient, chat),\n })\n}\n\n/** Rename a group (the title is encrypted under the current epoch). */\nexport function useRenameChat() {\n const arbi = useArbi()\n const queryClient = useQueryClient()\n return useMutation({\n mutationFn: (vars: { chat: ChatResponse; title: string | null }) =>\n arbi.chats.rename(vars.chat, vars.title),\n onSuccess: (chat) => upsertChat(queryClient, chat),\n })\n}\n\n/** Add people to a group, or to a meeting chat with its call key (`callKey`). */\nexport function useAddChatMembers() {\n const arbi = useArbi()\n const queryClient = useQueryClient()\n return useMutation({\n mutationFn: (vars: {\n chat: ChatResponse\n members: ChatMemberKey[]\n callKey?: Uint8Array | null\n }) => arbi.chats.addMembers(vars.chat, vars.members, { callKey: vars.callKey }),\n onSuccess: (chat) => upsertChat(queryClient, chat),\n })\n}\n\n/**\n * Remove someone from a group (owner) or leave it (my own id). Leaving drops the chat at once;\n * a removal refreshes the list (the chat now has a new epoch).\n */\nexport function useRemoveChatMember() {\n const arbi = useArbi()\n const queryClient = useQueryClient()\n return useMutation({\n mutationFn: (vars: { chat: ChatResponse; userExtId: string }) =>\n arbi.chats.removeMember(vars.chat, vars.userExtId),\n onSuccess: (_data, vars) => {\n if (vars.userExtId === myChatId(arbi)) removeChat(queryClient, vars.chat.external_id)\n else return queryClient.invalidateQueries({ queryKey: arbiQueryKeys.chatList() })\n },\n })\n}\n","/**\n * Someone else's message arriving in one of my chats that is not open: what a host announces (a\n * toast pointing at the thread). Text messages only, never from a person I muted; no preview (the\n * text is end-to-end encrypted, the announcement stays a pointer). The chat cache itself follows\n * by itself (`<ArbiWebSocketProvider>` applies the event first).\n */\n\nimport { useQueryClient } from '@tanstack/react-query'\nimport type { WsChatMessageMessage } from '@arbidocs/client'\nimport { useArbi } from '../useArbi'\nimport { arbiQueryKeys } from '../query-keys'\nimport { useArbiWsMessage } from '../websocket/hooks'\nimport { cachedChat, getOpenChat, myChatId, type ChatResponse } from './chat-cache'\n\n/** A chat message to announce. */\nexport interface ChatArrival {\n chatId: string\n chat: ChatResponse | undefined\n /** The sender, when the chat list knows them. */\n sender: ChatResponse['members'][number]['user'] | undefined\n senderId: string\n /** Where \"Reply\" goes: the person for a direct chat, the chat otherwise. */\n replyTo: string\n}\n\n/** Call `onArrival` for each chat message to announce (see the module comment). */\nexport function useChatArrivals(onArrival: (arrival: ChatArrival) => void): void {\n const arbi = useArbi()\n const queryClient = useQueryClient()\n useArbiWsMessage<WsChatMessageMessage>('chat.message', (message) => {\n const senderId = message.message.sender_ext_id\n if (!senderId || senderId === myChatId(arbi)) return\n if (message.message.kind !== 'text' || getOpenChat() === message.chat_ext_id) return\n const muted = queryClient\n .getQueriesData<{ muted_users?: string[] }>({ queryKey: arbiQueryKeys.userSettings() })\n .map(([, data]) => data)\n .find(Boolean)?.muted_users\n if (muted?.includes(senderId)) return\n const chat = cachedChat(queryClient, message.chat_ext_id)\n const sender = chat?.members.find((m) => m.user.external_id === senderId)?.user\n onArrival({\n chatId: message.chat_ext_id,\n chat,\n sender,\n senderId,\n replyTo: chat?.kind === 'direct' ? senderId : message.chat_ext_id,\n })\n })\n}\n","/**\n * The day divider between message runs in a thread.\n *\n * The label is supplied by the caller rather than formatted here: the ARBI app\n * has a friendly formatter that already says \"Today\" / \"Yesterday\" in the user's\n * locale, and a second date-formatting opinion in the kit would drift from it.\n */\n\nimport type { ReactNode } from 'react'\n\nexport interface DateSeparatorProps {\n children: ReactNode\n}\n\nexport function DateSeparator({ children }: DateSeparatorProps) {\n return (\n <div className=\"my-3 flex justify-center\" data-testid=\"dm-date-separator\">\n <span className=\"rounded-full bg-background/80 px-2 py-0.5 text-xs text-muted-foreground\">\n {children}\n </span>\n </div>\n )\n}\n","/**\n * Thread grouping: the two annotations a readable message list needs.\n *\n * A run is a burst from one sender close together in time; only its last\n * message carries the meta row (sender, time, receipt), so ten rapid messages\n * read as one block instead of ten stamped rows. A day boundary gets a\n * separator so a thread spanning weeks stays navigable.\n *\n * Generic over the message shape because the two consumers hold different ones —\n * the block's `DmMessage` and the ARBI app's decrypted notification rows — and\n * duplicating this logic is exactly how they drifted apart before.\n */\n\n/** Two messages belong to the same run when same sender and within this gap. */\nexport const RUN_WINDOW_MS = 2 * 60 * 1000\n\nexport interface ThreadItem<T> {\n message: T\n /** Last of a same-sender run: render the meta row here. */\n isLastOfRun: boolean\n /** First message on its calendar day: render a date separator above it. */\n isFirstOfDay: boolean\n}\n\nexport interface ThreadAccessors<T> {\n senderId: (message: T) => string\n createdAt: (message: T) => string\n}\n\n/**\n * Local calendar day for a timestamp.\n *\n * Deliberately local rather than UTC: a message sent at 23:30 in the reader's\n * zone belongs under that day's separator, not tomorrow's. Falls back to the\n * raw string for an unparseable timestamp so such a message still buckets\n * consistently with itself rather than joining an arbitrary day.\n */\nexport function dayKey(iso: string): string {\n const d = new Date(iso)\n if (Number.isNaN(d.getTime())) return iso\n return `${d.getFullYear()}-${d.getMonth() + 1}-${d.getDate()}`\n}\n\n/** Annotate messages (ascending time order) with run and day boundaries. */\nexport function annotateThread<T>(\n messages: T[],\n accessors: ThreadAccessors<T>,\n runWindowMs: number = RUN_WINDOW_MS\n): ThreadItem<T>[] {\n const { senderId, createdAt } = accessors\n return messages.map((message, i) => {\n const next = messages[i + 1]\n const prev = messages[i - 1]\n const day = dayKey(createdAt(message))\n\n const continuesIntoNext =\n !!next &&\n senderId(next) === senderId(message) &&\n dayKey(createdAt(next)) === day &&\n Date.parse(createdAt(next)) - Date.parse(createdAt(message)) < runWindowMs\n\n return {\n message,\n isLastOfRun: !continuesIntoNext,\n isFirstOfDay: !prev || dayKey(createdAt(prev)) !== day,\n }\n })\n}\n","/**\n * ImageCropper — a themeable pan/zoom crop surface (react-easy-crop) with an\n * optional aspect-ratio picker. Reports the chosen crop rectangle (in source\n * pixels) via `onCropComplete`; pair it with {@link cropImage} to export.\n *\n * react-easy-crop always constrains to a fixed aspect (you move the image under\n * a fixed frame), so \"change the aspect ratio\" is a discrete ratio picker, not\n * free-form rectangle dragging.\n */\n\nimport { useCallback, useEffect, useState } from 'react'\nimport Cropper, { type Area } from 'react-easy-crop'\nimport { Slider } from '../ui/slider'\nimport { cn } from '../lib/utils'\nimport type { CropArea } from './cropImage'\n\n/** A selectable aspect ratio (width / height). */\nexport interface AspectOption {\n label: string\n value: number\n}\n\n/** A sensible default ratio set (square, landscape, portrait, wide, tall). */\nexport const DEFAULT_ASPECT_OPTIONS: AspectOption[] = [\n { label: '1:1', value: 1 },\n { label: '4:3', value: 4 / 3 },\n { label: '3:4', value: 3 / 4 },\n { label: '16:9', value: 16 / 9 },\n { label: '9:16', value: 9 / 16 },\n]\n\nexport interface ImageCropperProps {\n image: string\n /** Fixed aspect ratio (w/h). Default 1. Ignored once the user picks from `aspectOptions`. */\n aspect?: number\n /** Show a ratio picker with these options (first is the initial selection). */\n aspectOptions?: AspectOption[]\n cropShape?: 'rect' | 'round'\n minZoom?: number\n maxZoom?: number\n className?: string\n /** Classes for the image area, e.g. a taller height than the default `h-72`. */\n cropAreaClassName?: string\n /** The crop rectangle (source pixels) + the active aspect, on every change. */\n onCropComplete?: (area: CropArea, aspect: number) => void\n}\n\nexport function ImageCropper({\n image,\n aspect = 1,\n aspectOptions,\n cropShape = 'rect',\n minZoom = 1,\n maxZoom = 3,\n className,\n cropAreaClassName,\n onCropComplete,\n}: ImageCropperProps) {\n const [crop, setCrop] = useState({ x: 0, y: 0 })\n const [zoom, setZoom] = useState(1)\n const [activeAspect, setActiveAspect] = useState(aspectOptions?.[0]?.value ?? aspect)\n\n // Keep the reported aspect in sync when the caller changes the fixed `aspect`.\n useEffect(() => {\n if (!aspectOptions) setActiveAspect(aspect)\n }, [aspect, aspectOptions])\n\n const handleComplete = useCallback(\n (_: Area, areaPixels: Area) => {\n onCropComplete?.(areaPixels, activeAspect)\n },\n [onCropComplete, activeAspect]\n )\n\n return (\n <div className={cn('flex flex-col gap-3', className)}>\n <div\n className={cn(\n 'relative h-72 w-full overflow-hidden rounded-md bg-foreground/95',\n cropAreaClassName\n )}\n >\n <Cropper\n image={image}\n crop={crop}\n zoom={zoom}\n aspect={activeAspect}\n cropShape={cropShape}\n showGrid={cropShape === 'rect'}\n onCropChange={setCrop}\n onZoomChange={setZoom}\n onCropComplete={handleComplete}\n objectFit=\"contain\"\n />\n </div>\n\n {aspectOptions && aspectOptions.length > 1 ? (\n <div className=\"flex flex-wrap items-center gap-1\" data-testid=\"image-cropper-aspects\">\n <span className=\"mr-1 text-xs font-semibold uppercase tracking-wider text-muted-foreground\">\n Ratio\n </span>\n {aspectOptions.map((opt) => {\n const on = opt.value === activeAspect\n return (\n <button\n key={opt.label}\n type=\"button\"\n onClick={() => setActiveAspect(opt.value)}\n data-testid={`image-cropper-aspect-${opt.label}`}\n className={cn(\n 'rounded-md px-2 py-1 text-xs font-medium transition-colors',\n on\n ? 'bg-primary text-primary-foreground'\n : 'text-muted-foreground hover:bg-accent hover:text-foreground'\n )}\n >\n {opt.label}\n </button>\n )\n })}\n </div>\n ) : null}\n\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-semibold uppercase tracking-wider text-muted-foreground\">\n Zoom\n </label>\n <Slider\n value={[zoom]}\n onValueChange={([v]) => setZoom(v ?? 1)}\n min={minZoom}\n max={maxZoom}\n step={0.01}\n />\n </div>\n </div>\n )\n}\n","/**\n * Crop a region of an image to a canvas and export it — the shared engine\n * behind every \"frame this image\" surface (avatars, builder image fields, …).\n *\n * `area` is the pixel rectangle react-easy-crop reports (`onCropComplete`'s\n * second arg). Output is rectangular (a round crop is a UI overlay only — JPEG\n * has no alpha), optionally downscaled so the longest edge fits `maxSize`.\n */\n\n/** Pixel crop rectangle in the source image's natural coordinates. */\nexport interface CropArea {\n x: number\n y: number\n width: number\n height: number\n}\n\nexport interface CropOutput {\n /** Cap the longest output edge to this many px (preserves aspect). Omit = native crop size. */\n maxSize?: number\n /** Output MIME type. Default `image/jpeg`. */\n mimeType?: string\n /** Quality for lossy formats, 0..1. Default 0.9. */\n quality?: number\n /** Background painted before the crop (JPEG has no alpha). Default `#ffffff`. */\n background?: string\n}\n\nexport interface CropResult {\n dataUrl: string\n blob: Blob\n width: number\n height: number\n}\n\nfunction loadImage(src: string): Promise<HTMLImageElement> {\n return new Promise((resolve, reject) => {\n const img = new Image()\n // Allow exporting cross-origin images the server marks CORS-safe; harmless for data/blob URLs.\n img.crossOrigin = 'anonymous'\n img.onload = () => resolve(img)\n img.onerror = () => reject(new Error('Failed to load image for cropping'))\n img.src = src\n })\n}\n\nexport async function cropImage(\n imageSrc: string,\n area: CropArea,\n output: CropOutput = {}\n): Promise<CropResult> {\n const { maxSize, mimeType = 'image/jpeg', quality = 0.9, background = '#ffffff' } = output\n const img = await loadImage(imageSrc)\n\n let outW = Math.max(1, Math.round(area.width))\n let outH = Math.max(1, Math.round(area.height))\n if (maxSize && Math.max(outW, outH) > maxSize) {\n const scale = maxSize / Math.max(outW, outH)\n outW = Math.max(1, Math.round(outW * scale))\n outH = Math.max(1, Math.round(outH * scale))\n }\n\n const canvas = document.createElement('canvas')\n canvas.width = outW\n canvas.height = outH\n const ctx = canvas.getContext('2d')\n if (!ctx) throw new Error('canvas 2d context unavailable')\n\n if (mimeType === 'image/jpeg') {\n ctx.fillStyle = background\n ctx.fillRect(0, 0, outW, outH)\n }\n ctx.drawImage(img, area.x, area.y, area.width, area.height, 0, 0, outW, outH)\n\n const dataUrl = canvas.toDataURL(mimeType, quality)\n const blob = await new Promise<Blob>((resolve, reject) =>\n canvas.toBlob(\n (b) => (b ? resolve(b) : reject(new Error('canvas toBlob returned null'))),\n mimeType,\n quality\n )\n )\n return { dataUrl, blob, width: outW, height: outH }\n}\n","/**\n * ImageCropModal — a turnkey crop dialog. Wraps {@link ImageCropper} with\n * Save/Cancel and runs {@link cropImage} on save, handing the caller the full\n * result (both a `dataUrl` and a `blob`, plus dimensions) so it can inline a\n * small avatar or upload a larger asset as it sees fit.\n */\n\nimport { useState } from 'react'\nimport { Loader2 } from 'lucide-react'\nimport { Button } from '../ui/button'\nimport { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from '../ui/dialog'\nimport { cropImage, type CropArea, type CropOutput, type CropResult } from './cropImage'\nimport { ImageCropper, type AspectOption } from './ImageCropper'\n\nexport interface ImageCropModalProps {\n open: boolean\n image: string | null\n title?: string\n saveLabel?: string\n aspect?: number\n aspectOptions?: AspectOption[]\n cropShape?: 'rect' | 'round'\n /** Export options (max size, mime, quality). */\n output?: CropOutput\n /** Called with the exported crop on save. */\n onComplete: (result: CropResult) => void | Promise<void>\n onCancel: () => void\n}\n\nexport function ImageCropModal({\n open,\n image,\n title = 'Crop image',\n saveLabel = 'Save',\n aspect,\n aspectOptions,\n cropShape = 'rect',\n output,\n onComplete,\n onCancel,\n}: ImageCropModalProps) {\n const [area, setArea] = useState<CropArea | null>(null)\n const [busy, setBusy] = useState(false)\n\n const handleSave = async () => {\n if (!image || !area) return\n setBusy(true)\n try {\n const result = await cropImage(image, area, output)\n await onComplete(result)\n } finally {\n setBusy(false)\n }\n }\n\n return (\n <Dialog open={open} onOpenChange={(next) => (!next ? onCancel() : undefined)}>\n <DialogContent className=\"sm:max-w-md\" data-testid=\"image-crop-modal\">\n <DialogHeader>\n <DialogTitle>{title}</DialogTitle>\n </DialogHeader>\n\n {image ? (\n <ImageCropper\n image={image}\n aspect={aspect}\n aspectOptions={aspectOptions}\n cropShape={cropShape}\n onCropComplete={setArea}\n />\n ) : null}\n\n <DialogFooter className=\"gap-2 sm:gap-2\">\n <Button variant=\"ghost\" onClick={onCancel} disabled={busy}>\n Cancel\n </Button>\n <Button onClick={handleSave} disabled={!area || busy} data-testid=\"image-crop-save\">\n {busy ? <Loader2 className=\"mr-1 size-4 animate-spin\" /> : null}\n {saveLabel}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )\n}\n","/**\n * Remote control's session state and its websocket message: an `agt-…` assistant asks to drive\n * the UI over the live connection (`remote_control`), and the user's consent decides whether it\n * may. The guided run itself (the cursor, the clicks) is `@arbidocs/blocks`' (`createRemoteControl`).\n *\n * GUARANTEE #1: `enabled` is `false` at the start of EVERY session and is NEVER saved. The state is\n * a transient view of the session's layout (`views.transient`), which the layout never saves. Every\n * sign-in and sign-out drops it: `@arbidocs/blocks`' remote control resets it (`reset`) on the\n * host's sign-in, sign-out, expiry and change of user, on every host, and a host's own\n * `resetLayout` drops it too.\n *\n * The actions here are pure state. Running the requested run (and labelling the driver for its\n * duration) is the orchestration layer's.\n *\n * ── BACKEND WS CONTRACT ──────────────────────────────────────────────────────\n * Message `type`: `'remote_control'`. Payload (snake_case, matching the other WS messages):\n * {\n * type: 'remote_control',\n * agent_name: string, // display name of the requesting agent\n * agent_ext_id?: string, // the agent's `agt-…` external id\n * sequence_id?: string, // a REGISTERED guided-run id\n * steps?: GuidedStep[], // OR an inline guided run (target-based)\n * }\n * Exactly one of `sequence_id` / `steps` is expected. An unknown `sequence_id`, a `steps` list with\n * no valid target, and an empty/absent run are all ignored.\n */\nimport type { components } from '@arbidocs/client'\nimport { logger } from '@arbidocs/client'\nimport type { ArbiSessionState, ArbiSessionStore } from './session'\nimport { useArbiSessionState } from './session'\n\n/** The websocket message: an `agt-…` agent asks to drive the UI (exactly one of `sequence_id` /\n * `steps`). The generated schema type is the single source of truth. */\nexport type RemoteControlMessage = components['schemas']['RemoteControlMessage']\n/** One guided-cursor step, as on the wire (nullable JSON fields). */\ntype RemoteControlStep = components['schemas']['RemoteControlStep']\n\n/** One UI operation: glide the cursor to `target`, then perform `do` on it. */\nexport interface GuidedStep {\n /** `[data-testid=...]` (or any CSS selector) the cursor glides to and acts on. */\n target: string\n /** Interaction once the cursor arrives. Defaults to 'click'. */\n do?: 'click' | 'type'\n /** Text to type for `do: 'type'`. */\n value?: string\n /** Narration toast shown when the step runs. */\n note?: string\n /** Pause (ms) AFTER this step, before the next. */\n pauseMs?: number\n /** Max ms to wait for the target to appear (it may follow a prior step). */\n waitMs?: number\n}\n\n/** A remote-control run requested by a backend agent (name always present so the consent prompt\n * can name who is asking — GUARANTEE #3). Carries either a registered `sequenceId` or an inline\n * `steps` list to execute. */\nexport interface RemoteControlRequest {\n /** Display name of the requesting assistant, e.g. \"Research Assistant\". */\n agentName: string\n /** The assistant's `agt-…` external id, shown so the user knows which agent. */\n agentExtId?: string\n /** A registered guided-run id to execute. */\n sequenceId?: string\n /** An ad-hoc guided run to execute (used when no registered sequence fits). */\n steps?: GuidedStep[]\n}\n\n/** The agent whose run is actively executing — drives the \"controlling\" banner. */\nexport interface ControllingAgent {\n name: string\n extId?: string\n}\n\n/** Session-only remote-control state (never saved — see the file header). */\nexport interface RemoteControlState {\n /** Whether WS-driven runs may execute without re-prompting this session. */\n enabled: boolean\n /** The in-flight consent request awaiting the user's decision, or null. */\n pending: RemoteControlRequest | null\n /** Set while a WS-driven run is actively executing (labels the banner). */\n controllingAgent: ControllingAgent | null\n}\n\n/** The session the state lives in. */\nexport type RemoteControlSession = Pick<ArbiSessionStore, 'getState' | 'setTransientView'>\n\n/** The transient view that holds the state. */\nexport const REMOTE_CONTROL_VIEW = 'actions.remoteControl'\nconst OFF: RemoteControlState = { enabled: false, pending: null, controllingAgent: null }\n\n/** The remote-control state of a session state. */\nexport const remoteControlStateOf = (state: Pick<ArbiSessionState, 'views'>): RemoteControlState =>\n (state.views.transient[REMOTE_CONTROL_VIEW] as RemoteControlState | undefined) ?? OFF\n\n/** A slice of the remote-control state of the host's session; re-renders when it changes. */\nexport function useRemoteControl<T>(selector: (state: RemoteControlState) => T): T {\n return useArbiSessionState((state) => selector(remoteControlStateOf(state)))\n}\n\n/** The state's actions on a session. */\nexport function remoteControlActions(session: RemoteControlSession) {\n const update = (change: (state: RemoteControlState) => Partial<RemoteControlState>): void => {\n const state = remoteControlStateOf(session.getState())\n session.setTransientView(REMOTE_CONTROL_VIEW, { ...state, ...change(state) })\n }\n return {\n /** Stash a requested run and open the consent prompt (`pending` set). */\n request: (req: RemoteControlRequest): void => update(() => ({ pending: req })),\n /** Resolve the pending request: `forSession` enables it for the whole session; either way\n * the pending request is cleared. Running it is the caller's job. */\n grant: ({ forSession }: { forSession: boolean }): void =>\n update((state) => ({ enabled: forSession || state.enabled, pending: null })),\n /** Reject the pending request — clears it, changes nothing else. */\n deny: (): void => update(() => ({ pending: null })),\n /** Directly set the session enabled flag. Turning it OFF revokes immediately: clears any\n * pending prompt and the controlling banner (GUARANTEE #5). */\n setEnabled: (enabled: boolean): void =>\n update(() => (enabled ? { enabled } : { enabled, pending: null, controllingAgent: null })),\n /** Set (or clear) the agent whose run is currently executing. */\n setControllingAgent: (agent: ControllingAgent | null): void =>\n update(() => ({ controllingAgent: agent })),\n /** Back to the session start: off, nothing pending, nobody driving (a sign-in or sign-out). */\n reset: (): void => session.setTransientView(REMOTE_CONTROL_VIEW, undefined),\n }\n}\n\n/** A runnable steps list: a non-empty array whose every step has a real target selector — the\n * one field the runner cannot act without. Operates on the wire step (nullable JSON fields). */\nfunction hasRunnableSteps(\n steps: RemoteControlStep[] | null | undefined\n): steps is RemoteControlStep[] {\n return (\n Array.isArray(steps) &&\n steps.length > 0 &&\n steps.every((s) => typeof s?.target === 'string' && s.target.length > 0)\n )\n}\n\n/** Normalise wire steps (nullable JSON fields) into plain optionals — a `null` off the socket\n * becomes an absent field. */\nfunction toGuidedSteps(steps: RemoteControlStep[]): GuidedStep[] {\n return steps.map((s) => ({\n target: s.target,\n do: s.do ?? undefined,\n value: s.value ?? undefined,\n note: s.note ?? undefined,\n pauseMs: s.pauseMs ?? undefined,\n waitMs: s.waitMs ?? undefined,\n }))\n}\n\n/**\n * Narrow an incoming message into a request, or null if nothing is runnable: inline steps that\n * all have a target, or a `sequence_id` the site registered (`isSequenceId`).\n */\nexport function toRemoteControlRequest(\n msg: RemoteControlMessage,\n isSequenceId: (id: string) => boolean\n): RemoteControlRequest | null {\n const steps = hasRunnableSteps(msg.steps) ? toGuidedSteps(msg.steps) : undefined\n const sequenceId =\n typeof msg.sequence_id === 'string' && isSequenceId(msg.sequence_id)\n ? msg.sequence_id\n : undefined\n if (!steps && !sequenceId) {\n logger.warn('[RemoteControl] Ignoring message with no runnable action', msg.sequence_id)\n return null\n }\n return {\n // The agent is always named in the prompt; fall back to a neutral label rather than leaving\n // the consent dialog anonymous.\n agentName: msg.agent_name.trim() || 'An assistant',\n agentExtId: msg.agent_ext_id ?? undefined,\n sequenceId,\n steps,\n }\n}\n","/** Personal support resources. Workspace switching never changes ticket ownership. */\nimport { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'\nimport type { SupportRating } from '@arbidocs/sdk/browser'\nimport { useArbi } from '../useArbi'\nimport { arbiQueryKeys } from '../query-keys'\n\nexport function useSupportTickets(options: { enabled?: boolean } = {}) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.supportTickets(),\n queryFn: () => arbi.support.list(),\n enabled: (options.enabled ?? true) && arbi.isLoggedIn,\n refetchInterval: 15000,\n })\n}\nexport function useSupportTicket(\n ticketId: number | undefined,\n options: { enabled?: boolean } = {}\n) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.supportTicket(ticketId ?? 0),\n queryFn: () => arbi.support.get(ticketId ?? 0),\n enabled: (options.enabled ?? true) && ticketId !== undefined && arbi.isLoggedIn,\n refetchInterval: 15000,\n })\n}\nexport function useRateSupportTicket() {\n const arbi = useArbi()\n const queries = useQueryClient()\n return useMutation({\n mutationFn: ({ ticketId, rating }: { ticketId: number; rating: SupportRating }) =>\n arbi.support.rate(ticketId, rating),\n onSuccess: () => queries.invalidateQueries({ queryKey: arbiQueryKeys.allSupportTickets() }),\n })\n}\n"]}
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/index.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * @arbidocs/react \u2014 React hooks and provider for the ARBI SDK.\n *\n * Usage:\n * import { ArbiHost, useArbi, useWorkspaces, useDocuments } from '@arbidocs/react'\n * <ArbiHost config={{ arbi }}><App /></ArbiHost>\n *\n * Chat page controller (UI in @arbidocs/blocks/chat):\n * const chat = useConversation({ workspaceId })\n */\n\n// The host configuration: one `<ArbiHost config>` for every hook and kit\nexport {\n ArbiHost,\n mergeHostConfig,\n useArbiHost,\n type ArbiHostConfig,\n type ArbiHostConnection,\n type ArbiHostProps,\n type AccountHost,\n type MailHost,\n type CallsHost,\n type CallSlotMode,\n} from './host'\n// Features the user switches on or off (the user's settings, or this device): `useFeature(name)`\nexport {\n createLocalFeatureStore,\n readLocalFeature,\n useFeature,\n useFeatureCheck,\n useFeatureSwitch,\n type ArbiFeature,\n type ArbiFeatures,\n type FeatureSource,\n type FeatureSwitch,\n type LocalFeatureStore,\n type LocalFeatureStoreOptions,\n type UserSettingFlag,\n} from './host/features'\nexport { useHostConfigRecord, type HostConfigRecord } from './host/context'\nexport * from './host/assistant-copy'\n\n// The chat engine as one hook: threads, messages, grounding documents (UI: `ChatPage` in\n// @arbidocs/blocks/chat), and the scope a surface keeps its own open conversation in\nexport {\n useConversation,\n workflowStepOf,\n titleFromQuestion,\n type ArbiConversation,\n type ArbiChatCitation,\n type ArbiChatDocument,\n type ArbiChatMessage,\n type ArbiChatMessageStatus,\n type ArbiChatPassage,\n type ArbiChatRole,\n type ArbiChatThread,\n type UseConversationOptions,\n} from './chat/useConversation'\nexport { ConversationScope, type ConversationScopeProps } from './chat/ConversationScope'\n// An untitled saved-workflow run's name (its workflow and day), as every thread list shows it\nexport { workflowRunTitle } from './chat/workflow-run-titles'\n// The workspace a conversation is in (a fact saved from its answer goes there)\nexport { useConversationWorkspace } from './chat/useConversationWorkspace'\nexport { toChatCitations } from './chat/citations'\n// A conversation's threads in the cache, and their writers (the chat engine's and the events')\nexport * from './chat/conversation-cache'\nexport * from './chat/conversation-events'\nexport * from './chat/run-state'\nexport * from './chat/stream-handlers'\nexport * from './chat/mentions'\nexport * from './chat/open-document'\nexport * from './chat/chat-artifacts'\nexport * from './chat/thread-document'\nexport * from './chat/thread-binding'\nexport * from './chat/useThreadDocument'\nexport * from './chat/conversation-mentions'\nexport { resolveConfigModel } from './chat/config-model'\nexport { useDeleteMessage } from './chat/useDeleteMessage'\nexport {\n formatConfigValidationError,\n isFullConfig,\n useApplyChatModel,\n pendingChatModelSave,\n AUTO_CHAT_MODEL,\n useConfigSchema,\n useDeleteConfig,\n useSaveConfig,\n useSaveConfigField,\n type ConfigUpdate,\n} from './config/config-hooks'\nexport { useConversationTurn } from './chat/useConversationTurn'\nexport { useActiveConfigId } from './chat/active-config'\nexport { useConversationDocuments } from './chat/useConversationDocuments'\nexport { useDocumentAutoAdd } from './chat/useDocumentAutoAdd'\nexport { useAutoSendDraft } from './chat/useAutoSendDraft'\nexport { getOrphanedLastMessage, isOrphanedUserMessage } from './chat/orphaned'\nexport { buildPendingFirstTurn } from './chat/pendingFirstTurn'\nexport { useAnswerAgentQuestion, type AgentQuestionRef } from './chat/useAnswerAgentQuestion'\nexport * from './chat/turn-control'\nexport * from './chat/reply-target'\nexport * from './chat/useConversationActions'\nexport * from './chat/useConnectRunStream'\nexport * from './chat/useConversationData'\nexport * from './chat/useConversationSettings'\nexport * from './chat/useBranchNavigation'\nexport * from './chat/useAskAgain'\nexport * from './chat/useThinkingContent'\nexport * from './chat/useMessageTimer'\nexport * from './chat/useAgentRunControl'\nexport type { ArbiChatHost, ArbiThreadView } from './chat/host'\n\n// Chat message bubble (props-in; host injects markdown renderer + timestamp fmt)\nexport { ChatBubble, TypingIndicator, type ChatBubbleProps } from './chat/ChatBubble'\n\n// Context hook\nexport { useArbi, useDeploymentDomain } from './useArbi'\nexport { BOOT_GATE_TIMEOUT_MS, useBootTimeout } from './boot-timeout'\nexport {\n useInstallSkillPack,\n createSkillPack,\n type CreateSkillPackOptions,\n type SkillPack,\n type SkillPackEntry,\n type InstallSkillPackVariables,\n} from './useInstallSkillPack'\nexport {\n defineSkillPack,\n skillPackPrompt,\n type DefineSkillPackOptions,\n type DefinedSkillPack,\n type SkillPackField,\n type SkillPackSkill,\n type SkillPackSkillDefinition,\n} from './skill-pack'\n\n// Online or not: the network, the live connection and \"Work offline\" (run by the provider)\nexport {\n computeOnline,\n isWorkingOffline,\n setWorkOfflineIn,\n useReconnect,\n useWorkOffline,\n WORK_OFFLINE_VIEW,\n type ReconnectOutcome,\n} from './connectivity'\n\n// Shared WebSocket layer (one reconnecting socket, canonical store, typed\n// subscriptions, drop-in document sync \u2014 the real-time layer both apps share)\nexport {\n ArbiWebSocketProvider,\n useArbiWsContext,\n type ArbiWebSocketProviderProps,\n type ArbiWsHandlers,\n useArbiWebSocket,\n useArbiWsMessage,\n useArbiWsStatus,\n applyLiveUpdate,\n LIVE_UPDATE_TYPES,\n useArbiWsStore,\n DISMISSED_TASK_TTL_MS,\n type LiveTask,\n type ArbiWsState,\n type ArbiWsStatus,\n} from './websocket'\n\n// Schema-typed WebSocket messages + the discriminant type guard (so consumers\n// narrow handlers exactly like the rest of the SDK).\nexport { isMessageType } from '@arbidocs/client'\nexport type {\n WebSocketServerMessage,\n WsTaskUpdateMessage,\n WsBatchCompleteMessage,\n WsPresenceUpdateMessage,\n WsResponseCompleteMessage,\n WsConversationMessagePostedMessage,\n WsNotificationResponse,\n} from '@arbidocs/client'\n\n// Workspaces as the shell and the gallery show them (adapters, active workspace, open)\nexport * from './workspaces'\n\n// React Query hooks\nexport {\n useWorkspaces,\n useDocumentVersionList,\n useThumbnails,\n useParsedDocument,\n useConversations,\n useConversationThreads,\n useMessageDetails,\n useBuiltinCommands,\n useTags,\n useAgents,\n useDeleteAgents,\n useAssistantQuery,\n useHealth,\n useAvailableModels,\n useConfigs,\n useConfig,\n useActivity,\n useWorkspaceActivity,\n useProjects,\n useProjectUsage,\n useProjectInvoices,\n useUserUsageToday,\n useCurrentUser,\n useCanCreateProjects,\n useBoxRole,\n PROJECT_CREATION_DENIED_REASON,\n} from './hooks'\n// The one query-key factory (and its prefix match): every key the packages and hosts use.\nexport { arbiQueryKeys, arbiMutationKeys, isUnderQueryKey } from './query-keys'\n\n// Workspace facts\nexport {\n useFacts,\n useCreateFact,\n useCreateFacts,\n useUpdateFact,\n useDeleteFact,\n useSearchFacts,\n type FactListFilter,\n} from './facts'\nexport {\n useFactsSearch,\n FACTS_SEARCH_VIEW,\n type FactSearchHit,\n type FactsSearch,\n type FactsSearchState,\n type UseFactsSearchOptions,\n} from './facts-search'\n\n// Work (conversations with a status), workflows, agents, skills (mutations invalidate through arbiQueryKeys)\nexport {\n useUpdateConversation,\n useCreateWork,\n useRunConversation,\n usePlanWork,\n useActOnStep,\n useConversationPendingAuth,\n useWorkflows,\n useWorkflowRuns,\n useCreateWorkflow,\n useUpdateWorkflow,\n useDeleteWorkflow,\n useRunWorkflow,\n useCreateAgent,\n useGenerateAgentAvatar,\n useAuthorizeLimits,\n useMcpTools,\n useAgentConfig,\n useAgentModels,\n useSaveAgentConfig,\n useAgentWorkspaces,\n useGrantAgentAccess,\n useRevokeAgentAccess,\n useSkills,\n useSkillSource,\n useDeleteSkill,\n useSaveSkill,\n useSetSkillVisibility,\n useUploadSkillFiles,\n useConversationActivity,\n useConversationItems,\n useConversationIsShared,\n useWorkItems,\n useWorkspaceRole,\n useCanEditShared,\n useIsWorkspaceOwner,\n useStartTaskQuery,\n useDeleteConversation,\n useConversationSearch,\n TaskThreadPendingError,\n isActivityKey,\n invalidateConversationActivity,\n type StartTaskQuery,\n type AgentConfigSections,\n type SaveAgentConfigVars,\n type AgentAccessMode,\n type GrantAgentAccessVars,\n} from './workforce'\n\n// The workspace's conversation list in the cache: its writers (patch, add, remove) and readers\nexport * from './conversation-list'\n\n// Databases: user-defined tables of the open workspace (reads, writes, imports, export)\nexport * from './databases'\n// Saved table views (user settings `tableviews`): a grid's columns, read by charts too\nexport {\n isTableViewOf,\n viewsOfTable,\n type TableView,\n type TableViewTable,\n} from './account/table-views'\n// Datasets: data source adapters (usage, documents, threads, projects, databases) returning one\n// normalized dataset, the chart / panel / dashboard specs, and saved dashboards\nexport * from './datasets'\n\n// Tags: the writes (patching the workspace's list), and kinds' fields (a table's columns)\nexport {\n useCreateTag,\n useIsCreatingTag,\n useUpdateTag,\n useDeleteTag,\n useExtractEntities,\n useTagKindSchema,\n useUpdateTagKindSchema,\n useSetTagValues,\n useInvalidateTagData,\n invalidateTagData,\n invalidateTagTables,\n patchWorkspaceTags,\n type CreateTagInput,\n} from './tags'\n\n// Cited passages' text, read live from their documents' parsed content\nexport {\n usePassageQuotes,\n type PassageResolvers,\n type QuoteResolver,\n type OrderResolver,\n} from './documents/usePassageQuotes'\n\n// The shared React Query client, and the offline cache it may keep on this device (opt in)\nexport {\n createArbiQueryClient,\n type ArbiQueryClient,\n type ArbiQueryClientOptions,\n} from './query-client'\nexport { claimOfflineQueue, type ArbiQueryPersistOptions } from './query-persist'\n// Offline writes kept across a reload (opt in: a host with a persisted query cache)\nexport { registerArbiMutationDefaults, isReplayableArbiMutation } from './offline'\n// Telling \"no connection\" from a server's answer (a request that never reached the server)\nexport { isNetworkFailure } from './offline-store/network'\n\n// Project details, their events, and spend by conversation and step\nexport { useUpdateProjectFields, useProjectConversationUsage } from './projects'\nexport * from './billing'\n// Storage: usage by project, kind and workspace, the largest items, Recently deleted, trash actions\nexport * from './storage'\n\n// Contacts\nexport {\n useContacts,\n useInviteContacts,\n useCreateContact,\n useUpdateContact,\n useLinkContact,\n useImportContacts,\n useDeleteContact,\n useSearchContacts,\n} from './contacts'\n// The people directory: who an account id or an address is (contacts, workspace members, agents)\nexport {\n peopleDirectory,\n personOfUser,\n usePeople,\n usePeopleSearch,\n type PeopleDirectory,\n type Person,\n type UserResponse,\n} from './people'\n\n// The Word house template a workspace may choose\nexport {\n useHouseTemplateCandidates,\n useSetWorkspaceHouseTemplate,\n useSetDeploymentHouseTemplate,\n supportsHouseTemplates,\n workspaceHouseTemplateId,\n isDeploymentAdmin,\n} from './house-template'\n\n// The main agent's model connections (box and personal) and the direct model usage\nexport {\n useModelConnections,\n useDirectModelUsage,\n useSaveModelConnection,\n useRemoveModelConnection,\n useUnlockModelConnections,\n} from './model-connections'\nexport type {\n ConnectionModel,\n DirectModelUsage,\n ModelConnection,\n PersonalConnectionInput,\n} from '@arbidocs/sdk/browser'\n\n// Account and settings: profile, email, password, notification preferences, sessions, deletion\nexport * from './account'\n\n// Mail: the native inbox and connected accounts (client, provider, hooks)\nexport * from './mail'\n\n// Calendar: hooks over arbi.calendar, and the host's offline storage and connector OAuth\nexport * from './calendar'\n// Calls without LiveKit: data, the call session and events, actions, meeting chats, recordings\nexport * from './calls'\n\n// AI usage is reported in \u00A3 (ex VAT): one formatter for every amount\nexport {\n formatGbp,\n formatGbpPerMillionTokens,\n usdToGbp,\n DEFAULT_AI_USD_PER_GBP,\n} from '@arbidocs/sdk/browser'\nexport { isUsageMetered, type UsageTotals } from './usage-metered'\n\n// Re-export key types from core (browser-safe)\nexport { Arbi, type ArbiOptions, type AskRequest, type AskHandlers } from '@arbidocs/sdk/browser'\nexport type {\n ActivityKind,\n ActivityResponse,\n AuthMode,\n ConversationResponse,\n CreateWorkRequest,\n CreateWorkflowRequest,\n PendingAuthResponse,\n PlanWorkRequest,\n TaskPlan,\n UpdateConversationRequest,\n UpdateWorkflowRequest,\n WorkStatus,\n WorkflowAuthMode,\n WorkflowResponse,\n WorkflowRunResponse,\n SkillSummary,\n FactResponse,\n CreateFactRequest,\n FactSearchRequest,\n FactSearchResponse,\n ProjectUsageResponse,\n ProjectInvoicesResponse,\n UserDailyUsageResponse,\n LoginProfile,\n} from '@arbidocs/sdk/browser'\nexport type { SSEStreamResult, SSEStreamCallbacks } from '@arbidocs/sdk/browser'\nexport type {\n ResponseCreatedEvent,\n ResponseCompletedEvent,\n ResponseFailedEvent,\n ResponseOutputTextDeltaEvent,\n ResponseOutputTextDoneEvent,\n ResponseOutputItemAddedEvent,\n ResponseOutputItemDoneEvent,\n ResponseContentPartAddedEvent,\n ResponseUsage,\n OutputTokensDetails,\n AgentStepEvent,\n UserInputRequestEvent,\n ArtifactEvent,\n UserMessageEvent,\n MessageMetadataPayload,\n SSEStreamStartData,\n} from '@arbidocs/sdk/browser'\nexport { ArbiError } from '@arbidocs/sdk/browser'\n\n// \u2500\u2500 UI \"lego\" (promoted from the ARBI app; consumer supplies Tailwind + tokens) \u2500\u2500\n\n// shadcn UI primitives\nexport { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from './ui/tooltip'\nexport { IconToggle, type IconToggleProps } from './ui/IconToggle'\nexport { VisibilityToggle, type VisibilityToggleProps } from './ui/VisibilityToggle'\nexport { VerifiedToggle } from './ui/VerifiedToggle'\nexport { formatFriendlyDate, formatCompactLastSeen } from './lib/format-friendly-date'\nexport { markdownToPlainText, markdownToPlainTextBlocks } from './lib/markdown-to-text'\nexport { DebouncedInput, type DebouncedInputProps } from './ui/DebouncedInput'\nexport { useDictateContext, type DictateContextValue } from './ui/DictateContext'\nexport { PortalContainerProvider, usePortalContainer } from './ui/portal-container'\nexport { Avatar, AvatarImage, AvatarFallback } from './ui/avatar'\nexport { Badge, badgeVariants, type BadgeProps } from './ui/badge'\nexport { Button, buttonVariants, type ButtonProps } from './ui/button'\nexport { HoverCard, HoverCardTrigger, HoverCardContent } from './ui/hover-card'\nexport {\n Card,\n CardHeader,\n CardTitle,\n CardDescription,\n CardContent,\n CardFooter,\n cardVariants,\n} from './ui/card'\nexport type { CardProps } from './ui/card'\nexport { Input, type InputProps } from './ui/input'\nexport { Label } from './ui/label'\nexport { Separator } from './ui/separator'\nexport { Textarea, type TextareaProps } from './ui/textarea'\nexport { Collapsible, CollapsibleTrigger, CollapsibleContent } from './ui/collapsible'\nexport { Progress } from './ui/progress'\nexport { ScrollArea, ScrollBar } from './ui/scroll-area'\nexport { RadioGroup, RadioGroupItem } from './ui/radio-group'\nexport { Checkbox } from './ui/checkbox'\nexport { Switch } from './ui/switch'\nexport { Tabs, TabsList, TabsTrigger, TabsContent } from './ui/tabs'\nexport {\n Table,\n TableHeader,\n TableBody,\n TableFooter,\n TableHead,\n TableRow,\n TableCell,\n TableCaption,\n} from './ui/table'\nexport { Slider } from './ui/slider'\nexport { Toggle, toggleVariants } from './ui/toggle'\nexport { ToggleGroup, ToggleGroupItem } from './ui/toggle-group'\nexport {\n Dialog,\n DialogPortal,\n DialogOverlay,\n DialogTrigger,\n DialogClose,\n DialogContent,\n DialogHeader,\n DialogFooter,\n DialogTitle,\n DialogDescription,\n type DialogPresentation,\n} from './ui/dialog'\nexport { Popover, PopoverTrigger, PopoverContent, PopoverAnchor, PopoverClose } from './ui/popover'\nexport { MarkMenu, type MarkMenuItem, type MarkMenuProps } from './ui/mark-menu'\nexport {\n DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuCheckboxItem,\n DropdownMenuRadioItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuGroup,\n DropdownMenuPortal,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuRadioGroup,\n} from './ui/dropdown-menu'\nexport {\n Select,\n SelectGroup,\n SelectValue,\n SelectTrigger,\n SelectContent,\n SelectLabel,\n SelectItem,\n SelectSeparator,\n SelectScrollUpButton,\n SelectScrollDownButton,\n} from './ui/select'\nexport {\n Command,\n CommandDialog,\n CommandInput,\n CommandList,\n CommandEmpty,\n CommandGroup,\n CommandItem,\n CommandShortcut,\n CommandSeparator,\n} from './ui/command'\n\n// \u2500\u2500 AI kit: mid-level, token-neutral building blocks for AI-native apps \u2500\u2500\n// (streaming answers, artifact canvas, redline, doc Q&A)\nexport * from './ai'\n\n// Document search: the one search hook, its session and the label-the-results write.\nexport * from './search'\n\n// File-type icons\nexport * from './icons'\n\n// Decoupled entity pills + canonical entity registry\nexport * from './entities'\n\n// Shared notification & activity presentation layer\nexport * from './notifications'\nexport * from './connectors'\n\n// Direct-message block kit (real E2E-encrypted messenger)\nexport * from './directmessages'\n\n// Image crop kit (frame any uploaded/generated image; avatar is a preset)\nexport * from './imagecrop'\n\n// User menu kit (topbar account avatar dropdown)\nexport * from './usermenu'\n\n// Documents: the list, its writes, uploads, and what a host adds\nexport * from './documents'\n\n// People: display name, initials, avatar colour\nexport * from './users'\n\n// Session state shared by every block (workspace, conversation, viewing document, \u2026)\nexport * from './session'\n\n// Remote control: its session-only consent state and the `remote_control` websocket message\nexport * from './remote-control'\n\n// Class-name helper\nexport { cn } from './lib/utils'\n\nexport {\n useAgentSession,\n useAgentChats,\n useStartAgentSession,\n useCloseAgentSession,\n} from './workforce'\n\n// The documents an entity extraction is running on, until the live connection says it is done\nexport {\n finishEntityExtraction,\n startEntityExtraction,\n useEntityExtractionDocIds,\n} from './entity-extraction'\n\nexport * from './support'\n\n// Heavy components in their own chunk, loaded the first time one renders.\nexport { lazyChunk, lazyComponent, preloadChunks, type LazyChunk } from './lazy-chunk'\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|