@arbidocs/react 0.5.56 → 0.5.58

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.
Files changed (56) hide show
  1. package/README.md +9 -0
  2. package/dist/artifacts/index.cjs +14 -14
  3. package/dist/artifacts/index.js +4 -4
  4. package/dist/calls/livekit/index.cjs +49 -49
  5. package/dist/calls/livekit/index.js +4 -4
  6. package/dist/{chunk-V64EETLS.cjs → chunk-3QK4VVPG.cjs} +4 -4
  7. package/dist/{chunk-V64EETLS.cjs.map → chunk-3QK4VVPG.cjs.map} +1 -1
  8. package/dist/{chunk-WRMA2JYX.js → chunk-7VENKMLD.js} +5 -5
  9. package/dist/{chunk-WRMA2JYX.js.map → chunk-7VENKMLD.js.map} +1 -1
  10. package/dist/{chunk-2JQ7QNOO.cjs → chunk-A675AQXL.cjs} +154 -69
  11. package/dist/chunk-A675AQXL.cjs.map +1 -0
  12. package/dist/{chunk-KUGZXI7V.js → chunk-CE4RY7VA.js} +3 -3
  13. package/dist/{chunk-KUGZXI7V.js.map → chunk-CE4RY7VA.js.map} +1 -1
  14. package/dist/{chunk-RRWAX52L.cjs → chunk-G76ASVVH.cjs} +6 -2
  15. package/dist/chunk-G76ASVVH.cjs.map +1 -0
  16. package/dist/{chunk-PVUZULHI.js → chunk-J33GSXDT.js} +92 -12
  17. package/dist/chunk-J33GSXDT.js.map +1 -0
  18. package/dist/{chunk-3CVY5SGY.cjs → chunk-JNS3BOPU.cjs} +65 -65
  19. package/dist/{chunk-3CVY5SGY.cjs.map → chunk-JNS3BOPU.cjs.map} +1 -1
  20. package/dist/{chunk-UKEUDTOE.cjs → chunk-LCSUCZVX.cjs} +46 -46
  21. package/dist/{chunk-UKEUDTOE.cjs.map → chunk-LCSUCZVX.cjs.map} +1 -1
  22. package/dist/{chunk-4TKNUJKD.js → chunk-M2SZQBCO.js} +3 -3
  23. package/dist/{chunk-4TKNUJKD.js.map → chunk-M2SZQBCO.js.map} +1 -1
  24. package/dist/{chunk-DFZECLD3.js → chunk-R7YNABZY.js} +2 -2
  25. package/dist/chunk-R7YNABZY.js.map +1 -0
  26. package/dist/{chunk-JFL7BBZ6.js → chunk-S2W3ZOWG.js} +4 -4
  27. package/dist/{chunk-JFL7BBZ6.js.map → chunk-S2W3ZOWG.js.map} +1 -1
  28. package/dist/{chunk-FSPLYO52.cjs → chunk-SOOLC65L.cjs} +3 -3
  29. package/dist/{chunk-FSPLYO52.cjs.map → chunk-SOOLC65L.cjs.map} +1 -1
  30. package/dist/{chunk-PBXJFMES.js → chunk-U64WCQP3.js} +6 -2
  31. package/dist/chunk-U64WCQP3.js.map +1 -0
  32. package/dist/{chunk-YRY6DGRU.cjs → chunk-Y7S2SQH3.cjs} +2 -2
  33. package/dist/chunk-Y7S2SQH3.cjs.map +1 -0
  34. package/dist/document-tools/index.cjs +60 -60
  35. package/dist/document-tools/index.d.cts +2 -2
  36. package/dist/document-tools/index.d.ts +2 -2
  37. package/dist/document-tools/index.js +5 -5
  38. package/dist/index.cjs +2569 -1343
  39. package/dist/index.cjs.map +1 -1
  40. package/dist/index.d.cts +1672 -1085
  41. package/dist/index.d.ts +1672 -1085
  42. package/dist/index.js +1228 -64
  43. package/dist/index.js.map +1 -1
  44. package/dist/{query-keys.d-DM2N5pzN.d.cts → query-keys.d-DEEMzkLz.d.cts} +4 -0
  45. package/dist/{query-keys.d-DM2N5pzN.d.ts → query-keys.d-DEEMzkLz.d.ts} +4 -0
  46. package/dist/ui/index.cjs +164 -164
  47. package/dist/ui/index.js +2 -2
  48. package/dist/viewers/index.cjs +2 -2
  49. package/dist/viewers/index.js +1 -1
  50. package/package.json +3 -3
  51. package/dist/chunk-2JQ7QNOO.cjs.map +0 -1
  52. package/dist/chunk-DFZECLD3.js.map +0 -1
  53. package/dist/chunk-PBXJFMES.js.map +0 -1
  54. package/dist/chunk-PVUZULHI.js.map +0 -1
  55. package/dist/chunk-RRWAX52L.cjs.map +0 -1
  56. package/dist/chunk-YRY6DGRU.cjs.map +0 -1
package/dist/index.js CHANGED
@@ -1,29 +1,29 @@
1
- import { invalidateConversationLists, patchConversation, invalidateConversationDetails, removeConversationFromLists, addConversationToList, findConversation, isConversationShared, isKnownSoloConversation, useUserSettings, patchConversationList, useFeature, useAccountClient, useUpdateUserSettings, myChatId, upsertChat, appendToThread, dropFromThread, deleteChatMessage, removeChat, getOpenChat, cachedChat, applyChatEvent, applyCallEvent } from './chunk-WRMA2JYX.js';
2
- export { AUDIENCE_CHOICES, CALL_CAPTION_TOPIC, CALL_CHAT_MAX_CHARS, CALL_CHAT_TOPIC, CALL_MODERATION_TOPIC, CALL_RECORDING_TOPIC, CALL_TRANSCRIPTION_TOPIC, CALL_WEBINAR_TOPIC, CAPTION_MAX_CHARS, COMPOSITE_AUDIO_BITS_PER_SECOND, COMPOSITE_VIDEO_BITS_PER_SECOND, DEFAULT_JOIN_CHOICES, EMPTY_CALL_SESSION, EXPORT_SAMPLE_RATE, HISTORY_LIMIT, LIVE_SEGMENTER, MAX_AVATAR_FILE_BYTES, MUTED_DEDUPE_MS, PLAYBACK_LOOKAHEAD_MS, READ_ONLY_MEETING_TEXT, RECORDING_CHUNK_MS, RECORDING_SEGMENTER, SEGMENT_FRAME_MS, SEGMENT_ID_PATTERN, SEGMENT_PRE_ROLL_MS, SHORT_PIECE_MERGE_GAP_MS, SPEAKER_AUDIO_BITS_PER_SECOND, TrackUploader, UPLOAD_ATTEMPTS, UPLOAD_BACKOFF_MS, acceptRing, addConversationToList, appendToThread, applyAgentDmStatus, applyCallEvent, applyChatEvent, applyChatMessage, applyChatRead, applyChatUpdated, arbiAccountClient, buildMeetingChatBody, cachedChat, cachedChats, callLink, callMemberKeys, callSession, chatByExtId, chatHasLiveCall, chatLiveCallId, chatTranscriptRef, clearMeetingChatCache, clearTrackUploaders, clockTime, compositeFiles, compositeTrack, conversationKeyForCall, createLocalFeatureStore, createMutedNotifier, createTrackCutter, cutAtPauses, declineRing, decodeCallChatPacket, decodeCaptionPacket, decodeMono16k, decryptPart, encodeCallChatPacket, encodeCaptionPacket, encodeWav, encryptPart, ensureMeetingChat, entitlementRefusal, extensionFor, fetchPart, fileSafe, findConversation, floatToWav, formatTranscriptMarkdown, getOpenChat, hasRecordingTranscript, invalidateCall, invalidateConversationDetails, invalidateConversationLists, isConversationListKey, isConversationShared, isKnownSoloConversation, isRecordingOver, isRecordingSegmentId, isRetryable, isWorkspaceGuestOf, joinFromPreJoin, knownMeetingChat, loadMeetingHistory, markRejoining, meetingChatRefFrom, meetingRefForCall, mergeChatLines, mutedNoticeFromEvent, mutedNoticeFromPacket, mutedNoticeText, myChatId, newPacketId, newSegmentId, newTrackKey, nextSeqAfter, onCallEvent, openCall, openQuestion, openRecording, parseWebinarPacket, partKey, partOffsetMs, partsDue, patchConversation, patchConversationList, persistMeetingMessage, persistTranscriptSegment, playheadAt, postRecordingDocsToThread, postTranscriptToThread, readLocalFeature, recordingFiles, recordingWindowsOf, rejoinAsAudience, removeChat, removeConversationFromLists, resetCallSession, resolveMeetingChat, saveRecordingFilesToThread, schedulePart, sealQuestionText, serverCallsExperimental, setOpenChat, sortTranscriptMessages, sortedParts, speakerTracks, speakerWav, splitIntoFiles, standalone, startChatCall, startContactsCall, startDmCall, startThreadCall, startsMediaFile, storeTranscriptSegment, stripSpeakerPrefix, supersedeLiveTranscript, supersededTranscriptLines, threadHasLiveCall, threadLiveCallId, threadTranscriptLines, threadTranscriptRef, threadTranscriptText, timelineDurationMs, timelineOf, toProfileView, trackUploaderFor, transcribeRecording, transcriptPersistRole, transcriptSegmentOf, unwrapTrackKey, upsertChat, useAccountClient, useAvatarCrop, useCall, useCallInviteLinks, useCallRecording, useCallRecordings, useCallSession, useCallTranscriptionAvailable, useCallsConfig, useCallsEnabled, useCanHostCalls, useEntitlements, useFeature, useFeatureSwitch, useIsEntitled, useMeetingReadOnly, useNameEditor, useOpenCallMeetingChat, useProfile, useRecordingActions, useRecordingWindows, useRevokeCallInviteLink, useSaveToThread, useServerCallsEnabled, useServerCallsExperimental, useUpdateProfile, useUpdateUserSettings, useUserSettings, wrapTrackKey, writeSamples } from './chunk-WRMA2JYX.js';
3
- import { replayableTagMutations, patchDocuments, setCachedDocument, adjustTagCounts, patchCachedDocument, FINISHED_DOCUMENT_STATUSES, refreshDocuments, getCachedDocuments, useArbiWsStore, IN_FLIGHT_DOCUMENT_STATUSES, forgetDocuments, useSimilarDocuments, SIMILARITY_THRESHOLD, useDocuments, finishEntityExtraction } from './chunk-JFL7BBZ6.js';
4
- export { DISMISSED_TASK_TTL_MS, DOCUMENTS_FIRST_PAGE_MEASURE, DOCUMENTS_FIRST_PAGE_SIZE, DOCUMENTS_PAGE_SIZE, FINISHED_DOCUMENT_STATUSES, IN_FLIGHT_DOCUMENT_STATUSES, SIMILARITY_THRESHOLD, adjustTagCounts, dropTagFromCachedDocuments, finishEntityExtraction, forgetDocuments, getCachedDocuments, invalidateTagData, invalidateTagTables, isDocumentsLoading, isRowNewer, isStaleTaskUpdate, patchCachedDocument, patchDocuments, patchWorkspaceTags, refreshDocuments, resolveDocumentStatus, setCachedDocument, settledByRows, startEntityExtraction, stopDocumentsLoading, subscribeDocumentRows, upsertDocuments, useArbiWsStore, useCreateTag, useDeleteTag, useDocument, useDocuments, useDocumentsById, useDocumentsLoading, useEntityExtractionDocIds, useExtractEntities, useInvalidateTagData, useIsCreatingTag, useRefreshDocuments, useSetTagValues, useSimilarDocuments, useTagKindSchema, useUpdateTag, useUpdateTagKindSchema } from './chunk-JFL7BBZ6.js';
5
- import { useArbiSessionState, useConversations, useArbiSession, useWorkspaces, useConfig, useArbiSessionStore, useAvailableModels, useParsedDocument, useTags, selectDraft, useConversationThreads, createArbiSessionStore, useAgents, useAssistantQuery, useActivity, queuedMessages, MIN_QUEUED_MESSAGE_VISIBILITY_MS } from './chunk-PVUZULHI.js';
6
- export { DEFAULT_DOCUMENT_VIEWER_STATE, EMPTY_SESSION_STATE, MAX_THREAD_TABS, MIN_QUEUED_MESSAGE_VISIBILITY_MS, PROJECT_CREATION_DENIED_REASON, agentControl, clearSealedDrafts, closePanelIn, conversationKey, createArbiLayoutStore, createArbiSessionStore, createDebouncedWriter, createSealedDraftStorage, createStoragePersist, defaultLayoutState, dmTabId, flushOnPageExit, isPanelOpen, isUsageMetered, layoutActionsOf, nextViewingDocument, openPanelIn, panelPlace, parseSavedLayout, queuedMessages, restoreLayout, savedLayoutOf, selectDraft, selectIsGenerating, selectViewingDocumentId, threadTabId, useActivity, useAgents, useArbiSession, useArbiSessionState, useArbiSessionStore, useAssistantQuery, useAvailableModels, useBoxRole, useBuiltinCommands, useCanCreateProjects, useConfig, useConfigs, useConversationThreads, useConversations, useCurrentUser, useDeleteAgents, useDocumentVersionList, useFirmPool, useHealth, useMessageDetails, useParsedDocument, useProjectInvoices, useProjectUsage, useProjects, useProjectsUsage, useSessionPageTab, useSessionView, useSignedInSession, useTags, useThumbnails, useTopUpFirmPool, useTransientView, useUserUsageToday, useWorkspaceActivity, useWorkspaces } from './chunk-PVUZULHI.js';
7
- import { fetchDocumentFile, downloadBlob, fetchMarkupPdf, fetchDocumentPdf } from './chunk-4TKNUJKD.js';
8
- import { arbiMutationKeys, arbiQueryKeys, mailQueryKeys, connectorQueryKeys, calendarQueryKeys } from './chunk-PBXJFMES.js';
9
- export { arbiMutationKeys, arbiQueryKeys, calendarQueryKeys, callQueryKeys, connectorQueryKeys, isUnderQueryKey, mailQueryKeys } from './chunk-PBXJFMES.js';
1
+ import { useUserSettings, invalidateConversationLists, patchConversation, invalidateConversationDetails, removeConversationFromLists, addConversationToList, findConversation, isConversationShared, isKnownSoloConversation, patchConversationList, useFeature, useAccountClient, useUpdateUserSettings, myChatId, upsertChat, appendToThread, dropFromThread, deleteChatMessage, removeChat, getOpenChat, cachedChat, applyChatEvent, applyCallEvent } from './chunk-7VENKMLD.js';
2
+ export { AUDIENCE_CHOICES, CALL_CAPTION_TOPIC, CALL_CHAT_MAX_CHARS, CALL_CHAT_TOPIC, CALL_MODERATION_TOPIC, CALL_RECORDING_TOPIC, CALL_TRANSCRIPTION_TOPIC, CALL_WEBINAR_TOPIC, CAPTION_MAX_CHARS, COMPOSITE_AUDIO_BITS_PER_SECOND, COMPOSITE_VIDEO_BITS_PER_SECOND, DEFAULT_JOIN_CHOICES, EMPTY_CALL_SESSION, EXPORT_SAMPLE_RATE, HISTORY_LIMIT, LIVE_SEGMENTER, MAX_AVATAR_FILE_BYTES, MUTED_DEDUPE_MS, PLAYBACK_LOOKAHEAD_MS, READ_ONLY_MEETING_TEXT, RECORDING_CHUNK_MS, RECORDING_SEGMENTER, SEGMENT_FRAME_MS, SEGMENT_ID_PATTERN, SEGMENT_PRE_ROLL_MS, SHORT_PIECE_MERGE_GAP_MS, SPEAKER_AUDIO_BITS_PER_SECOND, TrackUploader, UPLOAD_ATTEMPTS, UPLOAD_BACKOFF_MS, acceptRing, addConversationToList, appendToThread, applyAgentDmStatus, applyCallEvent, applyChatEvent, applyChatMessage, applyChatRead, applyChatUpdated, arbiAccountClient, buildMeetingChatBody, cachedChat, cachedChats, callLink, callMemberKeys, callSession, chatByExtId, chatHasLiveCall, chatLiveCallId, chatTranscriptRef, clearMeetingChatCache, clearTrackUploaders, clockTime, compositeFiles, compositeTrack, conversationKeyForCall, createLocalFeatureStore, createMutedNotifier, createTrackCutter, cutAtPauses, declineRing, decodeCallChatPacket, decodeCaptionPacket, decodeMono16k, decryptPart, encodeCallChatPacket, encodeCaptionPacket, encodeWav, encryptPart, ensureMeetingChat, entitlementRefusal, extensionFor, fetchPart, fileSafe, findConversation, floatToWav, formatTranscriptMarkdown, getOpenChat, hasRecordingTranscript, invalidateCall, invalidateConversationDetails, invalidateConversationLists, isConversationListKey, isConversationShared, isKnownSoloConversation, isRecordingOver, isRecordingSegmentId, isRetryable, isWorkspaceGuestOf, joinFromPreJoin, knownMeetingChat, loadMeetingHistory, markRejoining, meetingChatRefFrom, meetingRefForCall, mergeChatLines, mutedNoticeFromEvent, mutedNoticeFromPacket, mutedNoticeText, myChatId, newPacketId, newSegmentId, newTrackKey, nextSeqAfter, onCallEvent, openCall, openQuestion, openRecording, parseWebinarPacket, partKey, partOffsetMs, partsDue, patchConversation, patchConversationList, persistMeetingMessage, persistTranscriptSegment, playheadAt, postRecordingDocsToThread, postTranscriptToThread, readLocalFeature, recordingFiles, recordingWindowsOf, rejoinAsAudience, removeChat, removeConversationFromLists, resetCallSession, resolveMeetingChat, saveRecordingFilesToThread, schedulePart, sealQuestionText, serverCallsExperimental, setOpenChat, sortTranscriptMessages, sortedParts, speakerTracks, speakerWav, splitIntoFiles, standalone, startChatCall, startContactsCall, startDmCall, startThreadCall, startsMediaFile, storeTranscriptSegment, stripSpeakerPrefix, supersedeLiveTranscript, supersededTranscriptLines, threadHasLiveCall, threadLiveCallId, threadTranscriptLines, threadTranscriptRef, threadTranscriptText, timelineDurationMs, timelineOf, toProfileView, trackUploaderFor, transcribeRecording, transcriptPersistRole, transcriptSegmentOf, unwrapTrackKey, upsertChat, useAccountClient, useAvatarCrop, useCall, useCallInviteLinks, useCallRecording, useCallRecordings, useCallSession, useCallTranscriptionAvailable, useCallsConfig, useCallsEnabled, useCanHostCalls, useEntitlements, useFeature, useFeatureSwitch, useIsEntitled, useMeetingReadOnly, useNameEditor, useOpenCallMeetingChat, useProfile, useRecordingActions, useRecordingWindows, useRevokeCallInviteLink, useSaveToThread, useServerCallsEnabled, useServerCallsExperimental, useUpdateProfile, useUpdateUserSettings, useUserSettings, wrapTrackKey, writeSamples } from './chunk-7VENKMLD.js';
3
+ import { replayableTagMutations, patchDocuments, setCachedDocument, adjustTagCounts, patchCachedDocument, FINISHED_DOCUMENT_STATUSES, refreshDocuments, getCachedDocuments, useArbiWsStore, IN_FLIGHT_DOCUMENT_STATUSES, forgetDocuments, useSimilarDocuments, SIMILARITY_THRESHOLD, useDocuments, finishEntityExtraction } from './chunk-S2W3ZOWG.js';
4
+ export { DISMISSED_TASK_TTL_MS, DOCUMENTS_FIRST_PAGE_MEASURE, DOCUMENTS_FIRST_PAGE_SIZE, DOCUMENTS_PAGE_SIZE, FINISHED_DOCUMENT_STATUSES, IN_FLIGHT_DOCUMENT_STATUSES, SIMILARITY_THRESHOLD, adjustTagCounts, dropTagFromCachedDocuments, finishEntityExtraction, forgetDocuments, getCachedDocuments, invalidateTagData, invalidateTagTables, isDocumentsLoading, isRowNewer, isStaleTaskUpdate, patchCachedDocument, patchDocuments, patchWorkspaceTags, refreshDocuments, resolveDocumentStatus, setCachedDocument, settledByRows, startEntityExtraction, stopDocumentsLoading, subscribeDocumentRows, upsertDocuments, useArbiWsStore, useCreateTag, useDeleteTag, useDocument, useDocuments, useDocumentsById, useDocumentsLoading, useEntityExtractionDocIds, useExtractEntities, useInvalidateTagData, useIsCreatingTag, useRefreshDocuments, useSetTagValues, useSimilarDocuments, useTagKindSchema, useUpdateTag, useUpdateTagKindSchema } from './chunk-S2W3ZOWG.js';
5
+ import { useArbiSessionState, useArbiSession, useWorkspaces, useConversations, useConfig, useArbiSessionStore, useAvailableModels, useParsedDocument, useTags, selectDraft, useConversationThreads, createArbiSessionStore, useProjects, useAgents, useAssistantQuery, useActivity, queuedMessages, MIN_QUEUED_MESSAGE_VISIBILITY_MS } from './chunk-J33GSXDT.js';
6
+ export { DEFAULT_DOCUMENT_VIEWER_STATE, EMPTY_SESSION_STATE, MAX_THREAD_TABS, MIN_QUEUED_MESSAGE_VISIBILITY_MS, PROJECT_CREATION_DENIED_REASON, WORKSPACE_LAST_OPENED_KEY, WORKSPACE_STORAGE_KEY, agentControl, browserWorkspaceStorage, clearSealedDrafts, closePanelIn, conversationKey, createArbiLayoutStore, createArbiSessionStore, createArbiWorkspaceStore, createDebouncedWriter, createSealedDraftStorage, createStoragePersist, defaultLayoutState, dmTabId, flushOnPageExit, isPanelOpen, isUsageMetered, layoutActionsOf, nextViewingDocument, openPanelIn, panelPlace, parseSavedLayout, queuedMessages, readWorkspaceLastOpened, restoreLayout, savedLayoutOf, selectDraft, selectIsGenerating, selectViewingDocumentId, threadTabId, useActivity, useAgents, useArbiSession, useArbiSessionState, useArbiSessionStore, useAssistantQuery, useAvailableModels, useBoxRole, useBuiltinCommands, useCanCreateProjects, useConfig, useConfigs, useConversationThreads, useConversations, useCurrentUser, useDeleteAgents, useDocumentVersionList, useFirmPool, useHealth, useMessageDetails, useParsedDocument, useProjectInvoices, useProjectUsage, useProjects, useProjectsUsage, useSessionPageTab, useSessionView, useSignedInSession, useTags, useThumbnails, useTopUpFirmPool, useTransientView, useUserUsageToday, useWorkspaceActivity, useWorkspaces } from './chunk-J33GSXDT.js';
10
7
  import { ArbiHost, extractMentions, UNBOUND, bindingOfRow, readLegacyThreadDocuments, forgetLegacyThreadDocuments, toMessageMentions, takeDocumentForTurn, hasMessageBody, createSearchSession, clearSearchSession } from './chunk-CMNZI4WQ.js';
11
8
  export { LEGACY_THREAD_DOCUMENTS_KEY, MENTION_HREF_PREFIX, NotificationBell, Toaster, UNBOUND, bindingOfRow, clearSearchSession, createSearchSession, extractMentions, filterMentionCandidates, findMentionQuery, forgetLegacyThreadDocuments, hasMessageBody, insertMention, latestThreadOfDocument, linkMentions, mentionFromHref, openDocumentId, opensInWord, persistSearchSession, readLegacyThreadDocuments, requestSearch, savedDocumentIdFor, sharedSearchSession, takeDocumentForTurn, takePendingSearch, toMessageMentions, useOpenDocumentId, useRegisterOpenDocument, useTurnDocumentId } from './chunk-CMNZI4WQ.js';
12
9
  import { notify } from './chunk-5HDC43MF.js';
13
10
  export { DEFAULT_NOTIFY_TONE, MAX_SESSION_NOTIFICATIONS, configureNotify, notify, persistNotifyHistory, seedNotifications, selectUnread, toast, useNotify } from './chunk-5HDC43MF.js';
14
11
  export { mergeHostConfig } from './chunk-DPYBZDJB.js';
12
+ import { fetchDocumentFile, downloadBlob, fetchMarkupPdf, fetchDocumentPdf } from './chunk-M2SZQBCO.js';
13
+ import { arbiMutationKeys, arbiQueryKeys, mailQueryKeys, connectorQueryKeys, calendarQueryKeys } from './chunk-U64WCQP3.js';
14
+ export { arbiMutationKeys, arbiQueryKeys, calendarQueryKeys, callQueryKeys, connectorQueryKeys, isUnderQueryKey, mailQueryKeys } from './chunk-U64WCQP3.js';
15
15
  export { cleanDraftMarkdown, cleanDraftWithReport, promoteBoldTitle, repairParsedStructure, repairParsedTitle, stripAgentPreamble, unescapeMarkdown, unwrapCitationLinks } from './chunk-NNWMHMEC.js';
16
16
  import './chunk-WUTL62MC.js';
17
- import { returnFocusToMark, MarkMenu, getDocumentTitle, Badge, TagEntity, useAudioRecorder, MicWaveformIndicator, IconToggle, classifyMediaError, formatElapsed, AiMarkdown, Card, Input, FILE_TYPE_COLORS, getEntityIcon, UserEntity, getEntityColorStyles, AgentBadge, Textarea, Slider, getEntityLabel, getDocumentDate, usesOriginalBytesForViewer } from './chunk-KUGZXI7V.js';
18
- export { ARBI_MARK_SRC, AUDIO_MIME_PREFERENCE, AgentBadge, AiMarkdown, ArbiBotHeadIcon, ArbiIcon, AudIcon, BASE_COLORS, Badge, COLUMN_LABEL_FALLBACKS, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, ClaudeIcon, Collapsible, CollapsibleContent, CollapsibleTrigger, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, DEFAULT_METADATA_TAGS, DebouncedInput, DocIcon, DocumentCard, DocumentEntity, ENTITY_MAPPINGS, EmlIcon, EntityIcon, EntityPill, FILE_TYPE_COLORS, FireworksIcon, GeminiIcon, GoogleIcon, HoverCard, HoverCardContent, HoverCardTrigger, HtmlIcon, IconToggle, ImgIcon, InlineMicButton, Input, Label, MarkMenu, MicRecordingOverlay, MicWaveformIndicator, NEUTRAL_GRAY, OpenAIIcon, PLACEHOLDER_COLOR, PassageCard, PdfIcon, Popover, PopoverAnchor, PopoverClose, PopoverContent, PopoverTrigger, PresenceLabel, Progress, ProjectEntity, ProviderIcon, RadioGroup, RadioGroupItem, RagDot, RelevanceDot, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, ShieldIcon, Slider, StatusPill, Switch, TAG_TYPE_ICONS, TAG_TYPE_LABELS, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, TagEntity, Textarea, ThreadVisibilityIcon, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TxtIcon, UserEntity, UserMenu, VIDEO_MIME_PREFERENCE, VISIBILITY_ICONS, VerifiedBadge, VerifiedToggle, VidIcon, VisibilityIcon, VisibilityToggle, XlsIcon, agentAvatarColors, badgeVariants, buildFolderTree, canonicalFolderPath, cardVariants, classifyMediaError, configureEntityRegistry, configureRagLabels, configureStatusRegistry, createChunkedRecorder, entityNoun, extensionFromMime, formatDocDate, formatElapsed, formatFolderLabel, formatFriendlyDate, friendlyFileType, getDocIcon, getDocumentAuthor, getDocumentDate, getDocumentNature, getDocumentSubject, getDocumentTitle, getEntityColor, getEntityColorStyles, getEntityIcon, getEntityLabel, getFileExtension, getFileTypeIcon, getStatusVariant, getTagTypeIcon, getTagTypeLabel, getWorkspaceColor, isAudioFile, isDocumentAddableToConversation, isDownloadOnlyFile, isImageDocument, isImageFile, isMediaFile, isVideoFile, markdownToPlainText, markdownToPlainTextBlocks, pickRecorderMimeType, tagKindNouns, tagKindTitle, toggleVariants, useAudioRecorder, useDictateContext, usesOriginalBytesForViewer } from './chunk-KUGZXI7V.js';
17
+ import { returnFocusToMark, MarkMenu, getDocumentTitle, Badge, TagEntity, useAudioRecorder, MicWaveformIndicator, IconToggle, classifyMediaError, formatElapsed, friendlyFileType, AiMarkdown, Card, Input, FILE_TYPE_COLORS, getEntityIcon, UserEntity, getEntityColorStyles, AgentBadge, Textarea, Slider, getEntityLabel, getDocumentDate, usesOriginalBytesForViewer } from './chunk-CE4RY7VA.js';
18
+ export { ARBI_MARK_SRC, AUDIO_MIME_PREFERENCE, AgentBadge, AiMarkdown, ArbiBotHeadIcon, ArbiIcon, AudIcon, BASE_COLORS, Badge, COLUMN_LABEL_FALLBACKS, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, ClaudeIcon, Collapsible, CollapsibleContent, CollapsibleTrigger, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, DEFAULT_METADATA_TAGS, DebouncedInput, DocIcon, DocumentCard, DocumentEntity, ENTITY_MAPPINGS, EmlIcon, EntityIcon, EntityPill, FILE_TYPE_COLORS, FireworksIcon, GeminiIcon, GoogleIcon, HoverCard, HoverCardContent, HoverCardTrigger, HtmlIcon, IconToggle, ImgIcon, InlineMicButton, Input, Label, MarkMenu, MicRecordingOverlay, MicWaveformIndicator, NEUTRAL_GRAY, OpenAIIcon, PLACEHOLDER_COLOR, PassageCard, PdfIcon, Popover, PopoverAnchor, PopoverClose, PopoverContent, PopoverTrigger, PresenceLabel, Progress, ProjectEntity, ProviderIcon, RadioGroup, RadioGroupItem, RagDot, RelevanceDot, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, ShieldIcon, Slider, StatusPill, Switch, TAG_TYPE_ICONS, TAG_TYPE_LABELS, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, TagEntity, Textarea, ThreadVisibilityIcon, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TxtIcon, UserEntity, UserMenu, VIDEO_MIME_PREFERENCE, VISIBILITY_ICONS, VerifiedBadge, VerifiedToggle, VidIcon, VisibilityIcon, VisibilityToggle, XlsIcon, agentAvatarColors, badgeVariants, buildFolderTree, canonicalFolderPath, cardVariants, classifyMediaError, configureEntityRegistry, configureRagLabels, configureStatusRegistry, createChunkedRecorder, entityNoun, extensionFromMime, formatDocDate, formatElapsed, formatFolderLabel, formatFriendlyDate, friendlyFileType, getDocIcon, getDocumentAuthor, getDocumentDate, getDocumentNature, getDocumentSubject, getDocumentTitle, getEntityColor, getEntityColorStyles, getEntityIcon, getEntityLabel, getFileExtension, getFileTypeIcon, getStatusVariant, getTagTypeIcon, getTagTypeLabel, getWorkspaceColor, isAudioFile, isDocumentAddableToConversation, isDownloadOnlyFile, isImageDocument, isImageFile, isMediaFile, isVideoFile, markdownToPlainText, markdownToPlainTextBlocks, pickRecorderMimeType, tagKindNouns, tagKindTitle, toggleVariants, useAudioRecorder, useDictateContext, usesOriginalBytesForViewer } from './chunk-CE4RY7VA.js';
19
19
  import { getUserDisplayName, isAgent } from './chunk-APZZQZ6P.js';
20
20
  export { Avatar, AvatarFallback, AvatarImage, DEFAULT_SEGMENTER_CONFIG, INITIAL_SEGMENTER_STATE, createUserAvatarIcon, flushSegmenter, getUserAvatarColor, getUserDisplayName, getUserInitials, isAgent, levelFromRms, stepSegmenter } from './chunk-APZZQZ6P.js';
21
21
  import { MarkdownRenderer } from './chunk-C44GO33B.js';
22
22
  export { MarkdownCode, MarkdownLink, MarkdownRenderer, MarkdownStreamingContext, markdownBaseComponents, markdownSanitizeSchema, splitMarkdownBlocks } from './chunk-C44GO33B.js';
23
- import { Button, Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from './chunk-YNNAJJ5Z.js';
24
- export { Button, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, buttonVariants } from './chunk-YNNAJJ5Z.js';
25
23
  import { formatRelativeTime } from './chunk-Y3MTRA7D.js';
26
24
  export { ScrollArea, ScrollBar, configureEntityVocabulary, formatRelativeTime } from './chunk-Y3MTRA7D.js';
25
+ import { Button, Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from './chunk-YNNAJJ5Z.js';
26
+ export { Button, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, buttonVariants } from './chunk-YNNAJJ5Z.js';
27
27
  import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator } from './chunk-47CCGUWR.js';
28
28
  export { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, PortalContainerProvider, usePortalContainer } from './chunk-47CCGUWR.js';
29
29
  import { normalizeCitationMarkup } from './chunk-QRCMKEE6.js';
@@ -31,11 +31,11 @@ export { closeOpenEmphasis, normalizeCitationMarkup, trimOpenCitation } from './
31
31
  import { cn } from './chunk-SN5YV6FF.js';
32
32
  export { cn } from './chunk-SN5YV6FF.js';
33
33
  import { AudioViewer, ImageViewer, VideoViewer } from './chunk-HDCRPPBW.js';
34
- import { useArbi, useArbiHost } from './chunk-DFZECLD3.js';
35
- export { useArbi, useArbiHost, useDeploymentDomain } from './chunk-DFZECLD3.js';
34
+ import { useArbi, useArbiHost } from './chunk-R7YNABZY.js';
35
+ export { useArbi, useArbiHost, useDeploymentDomain } from './chunk-R7YNABZY.js';
36
36
  export { useHostConfigRecord } from './chunk-CPZ36AQS.js';
37
37
  import React, { memo, useState, createContext, useMemo, useCallback, useEffect, useRef, useLayoutEffect, useSyncExternalStore, useContext, useId } from 'react';
38
- import { useQueryClient, useMutation, useQuery, onlineManager, partialMatchKey, useMutationState, keepPreviousData, useQueries } from '@tanstack/react-query';
38
+ import { useQuery, useQueryClient, useMutation, onlineManager, partialMatchKey, useMutationState, keepPreviousData, useQueries } from '@tanstack/react-query';
39
39
  import { documents, doctags, houseTemplates, STOP_ID_WAIT_MS, resolveCitations, summarizeCitations, createIndexAssigner, reduceOutputItem, findReplyTarget, ArbiApiError, quotaFromStreamError, STOP_REPEAT_WINDOW_MS, getRunToCancel, pickMainThread, extractDocumentIdsFromMessages, extractFactIdsFromMessages, hydrateAgentSteps, getSubagentBranchRecord, getRunToAttach, settings, isConnectorVendorVisible, ACCOUNT_VENDOR, searchChunks, formatFileSize, chats, connectWithReconnect, ArbiWorkspaceSupersededError, identityErrorCode } from '@arbidocs/sdk/browser';
40
40
  export { ACCOUNT_VENDOR, Arbi, ArbiError, DEFAULT_AI_USD_PER_GBP, DRIVE_SYNC_VENDORS, GOOGLE_VENDORS, IMANAGE_VENDORS, MAILBOX_SYNC_VENDORS, MAX_RETRIEVE_DOC_IDS, MICROSOFT_VENDORS, PublicBookingError, SHAREPOINT_VENDORS, bookPublicSlot, cancelPublicBooking, connectErrorMessage, formatGbp, formatGbpPerMillionTokens, getPublicBookingPage, isConnectorVendorVisible, isDriveSyncVendor, isMailboxSyncVendor, isSharePointVendor, usdToGbp } from '@arbidocs/sdk/browser';
41
41
  import { Link, Trash2, CheckCheck, Check, MoreHorizontal, SquarePen, Pencil, Download, X, Mic, Pause, Play, Square, Loader2, RotateCcw, Sparkles, Camera, Circle, AlertTriangle, ShieldCheck, Copy, FileText, GitCompareArrows, Search, CornerDownLeft, Send, Tags, Info, Activity, HardDrive, Gauge, Gift, PartyPopper, UserPlus, UserCheck, Reply, PenLine, AtSign, MessageCircleMore, FileX2, FileCheck2, FolderPlus, SquareArrowOutUpRight, Paperclip, ArrowRight, Image as Image$1, AppWindow } from 'lucide-react';
@@ -51,6 +51,21 @@ import Cropper from 'react-easy-crop';
51
51
 
52
52
  // src/host/index.ts
53
53
  var ArbiHost2 = ArbiHost;
54
+ function useCurrentWorkspace() {
55
+ const workspaceId = useArbiSessionState((s) => s.workspaceId);
56
+ const workspaceStatus = useArbiSessionState((s) => s.workspaceStatus);
57
+ const userId = useArbiSession().user?.external_id ?? null;
58
+ const { data: workspaces } = useWorkspaces();
59
+ const workspace = workspaceId ? workspaces?.find((w) => w.external_id === workspaceId) : void 0;
60
+ const membership = userId ? workspace?.users?.find((member) => member.user.external_id === userId) : void 0;
61
+ const role = membership?.role ?? null;
62
+ return useMemo(
63
+ () => ({ workspaceId, workspaceStatus, workspace, role, isMember: !!membership, userId }),
64
+ [workspaceId, workspaceStatus, workspace, role, membership, userId]
65
+ );
66
+ }
67
+
68
+ // src/workforce.ts
54
69
  function isActivityKey(queryKey, conversationId) {
55
70
  const [scope, resource, id, leaf] = queryKey;
56
71
  if (scope !== "arbi" || resource !== "conversations" || leaf !== "activity") return false;
@@ -112,11 +127,7 @@ function useWorkItems() {
112
127
  return { tasks, isLoading, refetch };
113
128
  }
114
129
  function useWorkspaceRole() {
115
- const workspaceId = useArbiSessionState((s) => s.workspaceId);
116
- const me = useArbiSession().user?.external_id;
117
- const { data: workspaces } = useWorkspaces();
118
- const workspace = workspaces?.find((w) => w.external_id === workspaceId);
119
- return workspace?.users?.find((m) => m.user.external_id === me)?.role ?? null;
130
+ return useCurrentWorkspace().role;
120
131
  }
121
132
  function useCanEditShared() {
122
133
  const role = useWorkspaceRole();
@@ -800,8 +811,8 @@ function getInterjectionText(item) {
800
811
  if (candidate?.type !== "reasoning" || candidate.arbi?.step !== "interjection" && candidate.arbi?.label !== "Your message") {
801
812
  return null;
802
813
  }
803
- const text = Array.isArray(candidate.summary) ? candidate.summary.map((c) => c.text ?? "").join("") : "";
804
- return text || null;
814
+ const text2 = Array.isArray(candidate.summary) ? candidate.summary.map((c) => c.text ?? "").join("") : "";
815
+ return text2 || null;
805
816
  }
806
817
  function threadEndingAtContains(queryClient, conversationId, leafId, messageId) {
807
818
  const data = queryClient.getQueryData(getThreadsQueryKey(conversationId));
@@ -901,8 +912,8 @@ function markNarrationSettled(queryClient, conversationId, messageId) {
901
912
  );
902
913
  }
903
914
  function removeSettledNarration(queryClient, conversationId, messageId, itemContent) {
904
- const text = Array.isArray(itemContent) ? itemContent.map((c) => c.text ?? "").join("") : "";
905
- if (!text.trim()) return;
915
+ const text2 = Array.isArray(itemContent) ? itemContent.map((c) => c.text ?? "").join("") : "";
916
+ if (!text2.trim()) return;
906
917
  flushStreamingTokens(queryClient);
907
918
  queryClient.setQueryData(
908
919
  getThreadsQueryKey(conversationId),
@@ -915,9 +926,9 @@ function removeSettledNarration(queryClient, conversationId, messageId, itemCont
915
926
  history: thread.history.map((msg) => {
916
927
  if (msg.external_id !== messageId) return msg;
917
928
  const body = msg.content ?? "";
918
- const at = body.lastIndexOf(text);
929
+ const at = body.lastIndexOf(text2);
919
930
  if (at === -1) return msg;
920
- const rest = body.slice(0, at) + body.slice(at + text.length);
931
+ const rest = body.slice(0, at) + body.slice(at + text2.length);
921
932
  const content = rest.trim() ? rest : "";
922
933
  const settled = Math.min(msg.settledNarrationLength ?? 0, content.length);
923
934
  return { ...msg, content, settledNarrationLength: settled || void 0 };
@@ -2567,8 +2578,8 @@ function VoiceNoteRecorder({
2567
2578
  if (!transcribe) return;
2568
2579
  let cancelled = false;
2569
2580
  setIsTranscribing(true);
2570
- transcribe(recorder.blob).then((text) => {
2571
- if (!cancelled) setTranscript(text);
2581
+ transcribe(recorder.blob).then((text2) => {
2582
+ if (!cancelled) setTranscript(text2);
2572
2583
  }).catch(() => {
2573
2584
  }).finally(() => {
2574
2585
  if (!cancelled) setIsTranscribing(false);
@@ -3336,7 +3347,8 @@ function useUploadFiles() {
3336
3347
  shared: input.shared,
3337
3348
  folder: folder ?? void 0,
3338
3349
  configExtId: input.configExtId ?? void 0,
3339
- workspaceExtId: workspaceId !== openWorkspaceId2 ? workspaceId : void 0,
3350
+ // Named even when it is the open one: batches sent after a switch stay in this workspace.
3351
+ workspaceExtId: workspaceId,
3340
3352
  onProgress: (loaded) => {
3341
3353
  loadedByBatch[index] = Math.min(loaded, bytes);
3342
3354
  report();
@@ -5205,8 +5217,8 @@ function useAttachRun(conversationId, responseId) {
5205
5217
  }
5206
5218
  const item = ev.item;
5207
5219
  if (item?.type === "message" && item.arbi?.label === "Answered") {
5208
- const text = Array.isArray(item.content) ? item.content.map((c) => c.text ?? "").join("") : "";
5209
- if (text) setMessageContent(queryClient, conversationId, responseId, text);
5220
+ const text2 = Array.isArray(item.content) ? item.content.map((c) => c.text ?? "").join("") : "";
5221
+ if (text2) setMessageContent(queryClient, conversationId, responseId, text2);
5210
5222
  }
5211
5223
  },
5212
5224
  onAgentControlState: (event) => {
@@ -5445,17 +5457,17 @@ function useConversation(options = {}) {
5445
5457
  [docs, deselected, agentId, stagedFiles]
5446
5458
  );
5447
5459
  const withStagedFiles = useCallback(
5448
- (text) => {
5460
+ (text2) => {
5449
5461
  const staged = stagedFiles.filter((file) => !deselected.has(file.id));
5450
- if (!agentId || staged.length === 0) return text;
5451
- return text + "\n\nSource files staged in your sandbox:\n" + staged.map((file) => `${file.name}: ${file.id}`).join("\n");
5462
+ if (!agentId || staged.length === 0) return text2;
5463
+ return text2 + "\n\nSource files staged in your sandbox:\n" + staged.map((file) => `${file.name}: ${file.id}`).join("\n");
5452
5464
  },
5453
5465
  [agentId, stagedFiles, deselected]
5454
5466
  );
5455
5467
  const { handleSendMessage, handleCreateBranch } = actions;
5456
5468
  const send = useCallback(
5457
- async (text) => {
5458
- const trimmed = text.trim();
5469
+ async (text2) => {
5470
+ const trimmed = text2.trim();
5459
5471
  if (!trimmed || isUpdatingAssistantMode) return;
5460
5472
  setHistoryError(null);
5461
5473
  session.setConversationDocuments(
@@ -5486,7 +5498,7 @@ function useConversation(options = {}) {
5486
5498
  ]
5487
5499
  );
5488
5500
  const branch = useCallback(
5489
- (parentId, text) => handleCreateBranch(parentId, withStagedFiles(text)),
5501
+ (parentId, text2) => handleCreateBranch(parentId, withStagedFiles(text2)),
5490
5502
  [handleCreateBranch, withStagedFiles]
5491
5503
  );
5492
5504
  const switchBranch = useCallback(
@@ -5819,6 +5831,18 @@ function useConversationTurn({
5819
5831
  ...actions
5820
5832
  };
5821
5833
  }
5834
+ function useActiveConfigId() {
5835
+ const chatModel = useArbiSessionState((s) => s.chatModel);
5836
+ const cursor = useArbiSessionState((s) => s.cursor);
5837
+ const { messageHistory } = useConversationData();
5838
+ const { data: userSettings } = useUserSettings();
5839
+ return useMemo(() => {
5840
+ if (chatModel) return chatModel;
5841
+ const parent = cursor ? messageHistory?.find((m) => m.external_id === cursor) : void 0;
5842
+ if (parent?.config_ext_id) return parent.config_ext_id;
5843
+ return userSettings?.last_config ?? void 0;
5844
+ }, [chatModel, cursor, messageHistory, userSettings?.last_config]);
5845
+ }
5822
5846
  var EMPTY_DOCS = [];
5823
5847
  function useConversationDocuments() {
5824
5848
  const currentConversationId = useArbiSessionState((state) => state.conversationId);
@@ -6298,9 +6322,9 @@ var ChatBubble = memo(function ChatBubble2({
6298
6322
  }
6299
6323
  );
6300
6324
  });
6301
- function hashText(text) {
6325
+ function hashText(text2) {
6302
6326
  let h = 5381;
6303
- for (let i = 0; i < text.length; i++) h = h * 33 ^ text.charCodeAt(i);
6327
+ for (let i = 0; i < text2.length; i++) h = h * 33 ^ text2.charCodeAt(i);
6304
6328
  return (h >>> 0).toString(36);
6305
6329
  }
6306
6330
  function createSkillPack({ id, skills, marker }) {
@@ -7190,25 +7214,55 @@ function useOpenSelectedWorkspace() {
7190
7214
  const { clearWorkspace, openSelectedWorkspace } = useSwitchWorkspace();
7191
7215
  const workspaceId = useArbiSessionState((s) => s.workspaceId);
7192
7216
  const status = useArbiSessionState((s) => s.workspaceStatus);
7193
- const { data: workspaces, isLoading: listing } = useWorkspaces();
7194
- const archived = workspaces?.find(
7195
- (w) => w.external_id === workspaceId && w.archive
7196
- );
7217
+ const session = useArbiSessionStore();
7218
+ const queryClient = useQueryClient();
7219
+ const { data: workspaces, isLoading: listing, isFetching } = useWorkspaces();
7220
+ const listed = workspaces;
7221
+ const archived = listed?.find((w) => w.external_id === workspaceId && w.archive);
7222
+ const reads = queryClient.getQueryState(arbiQueryKeys.workspaces())?.dataUpdateCount ?? 0;
7223
+ const opened = useRef({ id: null, reads: 0 });
7224
+ const openId = status === "open" ? workspaceId : null;
7225
+ if (opened.current.id !== openId) opened.current = { id: openId, reads };
7226
+ const gone = !!openId && !!listed && !isFetching && reads > opened.current.reads && !listed.some((w) => w.external_id === openId);
7197
7227
  useEffect(() => {
7198
7228
  if (!archived) return;
7199
7229
  notify.info(archivedWorkspaceMessage(archived.name));
7200
7230
  clearWorkspace();
7201
7231
  }, [archived, clearWorkspace]);
7232
+ useEffect(() => {
7233
+ if (gone) clearWorkspace();
7234
+ }, [gone, clearWorkspace]);
7202
7235
  const opening = useRef(false);
7203
7236
  const signedIn2 = arbi.isLoggedIn;
7204
7237
  useEffect(() => {
7205
- if (!workspaceId || archived || listing || status !== "closed" || !signedIn2 || opening.current)
7238
+ if (!workspaceId || archived || gone || listing || status !== "closed" || !signedIn2 || opening.current)
7206
7239
  return;
7207
7240
  opening.current = true;
7208
- void openSelectedWorkspace().finally(() => {
7241
+ void openSelectedWorkspace().then(async (ok) => {
7242
+ if (ok) return;
7243
+ const fresh = await queryClient.fetchQuery({
7244
+ queryKey: arbiQueryKeys.workspaces(),
7245
+ queryFn: () => arbi.workspaces.list(),
7246
+ staleTime: 0
7247
+ }).catch(() => null);
7248
+ if (fresh && session.getState().workspaceId === workspaceId && !fresh.some((w) => w.external_id === workspaceId))
7249
+ clearWorkspace();
7250
+ }).finally(() => {
7209
7251
  opening.current = false;
7210
7252
  });
7211
- }, [openSelectedWorkspace, workspaceId, archived, listing, status, signedIn2]);
7253
+ }, [
7254
+ arbi,
7255
+ session,
7256
+ clearWorkspace,
7257
+ openSelectedWorkspace,
7258
+ queryClient,
7259
+ workspaceId,
7260
+ archived,
7261
+ gone,
7262
+ listing,
7263
+ status,
7264
+ signedIn2
7265
+ ]);
7212
7266
  }
7213
7267
 
7214
7268
  // src/workspaces/shell-workspaces.ts
@@ -7706,7 +7760,10 @@ function useInvalidate() {
7706
7760
  const queryClient = useQueryClient();
7707
7761
  return {
7708
7762
  list: () => queryClient.invalidateQueries({ queryKey: arbiQueryKeys.databaseList() }),
7709
- rows: () => queryClient.invalidateQueries({ queryKey: arbiQueryKeys.databaseRows() }),
7763
+ rows: () => Promise.all([
7764
+ queryClient.invalidateQueries({ queryKey: arbiQueryKeys.databaseRows() }),
7765
+ queryClient.invalidateQueries({ queryKey: arbiQueryKeys.databaseAggregate() })
7766
+ ]),
7710
7767
  all: () => queryClient.invalidateQueries({ queryKey: arbiQueryKeys.databases() })
7711
7768
  };
7712
7769
  }
@@ -7739,6 +7796,16 @@ function useDatabaseRows(databaseId, q) {
7739
7796
  placeholderData: (previous) => previous
7740
7797
  });
7741
7798
  }
7799
+ function useDatabaseAggregate(databaseId, request, options) {
7800
+ const arbi = useArbi();
7801
+ return useQuery({
7802
+ queryKey: arbiQueryKeys.databaseAggregate(databaseId ?? "", request),
7803
+ queryFn: () => arbi.databases.aggregate(databaseId, request),
7804
+ enabled: (options?.enabled ?? true) && arbi.hasWorkspace && Boolean(databaseId),
7805
+ staleTime: 1e3 * 15,
7806
+ placeholderData: (previous) => previous
7807
+ });
7808
+ }
7742
7809
  function useSearchDatabaseRows() {
7743
7810
  const arbi = useArbi();
7744
7811
  return useCallback(
@@ -7800,6 +7867,7 @@ function useUpdateDatabaseRow() {
7800
7867
  (column) => column.id in (values ?? {}) && column.type === "relation" && column.relation?.database_id === databaseId
7801
7868
  );
7802
7869
  void invalidateRelatedRows(queryClient, databaseId, selfLinked);
7870
+ void queryClient.invalidateQueries({ queryKey: arbiQueryKeys.databaseAggregate() });
7803
7871
  },
7804
7872
  onError: () => {
7805
7873
  void queryClient.invalidateQueries({ queryKey: arbiQueryKeys.databaseRows() });
@@ -7837,6 +7905,1102 @@ function useExportDatabase() {
7837
7905
  [arbi]
7838
7906
  );
7839
7907
  }
7908
+
7909
+ // src/account/table-views.ts
7910
+ function isTableViewOf(view, workspaceId, table) {
7911
+ return view.workspace === workspaceId && (view.table ?? null) === table;
7912
+ }
7913
+ function viewsOfTable(all, workspaceId, table) {
7914
+ if (!workspaceId) return [];
7915
+ const byName = /* @__PURE__ */ new Map();
7916
+ for (const view of all ?? []) {
7917
+ if (isTableViewOf(view, workspaceId, table)) byName.set(view.name, view);
7918
+ }
7919
+ return [...byName.values()];
7920
+ }
7921
+
7922
+ // src/datasets/types.ts
7923
+ var AGGREGATE_FIELDS = {
7924
+ /** The group's label ("Open", "2026-06"). */
7925
+ group: "group",
7926
+ /** The group's key as grouped (a date bucket, an id), for ordering and links. */
7927
+ key: "key",
7928
+ /** The series' label (only with `splitBy`). */
7929
+ series: "series",
7930
+ /** The measured value; `null` when the group has no value to measure. */
7931
+ value: "value"
7932
+ };
7933
+
7934
+ // src/datasets/aggregate.ts
7935
+ var EMPTY_GROUP_LABEL = "(empty)";
7936
+ var MAX_SERIES = 12;
7937
+ var DEFAULT_LIMIT = 50;
7938
+ var pad = (n) => String(n).padStart(2, "0");
7939
+ function asDay(value) {
7940
+ if (typeof value !== "string" || value.length < 10) return null;
7941
+ const day = /* @__PURE__ */ new Date(`${value.slice(0, 10)}T00:00:00Z`);
7942
+ return Number.isNaN(day.getTime()) ? null : day;
7943
+ }
7944
+ function isoWeek(day) {
7945
+ const d = new Date(day);
7946
+ const weekday = d.getUTCDay() || 7;
7947
+ d.setUTCDate(d.getUTCDate() + 4 - weekday);
7948
+ const yearStart = Date.UTC(d.getUTCFullYear(), 0, 1);
7949
+ return [d.getUTCFullYear(), Math.ceil(((d.getTime() - yearStart) / 864e5 + 1) / 7)];
7950
+ }
7951
+ function bucketOf(value, bucket) {
7952
+ const day = asDay(value);
7953
+ if (!day) return null;
7954
+ const y = day.getUTCFullYear();
7955
+ const m = day.getUTCMonth() + 1;
7956
+ switch (bucket) {
7957
+ case "day":
7958
+ return `${y}-${pad(m)}-${pad(day.getUTCDate())}`;
7959
+ case "week": {
7960
+ const [wy, w] = isoWeek(day);
7961
+ return `${wy}-W${pad(w)}`;
7962
+ }
7963
+ case "quarter":
7964
+ return `${y}-Q${Math.floor((m - 1) / 3) + 1}`;
7965
+ case "year":
7966
+ return String(y);
7967
+ default:
7968
+ return `${y}-${pad(m)}`;
7969
+ }
7970
+ }
7971
+ function bucketStart(key, bucket) {
7972
+ const parts = key.match(/^(\d{4})(?:-(W|Q)?(\d{1,2}))?(?:-(\d{2}))?$/);
7973
+ if (!parts) return null;
7974
+ const year = Number(parts[1]);
7975
+ const n = Number(parts[3] ?? 1);
7976
+ switch (bucket) {
7977
+ case "day":
7978
+ return asDay(key);
7979
+ case "week": {
7980
+ const jan4 = new Date(Date.UTC(year, 0, 4));
7981
+ const monday = new Date(jan4);
7982
+ monday.setUTCDate(jan4.getUTCDate() - ((jan4.getUTCDay() || 7) - 1) + (n - 1) * 7);
7983
+ return monday;
7984
+ }
7985
+ case "quarter":
7986
+ return new Date(Date.UTC(year, (n - 1) * 3, 1));
7987
+ case "year":
7988
+ return new Date(Date.UTC(year, 0, 1));
7989
+ default:
7990
+ return new Date(Date.UTC(year, n - 1, 1));
7991
+ }
7992
+ }
7993
+ function nextBucket(day, bucket) {
7994
+ const d = new Date(day);
7995
+ if (bucket === "day") d.setUTCDate(d.getUTCDate() + 1);
7996
+ else if (bucket === "week") d.setUTCDate(d.getUTCDate() + 7);
7997
+ else if (bucket === "month") d.setUTCMonth(d.getUTCMonth() + 1);
7998
+ else if (bucket === "quarter") d.setUTCMonth(d.getUTCMonth() + 3);
7999
+ else d.setUTCFullYear(d.getUTCFullYear() + 1);
8000
+ return d;
8001
+ }
8002
+ function bucketRange(first, last, bucket, max = 500) {
8003
+ const start = bucketStart(first, bucket);
8004
+ const end = bucketStart(last, bucket);
8005
+ if (!start || !end || start > end) return null;
8006
+ const keys = [];
8007
+ for (let d = start; d <= end && keys.length <= max; d = nextBucket(d, bucket)) {
8008
+ keys.push(bucketOf(d.toISOString(), bucket));
8009
+ }
8010
+ return keys.length > max ? null : keys;
8011
+ }
8012
+ var isEmpty = (value) => value === null || value === void 0 || value === "" || Array.isArray(value) && !value.length;
8013
+ function groupKeys(value, field, bucket) {
8014
+ if (isEmpty(value)) return [""];
8015
+ if (Array.isArray(value)) {
8016
+ return [...new Set(value.map((v) => groupKeys(v, field, bucket)[0]))];
8017
+ }
8018
+ if (field.type === "date") return [bucketOf(value, bucket) ?? ""];
8019
+ if (typeof value === "boolean") return [value ? "Yes" : "No"];
8020
+ return [String(value)];
8021
+ }
8022
+ var lower = (v) => String(v).toLowerCase();
8023
+ function compare(value, filter, field) {
8024
+ const empty = isEmpty(value);
8025
+ if (filter.op === "empty") return empty;
8026
+ if (filter.op === "not_empty") return !empty;
8027
+ if (Array.isArray(value)) {
8028
+ const values = value;
8029
+ if (filter.op === "contains")
8030
+ return values.some((v) => lower(v).includes(lower(filter.value ?? "")));
8031
+ if (filter.op === "eq" || filter.op === "neq") {
8032
+ const hit = values.some((v) => lower(v) === lower(filter.value));
8033
+ return filter.op === "eq" ? hit : !hit;
8034
+ }
8035
+ return false;
8036
+ }
8037
+ const same = typeof value === "string" ? lower(value) === lower(filter.value) : value === filter.value;
8038
+ if (filter.op === "eq") return same;
8039
+ if (filter.op === "neq") return !same;
8040
+ if (filter.op === "contains") return !empty && lower(value).includes(lower(filter.value ?? ""));
8041
+ if (empty || filter.value === null || filter.value === void 0) return false;
8042
+ const [a, b] = field.type === "number" ? [Number(value), Number(filter.value)] : [String(value).slice(0, 19), String(filter.value).slice(0, 19)];
8043
+ return { gt: a > b, gte: a >= b, lt: a < b, lte: a <= b }[filter.op];
8044
+ }
8045
+ function recordsOf(dataset, query) {
8046
+ const rows = filterRows(dataset.rows, dataset.fields, query.filters);
8047
+ const order = query.orderBy;
8048
+ const field = order && dataset.fields.find((f) => f.id === order.field);
8049
+ if (order && field) {
8050
+ const dir = order.direction === "desc" ? -1 : 1;
8051
+ const key = (v) => Array.isArray(v) ? v.join(", ") : v;
8052
+ rows.sort((a, b) => {
8053
+ const x = key(a[field.id]);
8054
+ const y = key(b[field.id]);
8055
+ if (isEmpty(x) || isEmpty(y)) return isEmpty(x) === isEmpty(y) ? 0 : isEmpty(x) ? 1 : -1;
8056
+ if (typeof x === "number" && typeof y === "number") return dir * (x - y);
8057
+ return dir * String(x).localeCompare(String(y));
8058
+ });
8059
+ }
8060
+ return {
8061
+ fields: dataset.fields,
8062
+ rows: query.limit ? rows.slice(0, query.limit) : rows,
8063
+ totalRows: rows.length,
8064
+ truncated: !!query.limit && rows.length > query.limit
8065
+ };
8066
+ }
8067
+ function filterRows(rows, fields, filters = []) {
8068
+ if (!filters.length) return [...rows];
8069
+ const byId = new Map(fields.map((f) => [f.id, f]));
8070
+ return rows.filter(
8071
+ (row) => filters.every((filter) => {
8072
+ const field = byId.get(filter.field);
8073
+ return field ? compare(row[filter.field], filter, field) : false;
8074
+ })
8075
+ );
8076
+ }
8077
+ function measure(values, op, countRows) {
8078
+ if (op === "count") return countRows ? values.length : values.filter((v) => !isEmpty(v)).length;
8079
+ const numbers = values.filter((v) => typeof v === "number" && Number.isFinite(v));
8080
+ if (!numbers.length) return null;
8081
+ if (op === "sum") return numbers.reduce((a, b) => a + b, 0);
8082
+ if (op === "avg") return numbers.reduce((a, b) => a + b, 0) / numbers.length;
8083
+ return op === "min" ? Math.min(...numbers) : Math.max(...numbers);
8084
+ }
8085
+ function measureLabel(op, field) {
8086
+ return field ? `${op} of ${field.label}` : "count";
8087
+ }
8088
+ var labelOf = (key) => key === "" ? EMPTY_GROUP_LABEL : key;
8089
+ function aggregateFields(fields, query) {
8090
+ const byId = new Map(fields.map((f) => [f.id, f]));
8091
+ const group = query.groupBy ? byId.get(query.groupBy) : void 0;
8092
+ const split = query.splitBy ? byId.get(query.splitBy) : void 0;
8093
+ const op = query.measure?.op ?? "count";
8094
+ const value = query.measure?.field ? byId.get(query.measure.field) : void 0;
8095
+ return [
8096
+ { id: AGGREGATE_FIELDS.group, label: group?.label ?? "All", type: "string" },
8097
+ { id: AGGREGATE_FIELDS.key, label: group?.label ?? "All", type: "string" },
8098
+ ...split ? [{ id: AGGREGATE_FIELDS.series, label: split.label, type: "string" }] : [],
8099
+ {
8100
+ id: AGGREGATE_FIELDS.value,
8101
+ label: measureLabel(op, value),
8102
+ type: "number",
8103
+ ...value?.unit && op !== "count" ? { unit: value.unit } : {}
8104
+ }
8105
+ ];
8106
+ }
8107
+ function aggregateDataset(dataset, query) {
8108
+ const byId = new Map(dataset.fields.map((f) => [f.id, f]));
8109
+ const group = query.groupBy ? byId.get(query.groupBy) : void 0;
8110
+ const split = query.splitBy ? byId.get(query.splitBy) : void 0;
8111
+ const op = query.measure?.op ?? "count";
8112
+ const valueField = query.measure?.field ? byId.get(query.measure.field) : void 0;
8113
+ const bucket = query.bucket ?? "month";
8114
+ const fields = aggregateFields(dataset.fields, query);
8115
+ if (op !== "count" && valueField?.type !== "number") {
8116
+ throw new Error(`${op} needs a number field`);
8117
+ }
8118
+ const rows = filterRows(dataset.rows, dataset.fields, query.filters);
8119
+ const cells = /* @__PURE__ */ new Map();
8120
+ for (const row of rows) {
8121
+ const groups = group ? groupKeys(row[group.id], group, bucket) : ["All"];
8122
+ const splits = split ? groupKeys(row[split.id], split, bucket) : [""];
8123
+ const value = valueField ? row[valueField.id] ?? null : 1;
8124
+ for (const g of groups) {
8125
+ const bySplit = cells.get(g) ?? /* @__PURE__ */ new Map();
8126
+ cells.set(g, bySplit);
8127
+ for (const s of splits) bySplit.set(s, [...bySplit.get(s) ?? [], value]);
8128
+ }
8129
+ }
8130
+ const countRows = !valueField;
8131
+ const totals = new Map(
8132
+ [...cells].map(([g, bySplit]) => [g, measure([...bySplit.values()].flat(), op, countRows)])
8133
+ );
8134
+ const byLabel = (a, b) => a === "" ? 1 : b === "" ? -1 : a.localeCompare(b);
8135
+ const byValue = (dir) => (a, b) => a === "" !== (b === "") ? a === "" ? 1 : -1 : dir * ((totals.get(a) ?? 0) - (totals.get(b) ?? 0)) || byLabel(a, b);
8136
+ const sort = query.sort ?? (group?.type === "date" ? "label" : "value-desc");
8137
+ const keys = [...cells.keys()].sort(
8138
+ sort === "label" ? byLabel : byValue(sort === "value-asc" ? 1 : -1)
8139
+ );
8140
+ const limit = query.limit ?? DEFAULT_LIMIT;
8141
+ const kept = keys.slice(0, limit);
8142
+ let splitKeys = [""];
8143
+ if (split) {
8144
+ const splitTotals = /* @__PURE__ */ new Map();
8145
+ for (const g of kept) {
8146
+ for (const [s, values] of cells.get(g) ?? []) {
8147
+ splitTotals.set(s, (splitTotals.get(s) ?? 0) + (measure(values, op, countRows) ?? 0));
8148
+ }
8149
+ }
8150
+ splitKeys = [...splitTotals.keys()].sort(
8151
+ (a, b) => a === "" !== (b === "") ? a === "" ? 1 : -1 : (splitTotals.get(b) ?? 0) - (splitTotals.get(a) ?? 0) || byLabel(a, b)
8152
+ ).slice(0, MAX_SERIES);
8153
+ }
8154
+ const out = [];
8155
+ for (const g of kept) {
8156
+ for (const s of splitKeys) {
8157
+ const values = cells.get(g)?.get(s);
8158
+ out.push({
8159
+ [AGGREGATE_FIELDS.group]: labelOf(g),
8160
+ [AGGREGATE_FIELDS.key]: g,
8161
+ ...split ? { [AGGREGATE_FIELDS.series]: labelOf(s) } : {},
8162
+ [AGGREGATE_FIELDS.value]: values ? measure(values, op, countRows) : null
8163
+ });
8164
+ }
8165
+ }
8166
+ return { fields, rows: out, totalRows: rows.length, truncated: keys.length > limit };
8167
+ }
8168
+ function fillTimeGaps(dataset, bucket) {
8169
+ const keyId = AGGREGATE_FIELDS.key;
8170
+ const keys = [...new Set(dataset.rows.map((r) => String(r[keyId] ?? "")))].filter(Boolean);
8171
+ if (keys.length < 2) return dataset;
8172
+ const sorted = [...keys].sort();
8173
+ const range = bucketRange(sorted[0], sorted[sorted.length - 1], bucket);
8174
+ if (!range || range.length === keys.length) return dataset;
8175
+ const hasSeries = dataset.fields.some((f) => f.id === AGGREGATE_FIELDS.series);
8176
+ const seriesLabels = hasSeries ? [...new Set(dataset.rows.map((r) => String(r[AGGREGATE_FIELDS.series])))] : [null];
8177
+ const byKey = /* @__PURE__ */ new Map();
8178
+ for (const row of dataset.rows) {
8179
+ const k = String(row[keyId] ?? "");
8180
+ byKey.set(k, [...byKey.get(k) ?? [], row]);
8181
+ }
8182
+ const rows = [];
8183
+ for (const k of range) {
8184
+ const existing = byKey.get(k);
8185
+ if (existing) rows.push(...existing);
8186
+ else {
8187
+ for (const s of seriesLabels) {
8188
+ rows.push({
8189
+ [AGGREGATE_FIELDS.group]: k,
8190
+ [keyId]: k,
8191
+ ...hasSeries ? { [AGGREGATE_FIELDS.series]: s } : {},
8192
+ [AGGREGATE_FIELDS.value]: null
8193
+ });
8194
+ }
8195
+ }
8196
+ }
8197
+ rows.push(...byKey.get("") ?? []);
8198
+ return { ...dataset, rows };
8199
+ }
8200
+ function datasetOf(fields, rows, query) {
8201
+ return query.records ? recordsOf({ fields, rows }, query) : aggregateDataset({ fields, rows }, query);
8202
+ }
8203
+ function defineRowsSource(definition) {
8204
+ const { useFields, useRows } = definition;
8205
+ function useDataset(params, query, options) {
8206
+ const fields = useFields(params);
8207
+ const rows = useRows(params, options?.enabled ?? true);
8208
+ const result = useMemo(() => {
8209
+ if (!rows.rows) return { dataset: void 0, error: null };
8210
+ try {
8211
+ return { dataset: datasetOf(fields.fields, rows.rows, query), error: null };
8212
+ } catch (error) {
8213
+ return { dataset: void 0, error };
8214
+ }
8215
+ }, [fields.fields, rows.rows, query]);
8216
+ return {
8217
+ dataset: result.dataset,
8218
+ isLoading: rows.isLoading || fields.isLoading,
8219
+ error: rows.error ?? fields.error ?? result.error
8220
+ };
8221
+ }
8222
+ return {
8223
+ id: definition.id,
8224
+ label: definition.label,
8225
+ description: definition.description,
8226
+ params: definition.params,
8227
+ useFields,
8228
+ useDataset
8229
+ };
8230
+ }
8231
+ function staticFields(fields) {
8232
+ const state = { fields, isLoading: false, error: null };
8233
+ return () => state;
8234
+ }
8235
+ function queryOfChart(chart) {
8236
+ if (chart.type === "table" && !chart.x) {
8237
+ return {
8238
+ records: true,
8239
+ ...chart.filters?.length ? { filters: chart.filters } : {},
8240
+ ...chart.orderBy ? { orderBy: chart.orderBy } : {},
8241
+ ...chart.limit ? { limit: chart.limit } : {}
8242
+ };
8243
+ }
8244
+ const grouped = chart.type !== "metric";
8245
+ const split = grouped && chart.type !== "pie" && chart.type !== "donut" && chart.series;
8246
+ const op = chart.aggregate ?? "count";
8247
+ return {
8248
+ ...chart.filters?.length ? { filters: chart.filters } : {},
8249
+ ...grouped && chart.x ? { groupBy: chart.x, bucket: chart.bucket ?? "month" } : {},
8250
+ ...split ? { splitBy: chart.series } : {},
8251
+ measure: { op, ...chart.y ? { field: chart.y } : {} },
8252
+ ...chart.sort ? { sort: chart.sort } : {},
8253
+ ...chart.limit ? { limit: chart.limit } : {}
8254
+ };
8255
+ }
8256
+ var TRENDS = /* @__PURE__ */ new Set(["bar", "line", "area"]);
8257
+ function usePanelDataset(source, params, chart, options) {
8258
+ const paramsKey = JSON.stringify(params ?? {});
8259
+ const chartKey = JSON.stringify(chart);
8260
+ const stableParams = useMemo(() => JSON.parse(paramsKey), [paramsKey]);
8261
+ const query = useMemo(() => queryOfChart(JSON.parse(chartKey)), [chartKey]);
8262
+ const fields = source.useFields(stableParams);
8263
+ const state = source.useDataset(stableParams, query, options);
8264
+ const xField = fields.fields.find((f) => f.id === chart.x);
8265
+ const fillGaps = !!state.dataset && xField?.type === "date" && TRENDS.has(chart.type) && (chart.sort ?? "label") === "label";
8266
+ const dataset = useMemo(
8267
+ () => state.dataset && fillGaps ? fillTimeGaps(state.dataset, chart.bucket ?? "month") : state.dataset,
8268
+ [state.dataset, fillGaps, chart.bucket]
8269
+ );
8270
+ return { ...state, dataset, fields: fields.fields };
8271
+ }
8272
+ function namesOfWorkspaces(workspaces) {
8273
+ const names = /* @__PURE__ */ new Map();
8274
+ for (const w of workspaces ?? []) {
8275
+ if (w.name) names.set(w.external_id, w.name);
8276
+ for (const member of w.users ?? []) {
8277
+ const user = member.user;
8278
+ if (!user?.external_id || names.has(user.external_id)) continue;
8279
+ const name = [user.given_name, user.family_name].filter(Boolean).join(" ").trim();
8280
+ names.set(user.external_id, name || user.email || user.external_id);
8281
+ }
8282
+ }
8283
+ return names;
8284
+ }
8285
+ function useNames(enabled = true) {
8286
+ const { data } = useWorkspaces({ enabled });
8287
+ return useMemo(() => {
8288
+ const names = namesOfWorkspaces(data);
8289
+ return (id) => id ? names.get(id) ?? id : null;
8290
+ }, [data]);
8291
+ }
8292
+
8293
+ // src/datasets/sources/conversations.ts
8294
+ var DEFAULT_CONVERSATIONS_SOURCE_LABELS = {
8295
+ source: "Threads",
8296
+ description: "The threads and tasks of the open workspace: activity, status, owners, due dates.",
8297
+ title: "Title",
8298
+ created: "Started",
8299
+ lastActivity: "Last activity",
8300
+ due: "Due",
8301
+ completed: "Completed",
8302
+ kind: "Kind",
8303
+ thread: "Thread",
8304
+ task: "Task",
8305
+ status: "Status",
8306
+ statuses: { todo: "To do", generating: "Running", done: "Done" },
8307
+ overdue: "Overdue",
8308
+ owner: "Owner",
8309
+ messages: "Messages",
8310
+ shared: "Shared"
8311
+ };
8312
+ function createConversationsSource(labels) {
8313
+ const l = { ...DEFAULT_CONVERSATIONS_SOURCE_LABELS, ...labels };
8314
+ const fields = [
8315
+ { id: "title", label: l.title, type: "string" },
8316
+ { id: "created", label: l.created, type: "date" },
8317
+ { id: "lastActivity", label: l.lastActivity, type: "date" },
8318
+ { id: "due", label: l.due, type: "date" },
8319
+ { id: "completed", label: l.completed, type: "date" },
8320
+ { id: "kind", label: l.kind, type: "string", options: [l.thread, l.task] },
8321
+ { id: "status", label: l.status, type: "string", options: Object.values(l.statuses) },
8322
+ { id: "overdue", label: l.overdue, type: "boolean" },
8323
+ { id: "owner", label: l.owner, type: "string" },
8324
+ { id: "messages", label: l.messages, type: "number" },
8325
+ { id: "shared", label: l.shared, type: "boolean" }
8326
+ ];
8327
+ return defineRowsSource({
8328
+ id: "conversations",
8329
+ label: l.source,
8330
+ description: l.description,
8331
+ useFields: staticFields(fields),
8332
+ useRows(params, enabled) {
8333
+ const arbi = useArbi();
8334
+ const workspaceId = typeof params.workspaceId === "string" && params.workspaceId ? params.workspaceId : arbi.hasWorkspace ? arbi.getWorkspaceId() : void 0;
8335
+ const query = useConversations(workspaceId, { enabled });
8336
+ const nameOf = useNames(enabled);
8337
+ const rows = useMemo(() => {
8338
+ const now = (/* @__PURE__ */ new Date()).toISOString();
8339
+ return query.data?.map((c) => ({
8340
+ title: c.title || null,
8341
+ created: c.created_at ?? null,
8342
+ lastActivity: c.last_message_updated_at ?? c.updated_at ?? null,
8343
+ due: c.due_at ?? null,
8344
+ completed: c.completed_at ?? null,
8345
+ kind: c.status ? l.task : l.thread,
8346
+ status: c.status ? l.statuses[c.status] : null,
8347
+ overdue: Boolean(c.due_at && c.status !== "done" && c.due_at < now),
8348
+ owner: nameOf(c.owner_ext_id ?? c.created_by_ext_id),
8349
+ messages: c.message_count ?? null,
8350
+ shared: c.is_shared ?? null
8351
+ }));
8352
+ }, [query.data, nameOf]);
8353
+ return { rows, isLoading: query.isLoading && !!workspaceId, error: query.error };
8354
+ }
8355
+ });
8356
+ }
8357
+ var DEFAULT_DATABASE_SOURCE_LABELS = {
8358
+ source: "Database",
8359
+ description: "A database of the open workspace, or one of its saved views.",
8360
+ database: "Database",
8361
+ view: "Saved view",
8362
+ allColumns: "All columns"
8363
+ };
8364
+ var MULTI = /* @__PURE__ */ new Set(["document", "relation", "lookup", "tag"]);
8365
+ function fieldOfColumn(column) {
8366
+ const type = column.type === "number" || column.type === "rollup" ? "number" : column.type === "date" ? "date" : column.type === "checkbox" ? "boolean" : "string";
8367
+ return {
8368
+ id: column.id,
8369
+ label: column.name,
8370
+ type,
8371
+ ...column.options?.length ? { options: column.options } : {},
8372
+ ...MULTI.has(column.type) ? { multiple: true } : {}
8373
+ };
8374
+ }
8375
+ var text = (v) => typeof v === "string" && v ? v : void 0;
8376
+ function databaseFields(database, view) {
8377
+ const columns = database?.columns ?? [];
8378
+ if (!view?.columns?.length) return columns.map(fieldOfColumn);
8379
+ const byId = new Map(columns.map((c) => [c.id, c]));
8380
+ return view.columns.flatMap((id) => {
8381
+ const column = byId.get(id);
8382
+ return column ? [fieldOfColumn(column)] : [];
8383
+ });
8384
+ }
8385
+ function aggregateRequest(query) {
8386
+ return {
8387
+ group_by: query.groupBy ?? null,
8388
+ split_by: query.splitBy ?? null,
8389
+ time_bucket: query.bucket ?? "month",
8390
+ measure: { op: query.measure?.op ?? "count", column: query.measure?.field ?? null },
8391
+ filters: (query.filters ?? []).map((f) => ({ column: f.field, op: f.op, value: f.value })),
8392
+ limit: query.limit ?? 50
8393
+ };
8394
+ }
8395
+ function datasetOfAggregate(result, fields, query) {
8396
+ const split = Boolean(query.splitBy);
8397
+ let order = result.keys.map((_, i) => i);
8398
+ const total = (i) => result.series.reduce((sum, s) => sum + (s.values[i] ?? 0), 0);
8399
+ if (query.sort === "label") {
8400
+ order = [...order].sort(
8401
+ (a, b) => result.keys[a] === "" ? 1 : result.keys[b] === "" ? -1 : result.labels[a].localeCompare(result.labels[b])
8402
+ );
8403
+ } else if (query.sort === "value-asc") {
8404
+ order = [...order].sort((a, b) => total(a) - total(b));
8405
+ } else if (query.sort === "value-desc") {
8406
+ order = [...order].sort((a, b) => total(b) - total(a));
8407
+ }
8408
+ const rows = order.flatMap(
8409
+ (i) => result.series.map((s) => ({
8410
+ [AGGREGATE_FIELDS.group]: result.labels[i],
8411
+ [AGGREGATE_FIELDS.key]: result.keys[i],
8412
+ ...split ? { [AGGREGATE_FIELDS.series]: s.label } : {},
8413
+ [AGGREGATE_FIELDS.value]: s.values[i] ?? null
8414
+ }))
8415
+ );
8416
+ return {
8417
+ fields: aggregateFields(fields, query),
8418
+ rows,
8419
+ totalRows: result.total_rows,
8420
+ truncated: result.truncated
8421
+ };
8422
+ }
8423
+ function datasetRowOf(row, fields) {
8424
+ const titles = row.titles ?? {};
8425
+ const out = {};
8426
+ for (const field of fields) {
8427
+ const raw = row.values[field.id];
8428
+ if (raw === null || raw === void 0) out[field.id] = null;
8429
+ else if (Array.isArray(raw)) out[field.id] = raw.map((v) => titles[String(v)] ?? String(v));
8430
+ else if (typeof raw === "string")
8431
+ out[field.id] = field.type === "string" ? titles[raw] ?? raw : raw;
8432
+ else if (typeof raw === "number" || typeof raw === "boolean") out[field.id] = raw;
8433
+ else out[field.id] = String(raw);
8434
+ }
8435
+ return out;
8436
+ }
8437
+ function createDatabaseSource(labels) {
8438
+ const l = { ...DEFAULT_DATABASE_SOURCE_LABELS, ...labels };
8439
+ function useView(params) {
8440
+ const arbi = useArbi();
8441
+ const databaseId = text(params.databaseId);
8442
+ const viewName = text(params.view);
8443
+ const settings = useUserSettings({ enabled: Boolean(viewName) });
8444
+ const workspaceId = arbi.hasWorkspace ? arbi.getWorkspaceId() : null;
8445
+ return useMemo(
8446
+ () => viewName && databaseId ? viewsOfTable(settings.data?.tableviews, workspaceId, databaseId).find(
8447
+ (v) => v.name === viewName
8448
+ ) : void 0,
8449
+ [settings.data?.tableviews, workspaceId, databaseId, viewName]
8450
+ );
8451
+ }
8452
+ function useFields(params) {
8453
+ const databaseId = text(params.databaseId) ?? null;
8454
+ const database = useDatabase(databaseId);
8455
+ const view = useView(params);
8456
+ const fields = useMemo(() => databaseFields(database.data, view), [database.data, view]);
8457
+ return { fields, isLoading: database.isLoading && !!databaseId, error: database.error };
8458
+ }
8459
+ function useDataset(params, query, options) {
8460
+ const databaseId = text(params.databaseId) ?? null;
8461
+ const enabled = options?.enabled ?? true;
8462
+ const fields = useFields(params);
8463
+ const grouped = !query.records;
8464
+ const request = useMemo(() => grouped ? aggregateRequest(query) : {}, [grouped, query]);
8465
+ const aggregate = useDatabaseAggregate(databaseId, request, { enabled: enabled && grouped });
8466
+ const rows = useDatabaseRows(enabled && !grouped ? databaseId : null, "");
8467
+ const dataset = useMemo(() => {
8468
+ if (grouped) {
8469
+ return aggregate.data ? datasetOfAggregate(aggregate.data, fields.fields, query) : void 0;
8470
+ }
8471
+ if (!rows.data) return void 0;
8472
+ const records = rows.data.rows.map((r) => datasetRowOf(r, fields.fields));
8473
+ return recordsOf({ fields: fields.fields, rows: records }, query);
8474
+ }, [grouped, query, aggregate.data, rows.data, fields.fields]);
8475
+ const active = grouped ? aggregate : rows;
8476
+ return {
8477
+ dataset,
8478
+ isLoading: !!databaseId && (active.isLoading || fields.isLoading),
8479
+ error: active.error ?? fields.error
8480
+ };
8481
+ }
8482
+ return {
8483
+ id: "database",
8484
+ label: l.source,
8485
+ description: l.description,
8486
+ params: [
8487
+ {
8488
+ id: "databaseId",
8489
+ label: l.database,
8490
+ required: true,
8491
+ useOptions() {
8492
+ const databases = useDatabases();
8493
+ const options = useMemo(
8494
+ () => (databases.data ?? []).map((d) => ({ value: d.id, label: d.name })),
8495
+ [databases.data]
8496
+ );
8497
+ return { options, isLoading: databases.isLoading };
8498
+ }
8499
+ },
8500
+ {
8501
+ id: "view",
8502
+ label: l.view,
8503
+ placeholder: l.allColumns,
8504
+ useOptions(params) {
8505
+ const arbi = useArbi();
8506
+ const databaseId = text(params.databaseId);
8507
+ const settings = useUserSettings({ enabled: Boolean(databaseId) });
8508
+ const workspaceId = arbi.hasWorkspace ? arbi.getWorkspaceId() : null;
8509
+ const options = useMemo(
8510
+ () => databaseId ? viewsOfTable(settings.data?.tableviews, workspaceId, databaseId).map((v) => ({
8511
+ value: v.name,
8512
+ label: v.name
8513
+ })) : [],
8514
+ [settings.data?.tableviews, workspaceId, databaseId]
8515
+ );
8516
+ return { options, isLoading: settings.isLoading && !!databaseId };
8517
+ }
8518
+ }
8519
+ ],
8520
+ useFields,
8521
+ useDataset
8522
+ };
8523
+ }
8524
+ var DEFAULT_DOCUMENTS_SOURCE_LABELS = {
8525
+ source: "Documents",
8526
+ description: "The documents of the open workspace: type, folder, status, dates.",
8527
+ created: "Added",
8528
+ updated: "Updated",
8529
+ documentDate: "Document date",
8530
+ status: "Status",
8531
+ type: "Type",
8532
+ folder: "Folder",
8533
+ nature: "Kind of document",
8534
+ author: "Author",
8535
+ createdBy: "Added by",
8536
+ pages: "Pages",
8537
+ size: "Size",
8538
+ shared: "Shared"
8539
+ };
8540
+ var workspaceOf2 = (params) => typeof params.workspaceId === "string" && params.workspaceId ? params.workspaceId : void 0;
8541
+ function createDocumentsSource(labels) {
8542
+ const l = { ...DEFAULT_DOCUMENTS_SOURCE_LABELS, ...labels };
8543
+ const fields = [
8544
+ { id: "name", label: l.source, type: "string" },
8545
+ { id: "created", label: l.created, type: "date" },
8546
+ { id: "updated", label: l.updated, type: "date" },
8547
+ { id: "documentDate", label: l.documentDate, type: "date" },
8548
+ { id: "status", label: l.status, type: "string" },
8549
+ { id: "type", label: l.type, type: "string" },
8550
+ { id: "folder", label: l.folder, type: "string" },
8551
+ { id: "nature", label: l.nature, type: "string" },
8552
+ { id: "author", label: l.author, type: "string" },
8553
+ { id: "createdBy", label: l.createdBy, type: "string" },
8554
+ { id: "pages", label: l.pages, type: "number" },
8555
+ { id: "size", label: l.size, type: "number", unit: "bytes" },
8556
+ { id: "shared", label: l.shared, type: "boolean" }
8557
+ ];
8558
+ return defineRowsSource({
8559
+ id: "documents",
8560
+ label: l.source,
8561
+ description: l.description,
8562
+ useFields: staticFields(fields),
8563
+ useRows(params, enabled) {
8564
+ const query = useDocuments(workspaceOf2(params), { enabled });
8565
+ const nameOf = useNames(enabled);
8566
+ const rows = useMemo(
8567
+ () => query.data?.map((d) => ({
8568
+ name: d.doc_metadata?.title || d.file_name || d.external_id,
8569
+ created: d.created_at ?? null,
8570
+ updated: d.updated_at ?? null,
8571
+ documentDate: d.doc_metadata?.doc_date ?? null,
8572
+ status: d.status ?? null,
8573
+ type: friendlyFileType(d.file_type, d.file_name) || null,
8574
+ folder: d.folder || null,
8575
+ nature: d.doc_metadata?.doc_nature ?? null,
8576
+ author: d.doc_metadata?.doc_author ?? null,
8577
+ createdBy: nameOf(d.created_by_ext_id),
8578
+ pages: d.n_pages ?? null,
8579
+ size: d.file_size ?? null,
8580
+ shared: d.shared ?? null
8581
+ })),
8582
+ [query.data, nameOf]
8583
+ );
8584
+ return { rows, isLoading: query.isLoading, error: query.error };
8585
+ }
8586
+ });
8587
+ }
8588
+ var DEFAULT_PROJECTS_SOURCE_LABELS = {
8589
+ source: "Projects",
8590
+ description: "Your projects: stage, lead, client and their own fields; opened and closed.",
8591
+ name: "Name",
8592
+ opened: "Opened",
8593
+ stage: "Stage",
8594
+ stageChanged: "Stage changed",
8595
+ lead: "Lead",
8596
+ client: "Client",
8597
+ plan: "Plan",
8598
+ state: "Open or closed",
8599
+ open: "Open",
8600
+ closed: "Closed",
8601
+ closedAt: "Closed"
8602
+ };
8603
+ var FIELD_PREFIX = "field:";
8604
+ function hostField(entry) {
8605
+ const type = entry.type === "number" || entry.type === "rollup" ? "number" : entry.type === "date" ? "date" : entry.type === "checkbox" ? "boolean" : "string";
8606
+ return {
8607
+ id: `${FIELD_PREFIX}${entry.key}`,
8608
+ label: entry.label || entry.key,
8609
+ type,
8610
+ ...entry.options?.length ? { options: entry.options } : {}
8611
+ };
8612
+ }
8613
+ function hostValue(value, field) {
8614
+ if (value === null || value === void 0 || value === "") return null;
8615
+ if (Array.isArray(value)) return value.map(String);
8616
+ if (field.type === "number") return typeof value === "number" ? value : Number(value) || null;
8617
+ if (field.type === "boolean") return Boolean(value);
8618
+ return String(value);
8619
+ }
8620
+ function createProjectsSource(options = {}) {
8621
+ const l = { ...DEFAULT_PROJECTS_SOURCE_LABELS, ...options.labels };
8622
+ const closing = new Set((options.closedStages ?? []).map((s) => s.toLowerCase()));
8623
+ const base = [
8624
+ { id: "name", label: l.name, type: "string" },
8625
+ { id: "opened", label: l.opened, type: "date" },
8626
+ { id: "stage", label: l.stage, type: "string" },
8627
+ { id: "stageChanged", label: l.stageChanged, type: "date" },
8628
+ { id: "lead", label: l.lead, type: "string" },
8629
+ { id: "client", label: l.client, type: "string" },
8630
+ { id: "plan", label: l.plan, type: "string" },
8631
+ ...closing.size ? [
8632
+ { id: "state", label: l.state, type: "string", options: [l.open, l.closed] },
8633
+ { id: "closedAt", label: l.closedAt, type: "date" }
8634
+ ] : []
8635
+ ];
8636
+ function fieldsOf(projects) {
8637
+ const seen = /* @__PURE__ */ new Map();
8638
+ for (const p of projects ?? []) {
8639
+ for (const entry of p.field_schema ?? []) {
8640
+ if (!seen.has(entry.key)) seen.set(entry.key, hostField(entry));
8641
+ }
8642
+ }
8643
+ return [...base, ...seen.values()];
8644
+ }
8645
+ return defineRowsSource({
8646
+ id: "projects",
8647
+ label: l.source,
8648
+ description: l.description,
8649
+ useFields() {
8650
+ const query = useProjects();
8651
+ const fields = useMemo(
8652
+ () => fieldsOf(query.data),
8653
+ [query.data]
8654
+ );
8655
+ return { fields, isLoading: query.isLoading, error: query.error };
8656
+ },
8657
+ useRows(_params, enabled) {
8658
+ const query = useProjects({ enabled });
8659
+ const nameOf = useNames(enabled);
8660
+ const rows = useMemo(() => {
8661
+ const projects = query.data;
8662
+ if (!projects) return void 0;
8663
+ const host = fieldsOf(projects).filter((f) => f.id.startsWith(FIELD_PREFIX));
8664
+ const people = new Set(
8665
+ projects.flatMap(
8666
+ (p) => (p.field_schema ?? []).filter((e) => e.type === "person").map((e) => e.key)
8667
+ )
8668
+ );
8669
+ return projects.map((p) => {
8670
+ const closed = !!p.stage && closing.has(p.stage.toLowerCase());
8671
+ const row = {
8672
+ name: p.name,
8673
+ opened: p.created_at,
8674
+ stage: p.stage ?? null,
8675
+ stageChanged: p.stage_changed_at ?? null,
8676
+ lead: nameOf(p.lead_user),
8677
+ client: p.client ?? null,
8678
+ plan: p.subscription ?? null
8679
+ };
8680
+ if (closing.size) {
8681
+ row.state = closed ? l.closed : l.open;
8682
+ row.closedAt = closed ? p.stage_changed_at ?? null : null;
8683
+ }
8684
+ for (const field of host) {
8685
+ const key = field.id.slice(FIELD_PREFIX.length);
8686
+ const value = hostValue(p.fields?.[key], field);
8687
+ row[field.id] = people.has(key) && value !== null ? Array.isArray(value) ? value.map((id) => nameOf(id) ?? id) : nameOf(String(value)) : value;
8688
+ }
8689
+ return row;
8690
+ });
8691
+ }, [query.data, nameOf]);
8692
+ return { rows, isLoading: query.isLoading, error: query.error };
8693
+ }
8694
+ });
8695
+ }
8696
+ var MODEL_GROUP_LABELS = {
8697
+ "arbi-transcribe-diarized": "Transcription (diarized)",
8698
+ "arbi-transcribe": "Transcription"
8699
+ };
8700
+ var DEFAULT_USAGE_SOURCE_LABELS = {
8701
+ source: "AI usage",
8702
+ description: "AI usage of your projects by day and model: \xA3 (ex VAT), tokens and requests.",
8703
+ period: "Period",
8704
+ periods: { current: "This period", previous: "Last period" },
8705
+ day: "Day",
8706
+ project: "Project",
8707
+ model: "Model",
8708
+ spend: "AI usage (\xA3)",
8709
+ tokens: "Tokens",
8710
+ requests: "Requests"
8711
+ };
8712
+ var monthsBackOf = (params) => String(params.period ?? "0") === "1" ? 1 : 0;
8713
+ function usageRows(usage, project, modelLabel = (g) => MODEL_GROUP_LABELS[g] ?? g) {
8714
+ return (usage.daily ?? []).flatMap(
8715
+ (day) => Object.entries(day.model_groups ?? {}).map(([group, mg]) => ({
8716
+ day: day.date,
8717
+ project,
8718
+ model: modelLabel(group),
8719
+ spend: mg.spend ?? 0,
8720
+ tokens: mg.total_tokens ?? 0,
8721
+ requests: (mg.successful_requests ?? 0) + (mg.failed_requests ?? 0)
8722
+ }))
8723
+ );
8724
+ }
8725
+ function createUsageSource(labels) {
8726
+ const l = { ...DEFAULT_USAGE_SOURCE_LABELS, ...labels };
8727
+ const fields = [
8728
+ { id: "day", label: l.day, type: "date" },
8729
+ { id: "project", label: l.project, type: "string" },
8730
+ { id: "model", label: l.model, type: "string" },
8731
+ { id: "spend", label: l.spend, type: "number", unit: "gbp" },
8732
+ { id: "tokens", label: l.tokens, type: "number", unit: "tokens" },
8733
+ { id: "requests", label: l.requests, type: "number" }
8734
+ ];
8735
+ const periodOptions = {
8736
+ options: [
8737
+ { value: "0", label: l.periods.current },
8738
+ { value: "1", label: l.periods.previous }
8739
+ ],
8740
+ isLoading: false
8741
+ };
8742
+ return defineRowsSource({
8743
+ id: "usage",
8744
+ label: l.source,
8745
+ description: l.description,
8746
+ params: [
8747
+ {
8748
+ id: "period",
8749
+ label: l.period,
8750
+ placeholder: l.periods.current,
8751
+ useOptions: () => periodOptions
8752
+ }
8753
+ ],
8754
+ useFields: staticFields(fields),
8755
+ useRows(params, enabled) {
8756
+ const arbi = useArbi();
8757
+ const monthsBack = monthsBackOf(params);
8758
+ const projects = useProjects({ enabled });
8759
+ const list = projects.data ?? [];
8760
+ const results = useQueries({
8761
+ queries: list.map((p) => ({
8762
+ queryKey: arbiQueryKeys.projectUsage(p.external_id, monthsBack),
8763
+ queryFn: () => arbi.projects.usage(p.external_id, monthsBack),
8764
+ enabled: enabled && arbi.isLoggedIn
8765
+ }))
8766
+ });
8767
+ const signature = results.map((r) => `${r.status}:${r.dataUpdatedAt}`).join("|");
8768
+ const rows = useMemo(() => {
8769
+ if (!projects.data || results.some((r) => r.isLoading)) return void 0;
8770
+ return results.flatMap(
8771
+ (r, i) => r.data ? usageRows(r.data, list[i].name) : []
8772
+ );
8773
+ }, [projects.data, signature]);
8774
+ return {
8775
+ rows,
8776
+ isLoading: projects.isLoading || results.some((r) => r.isLoading),
8777
+ error: projects.error ?? results.find((r) => r.error)?.error ?? null
8778
+ };
8779
+ }
8780
+ });
8781
+ }
8782
+ var DEFAULT_WORKSPACES_SOURCE_LABELS = {
8783
+ source: "Workspaces",
8784
+ description: "Your workspaces: their project, documents, threads, members and storage.",
8785
+ name: "Workspace",
8786
+ project: "Project",
8787
+ documents: "Documents",
8788
+ threads: "Threads",
8789
+ members: "Members",
8790
+ storage: "Storage (MB)",
8791
+ created: "Created",
8792
+ updated: "Updated",
8793
+ shared: "Public"
8794
+ };
8795
+ function createWorkspacesSource(labels) {
8796
+ const l = { ...DEFAULT_WORKSPACES_SOURCE_LABELS, ...labels };
8797
+ const fields = [
8798
+ { id: "name", label: l.name, type: "string" },
8799
+ { id: "project", label: l.project, type: "string" },
8800
+ { id: "documents", label: l.documents, type: "number" },
8801
+ { id: "threads", label: l.threads, type: "number" },
8802
+ { id: "members", label: l.members, type: "number" },
8803
+ { id: "storage", label: l.storage, type: "number", unit: "MB" },
8804
+ { id: "created", label: l.created, type: "date" },
8805
+ { id: "updated", label: l.updated, type: "date" },
8806
+ { id: "shared", label: l.shared, type: "boolean" }
8807
+ ];
8808
+ return defineRowsSource({
8809
+ id: "workspaces",
8810
+ label: l.source,
8811
+ description: l.description,
8812
+ useFields: staticFields(fields),
8813
+ useRows(_params, enabled) {
8814
+ const workspaces = useWorkspaces({ enabled });
8815
+ const projects = useProjects({ enabled });
8816
+ const rows = useMemo(() => {
8817
+ const list = workspaces.data;
8818
+ if (!list) return void 0;
8819
+ const projectNames = new Map(
8820
+ (projects.data ?? []).map((p) => [
8821
+ p.external_id,
8822
+ p.name
8823
+ ])
8824
+ );
8825
+ return list.map((w) => ({
8826
+ name: w.name,
8827
+ project: w.project_ext_id ? projectNames.get(w.project_ext_id) ?? null : null,
8828
+ documents: (w.shared_document_count ?? 0) + (w.private_document_count ?? 0),
8829
+ threads: (w.shared_conversation_count ?? 0) + (w.private_conversation_count ?? 0),
8830
+ members: w.users?.length ?? 0,
8831
+ storage: Math.round((w.user_files_mb ?? 0) * 10) / 10,
8832
+ created: w.created_at ?? null,
8833
+ updated: w.updated_at ?? null,
8834
+ shared: w.is_public ?? null
8835
+ }));
8836
+ }, [workspaces.data, projects.data]);
8837
+ return { rows, isLoading: workspaces.isLoading, error: workspaces.error };
8838
+ }
8839
+ });
8840
+ }
8841
+
8842
+ // src/datasets/registry.ts
8843
+ var BUILTIN_DATA_SOURCES = [
8844
+ createUsageSource(),
8845
+ createDocumentsSource(),
8846
+ createConversationsSource(),
8847
+ createProjectsSource(),
8848
+ createWorkspacesSource(),
8849
+ createDatabaseSource()
8850
+ ];
8851
+ function createDataSourceRegistry(sources) {
8852
+ const byId = /* @__PURE__ */ new Map();
8853
+ for (const source of sources) byId.set(source.id, source);
8854
+ const list = [...byId.values()];
8855
+ return { list, get: (id) => byId.get(id) };
8856
+ }
8857
+ function useDataSources() {
8858
+ const { dashboards } = useArbiHost();
8859
+ return useMemo(
8860
+ () => createDataSourceRegistry([
8861
+ ...dashboards?.builtins === false ? [] : BUILTIN_DATA_SOURCES,
8862
+ ...dashboards?.sources ?? []
8863
+ ]),
8864
+ [dashboards]
8865
+ );
8866
+ }
8867
+ var MAX_DASHBOARD_SPEC_CHARS = 1e4;
8868
+ var isObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
8869
+ function isPanel(v) {
8870
+ return isObject(v) && typeof v.id === "string" && typeof v.title === "string" && isObject(v.source) && typeof v.source.id === "string" && isObject(v.chart) && typeof v.chart.type === "string";
8871
+ }
8872
+ function parseDashboardSpec(value) {
8873
+ let parsed = value;
8874
+ if (typeof value === "string") {
8875
+ try {
8876
+ parsed = JSON.parse(value);
8877
+ } catch {
8878
+ return null;
8879
+ }
8880
+ }
8881
+ if (!isObject(parsed) || parsed.version !== 1 || typeof parsed.title !== "string") return null;
8882
+ const panels = Array.isArray(parsed.panels) ? parsed.panels.filter(isPanel) : [];
8883
+ return {
8884
+ version: 1,
8885
+ title: parsed.title,
8886
+ ...typeof parsed.description === "string" ? { description: parsed.description } : {},
8887
+ panels
8888
+ };
8889
+ }
8890
+ function serializeDashboardSpec(spec, max = MAX_DASHBOARD_SPEC_CHARS) {
8891
+ const json = JSON.stringify(spec);
8892
+ if (json.length > max) {
8893
+ throw new Error(
8894
+ `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.`
8895
+ );
8896
+ }
8897
+ return json;
8898
+ }
8899
+ function createMemoryDashboardStore(initial = [], scope = "memory") {
8900
+ let items = [...initial];
8901
+ let next = items.length + 1;
8902
+ return {
8903
+ scope,
8904
+ list: async () => items.map((d) => ({ ...d })),
8905
+ save: async ({ id, spec }) => {
8906
+ const saved = { id: id ?? `dash-${next++}`, spec, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
8907
+ items = id ? items.map((d) => d.id === id ? saved : d) : [...items, saved];
8908
+ return saved;
8909
+ },
8910
+ remove: async (id) => {
8911
+ items = items.filter((d) => d.id !== id);
8912
+ }
8913
+ };
8914
+ }
8915
+ var NAME_COLUMN = "Name";
8916
+ var SPEC_COLUMN = "Spec";
8917
+ function useDatabaseDashboardStore(options = {}) {
8918
+ const arbi = useArbi();
8919
+ const queryClient = useQueryClient();
8920
+ const name = options.name ?? "Dashboards";
8921
+ const workspaceId = arbi.hasWorkspace ? arbi.getWorkspaceId() : null;
8922
+ return useMemo(() => {
8923
+ async function find() {
8924
+ const all = await arbi.databases.list();
8925
+ return all.find(
8926
+ (d) => d.editable && d.workspace_id === workspaceId && d.name === name && (d.columns ?? []).some((c) => c.name === SPEC_COLUMN)
8927
+ );
8928
+ }
8929
+ async function ensure() {
8930
+ const found = await find();
8931
+ if (found) return found;
8932
+ const created = await arbi.databases.create({
8933
+ name,
8934
+ description: "Saved dashboards (written by the Dashboards page).",
8935
+ columns: [
8936
+ { name: NAME_COLUMN, type: "text" },
8937
+ { name: SPEC_COLUMN, type: "text" }
8938
+ ]
8939
+ });
8940
+ void queryClient.invalidateQueries({ queryKey: arbiQueryKeys.databaseList() });
8941
+ return created;
8942
+ }
8943
+ return {
8944
+ scope: workspaceId,
8945
+ async list() {
8946
+ const database = await find();
8947
+ if (!database) return [];
8948
+ const spec = database.columns?.find((c) => c.name === SPEC_COLUMN)?.id ?? SPEC_COLUMN;
8949
+ const page = await arbi.databases.rows(database.id, { limit: 1e3 });
8950
+ return page.rows.flatMap((row) => {
8951
+ const parsed = parseDashboardSpec(row.values[spec]);
8952
+ return parsed ? [{ id: row.id, spec: parsed, updatedAt: row.updated_at }] : [];
8953
+ });
8954
+ },
8955
+ async save({ id, spec }) {
8956
+ const values = { [NAME_COLUMN]: spec.title, [SPEC_COLUMN]: serializeDashboardSpec(spec) };
8957
+ const database = await ensure();
8958
+ const row = id ? await arbi.databases.updateRow(database.id, id, values) : (await arbi.databases.addRows(database.id, [{ values }]))[0];
8959
+ return { id: row.id, spec, updatedAt: row.updated_at };
8960
+ },
8961
+ async remove(id) {
8962
+ const database = await find();
8963
+ if (database) await arbi.databases.deleteRows(database.id, [id]);
8964
+ }
8965
+ };
8966
+ }, [arbi, queryClient, name, workspaceId]);
8967
+ }
8968
+ function useDashboardStore() {
8969
+ const { dashboards } = useArbiHost();
8970
+ return (dashboards?.useStore ?? useDatabaseDashboardStore)();
8971
+ }
8972
+ function useSavedDashboards(store) {
8973
+ return useQuery({
8974
+ queryKey: arbiQueryKeys.dashboards(store.scope ?? ""),
8975
+ queryFn: () => store.list(),
8976
+ enabled: store.scope !== null
8977
+ });
8978
+ }
8979
+ function useSaveDashboard(store) {
8980
+ const queryClient = useQueryClient();
8981
+ const key = arbiQueryKeys.dashboards(store.scope ?? "");
8982
+ return useMutation({
8983
+ mutationFn: (dashboard) => store.save(dashboard),
8984
+ onSuccess: (saved) => {
8985
+ queryClient.setQueryData(
8986
+ key,
8987
+ (old = []) => old.some((d) => d.id === saved.id) ? old.map((d) => d.id === saved.id ? saved : d) : [...old, saved]
8988
+ );
8989
+ void queryClient.invalidateQueries({ queryKey: arbiQueryKeys.databaseRows() });
8990
+ }
8991
+ });
8992
+ }
8993
+ function useDeleteDashboard(store) {
8994
+ const queryClient = useQueryClient();
8995
+ const key = arbiQueryKeys.dashboards(store.scope ?? "");
8996
+ return useMutation({
8997
+ mutationFn: (id) => store.remove(id),
8998
+ onSuccess: (_void, id) => {
8999
+ queryClient.setQueryData(key, (old = []) => old.filter((d) => d.id !== id));
9000
+ void queryClient.invalidateQueries({ queryKey: arbiQueryKeys.databaseRows() });
9001
+ }
9002
+ });
9003
+ }
7840
9004
  var PARSED_STALE_TIME = 5 * 60 * 1e3;
7841
9005
  function indexPassages(results) {
7842
9006
  const index = /* @__PURE__ */ new Map();
@@ -10047,7 +11211,7 @@ function useWorkspaceDocs(workspaceId) {
10047
11211
  function useAiTask() {
10048
11212
  const mutation = useAssistantQuery();
10049
11213
  const [status, setStatus] = useState("idle");
10050
- const [text, setText] = useState("");
11214
+ const [text2, setText] = useState("");
10051
11215
  const [stepCount, setStepCount] = useState(0);
10052
11216
  const [error, setError] = useState(null);
10053
11217
  const [responseId, setResponseId] = useState(null);
@@ -10127,7 +11291,7 @@ function useAiTask() {
10127
11291
  );
10128
11292
  return {
10129
11293
  status,
10130
- text,
11294
+ text: text2,
10131
11295
  stepCount,
10132
11296
  error,
10133
11297
  responseId,
@@ -10174,7 +11338,7 @@ function textToArtifact(title, content, opts) {
10174
11338
  }
10175
11339
  function AiAnswer({
10176
11340
  status,
10177
- text,
11341
+ text: text2,
10178
11342
  stepCount,
10179
11343
  error,
10180
11344
  className,
@@ -10185,9 +11349,9 @@ function AiAnswer({
10185
11349
  }) {
10186
11350
  const [copied, setCopied] = useState(false);
10187
11351
  const running = status === "running";
10188
- const hasText = text.trim().length > 0;
11352
+ const hasText = text2.trim().length > 0;
10189
11353
  const copy = async () => {
10190
- await navigator.clipboard.writeText(text);
11354
+ await navigator.clipboard.writeText(text2);
10191
11355
  setCopied(true);
10192
11356
  setTimeout(() => setCopied(false), 1600);
10193
11357
  };
@@ -10218,7 +11382,7 @@ function AiAnswer({
10218
11382
  }
10219
11383
  ),
10220
11384
  hasText && /* @__PURE__ */ jsxs(Fragment, { children: [
10221
- /* @__PURE__ */ jsx(AiMarkdown, { isStreaming: running, children: text }),
11385
+ /* @__PURE__ */ jsx(AiMarkdown, { isStreaming: running, children: text2 }),
10222
11386
  !running && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between border-t border-border pt-2.5", children: [
10223
11387
  /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1.5 text-xs text-muted-foreground", children: [
10224
11388
  /* @__PURE__ */ jsx(ShieldCheck, { className: "size-3.5 text-ai-accent" }),
@@ -10942,17 +12106,17 @@ var CitationPopover = ({
10942
12106
  useLayoutEffect(() => {
10943
12107
  if (!open) return;
10944
12108
  const edge = document.querySelector('[data-testid="message-input-container"]') ?? document.querySelector('main[data-testid^="conversation-"]') ?? document.body;
10945
- const measure = () => {
12109
+ const measure2 = () => {
10946
12110
  const rect = edge.getBoundingClientRect();
10947
12111
  setDock({ left: rect.left, top: rect.top, width: rect.width });
10948
12112
  };
10949
- measure();
10950
- const observer = new ResizeObserver(measure);
12113
+ measure2();
12114
+ const observer = new ResizeObserver(measure2);
10951
12115
  observer.observe(edge);
10952
- window.addEventListener("resize", measure);
12116
+ window.addEventListener("resize", measure2);
10953
12117
  return () => {
10954
12118
  observer.disconnect();
10955
- window.removeEventListener("resize", measure);
12119
+ window.removeEventListener("resize", measure2);
10956
12120
  };
10957
12121
  }, [open]);
10958
12122
  const handleOpen = useCallback(() => {
@@ -12253,17 +13417,17 @@ function DmComposer({
12253
13417
  setAttachError(null);
12254
13418
  };
12255
13419
  const submit = async () => {
12256
- const text = draft.trim();
12257
- if (!text && files.length === 0 || disabled || busy) return;
13420
+ const text2 = draft.trim();
13421
+ if (!text2 && files.length === 0 || disabled || busy) return;
12258
13422
  const sending = files;
12259
13423
  setDraft("");
12260
13424
  setFiles([]);
12261
13425
  setAttachError(null);
12262
13426
  try {
12263
- await onSend(text, sending);
13427
+ await onSend(text2, sending);
12264
13428
  inputRef.current?.focus();
12265
13429
  } catch {
12266
- setDraft(text);
13430
+ setDraft(text2);
12267
13431
  setFiles(sending);
12268
13432
  }
12269
13433
  };
@@ -13102,6 +14266,6 @@ function CommandPaletteProvider({
13102
14266
  ] });
13103
14267
  }
13104
14268
 
13105
- export { AGENT_CONTROL_COMMANDS, ALLOWED_PORTAL_ORIGINS, ARCHIVE_POLL_MS, ASSISTANT_MENTION_LABEL, AUTO_CHAT_MODEL, ActivityFeed, AiActionCard, AiAnswer, AppleIcon, ArbiBotIcon, ArbiHost2 as ArbiHost, ArbiWebSocketProvider, ArtifactCanvas, BOX_SEAT_REFUSED, BOX_SEAT_REFUSED_ACTION, BOX_SEAT_REFUSED_TITLE, CONVERSATION_SWITCH_MEASURE, ChatBubble, CitationRenderer, CommandPalette, CommandPaletteProvider, ConversationList, ConversationScope, DATABASE_RELATION_PICK_LIMIT, DATABASE_ROWS_PAGE, DEFAULT_ASPECT_OPTIONS, DEFAULT_PASSWORD_CHANGE_FORM_MESSAGES, DateSeparator, DmAvatar, DmComposer, DocQaPanel, DocSearch, DocumentCardMenu, DocumentReview, DraftTitleControls, FIRST_TOKEN_MEASURE, FileIcon, GitHubIcon, ImageCropModal, ImageCropper, LIVE_UPDATE_TYPES, LinkedInIcon, MAIL_DRAFT_REPLACED_EVENT, MIN_NARRATION_DWELL_MS, MailOfflineUnavailableError, MessageArtifactCard, PENDING_SYNC_PREDICATE, POLL_EVERY_MS, PhotoCapture, RUN_WINDOW_MS, SIGNATURE_NOTIFICATION_TYPES, SLOW_AFTER_MS, STILL_WORKING, StorageActionError, TRANSFER_POLL_MS, TaskThreadPendingError, TypingIndicator, UPLOAD_ACCEPT, UPLOAD_MAX_FILE_SIZE, VideoCapture, VoiceNoteRecorder, WORK_NOTIFICATION_LABELS, __resetPendingFinalCommitsForTests, __resetStreamingTokenBufferForTests, accountPath, addAssistantMessageToCache, addUserMessageToCache, adoptNewChatDocument, aliasTakenMessage, allConversationThreads, annotateThread, announceMailDraftReplaced, appendTokenToMessage, applyConversationEvent, applyFinalContextToMessage, applyLiveUpdate, applyNotificationRow, applyOptimisticDocumentEdit, applyOutputItemToMessage, applyTaskEvent, arbiMailClient, archiveName, archivedWorkspaceMessage, bindThreadDocument, boundDocumentOf, buildDocumentMetadataRows, buildMentionCandidates, buildPendingFirstTurn, buildPendingSyncItem, buildWorkspaceArchive, cacheThreadBinding, cachedAssistantMode, cachedMentionCandidates, cachedQuotaUsedUp, calendarNotificationMeta, callNotificationMeta, captureFrameAsBlob, clearLoadingState, clearUserInputRequest, commitFinalMessage, completeQueuedUserMessageByContent, connectOAuthCalendarAccount, connectorErrorStatus, connectorReturnTo, createMailClient, createSkillPack, createStreamHandlers, createWorkspaceSwitch, cropImage, dayKey, defaultMailAlias, deploymentUserMeta, describeActivity, describeCalendarNotification, describeServerNotification, discardStreamingTokensForMessage, disconnectAttachedRun, documentActivityMeta, documentActivityPhrase, documentDisplayName, docxMentionMeta, downloadRecoveryFile, ensureAssistantMessageLoading, extractZipFile, fallbackFileName, fileAttachment, filesFromDrop, flushStreamingTokens, forgetUploadedDocumentFolder, formatConfigValidationError, formatIdentityPrice, getInterjectionText, getNotificationTypeMeta, getOfflineDocument, getOrphanedLastMessage, getRelatedLabels, getRelatedTotal, getRunStartedAt, getThreadsQueryKey, getWorkspaceActionText, getWorkspaceKind, getWorkspaceSentPhrase, hasPendingFinalCommit, hasVideoTrack, identityStepFor, inputRequestTitle, invalidateCalendarEvents, invalidateCalendars, invalidateConversationActivity, isActivityKey, isAliasTakenError, isArchiveMoving, isCommentToPeople, isDeploymentAdmin, isDeploymentUserNotification, isFullConfig, isMessageRunning, isNotificationRow, isOfflineReadableArbiQuery, isOrphanedUserMessage, isQueuedCalendarWrite, isReplayableArbiMutation, isRestorableArbiQueryOnline, isSignatureNotificationType, isTransferFinished, isTransferResumable, isWorkspaceArchivedError, isWorkspaceNotificationType, isZipFile, loadOfflineDocument, mailDraftIdFromContent, mailJson, markMessageAsFailed, markNarrationSettled, migrateLegacyThreadDocuments, mountDiditVerification, nextAliasSuggestion, notificationUserName, openAccessRequest, parseActivityContent, parseDeleteAccountBlockers, pendingChatModelSave, peopleDirectory, personOfUser, pickRecentWorkspaces, prepareUploadFiles, redlineStats, refuseChatWhenOffline, registerArbiMutationDefaults, registerAttachedRun, removeSettledNarration, requestPersistentStorage, resetCalendarAccountSyncState, resetMessageContent, resolveActiveWorkspace, resolveConfigModel, resolveReplyTarget, rollbackOptimisticDocumentEdit, safePortalUrl, serverNotificationBellEntry, setMessageContent, setUserInputRequest, signatureNotificationPhrase, signatureRequestMeta, subscribeDocumentReads, supportsHouseTemplates, textToArtifact, threadBinding, threadEndingAtContains, titleFromQuestion, toChatCitations, toNotificationPreferences, toRedlineMarkdown, toShellWorkspace, updateMessageWithMetadata, updateUserMessageInCache, updateUserMessageStateInCache, uploadFolderOf, uploadedDocumentFolder, useActOnStep, useAddChatMembers, useAddDatabaseRows, useAddHolidayCalendar, useAddProjectAddonBlock, useAddWorkspaceMembers, useAddonQuote, useAgentChats, useAgentConfig, useAgentDmStatus, useAgentModels, useAgentRunControl, useAgentSession, useAgentWorkspaces, useAiTask, useAnswerAgentQuestion, useApplyChatModel, useArbiConnected, useArbiShellWorkspaces, useArbiWebSocket, useArbiWsContext, useArbiWsMessage, useArbiWsStatus, useArchiveProgressPolling, useArchiveWorkspace, useAskAgain, useAssignDocTags, useAuthorizeLimits, useAutoSendDraft, useBookingPages, useBranchNavigation, useCalDavProfiles, useCalendarAccounts, useCalendarEvent, useCalendarEventByUid, useCalendarEvents, useCalendarInvitations, useCalendarOutbox, useCalendarOverlays, useCalendarSettings, useCalendarShares, useCalendarSupport, useCalendars, useCameraStream, useCanEditShared, useCancelDriveSync, useCancelMailboxSync, useCancelManyPendingSync, useCancelProjectSubscription, useCancelWorkspaceTransfer, useChangeProjectPlan, useChargeWatch, useChatArrivals, useChatPost, useChatSummaries, useChatThread, useChatUnreadTotal, useChats, useClaimNativeAlias, useCloseAgentSession, useCommandPalette, useConfigSchema, useConfirmEmailChange, useConnectCalDavAccount, useConnectMailAccount, useConnectOAuthAccount, useConnectRunStream, useConnectorAutoSync, useConnectorCatalog, useConnectorVendorVisibility, useContacts, useConversation, useConversationActions, useConversationActivity, useConversationData, useConversationDocuments, useConversationIsShared, useConversationItems, useConversationPendingAuth, useConversationSearch, useConversationTurn, useConversationUsage, useCreateAgent, useCreateCalendar, useCreateContact, useCreateDatabase, useCreateEvent, useCreateFact, useCreateFacts, useCreateGroupChat, useCreateProject, useCreateProjectCheckout, useCreateRoom, useCreateWork, useCreateWorkflow, useCreateWorkspace, useCurrentSessionId, useDatabase, useDatabaseRows, useDatabases, useDecideCounter, useDeleteAccount, useDeleteAccountFlow, useDeleteBookingPage, useDeleteCalendar, useDeleteChatMessage, useDeleteConfig, useDeleteContact, useDeleteConversation, useDeleteDatabase, useDeleteDatabaseRows, useDeleteDocuments, useDeleteEvent, useDeleteFact, useDeleteMessage, useDeleteNotifications, useDeleteProject, useDeleteSkill, useDeleteWorkflow, useDeleteWorkspaces, useDisconnectCalendarAccount, useDisconnectConnector, useDisconnectMailAccount, useDisconnectSlack, useDismissedTips, useDocumentAutoAdd, useDocumentHostActions, useDocumentPendingSync, useDocumentThumbnails, useDocumentsSupport, useDownloadDocuments, useDriveFolderChildren, useDriveFolderDocCount, useDriveFolders, useDriveSyncEstimate, useDriveSyncProgress, useEmailChange, useEnableDriveSync, useEnableMailboxSync, useExportDatabase, useFacts, useFetchCalendarEvent, useFilteredProjects, useFinaliseTranslation, useFindTime, useFollowThread, useFreeBusy, useGenerateAgentAvatar, useGenerateDocTags, useGrantAgentAccess, useHolidayCountries, useHouseTemplateCandidates, useIdentityVerification, useIdentityVerificationFlow, useImportCalendar, useImportContacts, useImportDatabase, useImportDatabaseRows, useInstallSkillPack, useInvalidateAfterTransfer, useInvalidateProjects, useInvalidateStorage, useInviteContacts, useIsSlow, useIsWorkspaceOwner, useKeepDocumentsOffline, useLinkContact, useMailAccounts, useMailAttachmentText, useMailCache, useMailClient, useMailDraftCompose, useMailDraftEditor, useMailDraftReplaced, useMailFolders, useMailMessage, useMailMessages, useMailOnline, useMailPolicy, useMailProjects, useMailUnlock, useMailboxFolders, useMailboxSyncProgress, useMarkChatRead, useMarkDocumentShared, useMarkNotificationsRead, useMcpTools, useMentionCandidates, useMessageTimer, useMoveEvent, useMoveWorkspaceToProject, useMyConnectors, useNotificationPreferences, useNotifications, useNotifyConversation, useOfflineDocumentIds, useOpenSelectedWorkspace, useOpenViewerDocumentId, usePassageQuotes, usePasswordChange, usePasswordChangeForm, usePendingContacts, usePendingSyncCounts, usePendingSyncItems, usePeople, usePeopleSearch, usePlanQuote, usePlanWork, usePlanWorkspaceTransfer, usePreviewProjectPlanChange, useProcessingTask, useProcessingTasks, useProducts, useProjectBillingPortal, useProjectConversationUsage, useProjectEvents, usePublishCalendar, useRefreshCalendar, useRefreshConnectorsOnRunEnd, useRefreshProject, useRelatedDocuments, useRemoveChatMember, useRemoveDocTags, useRemoveDocumentsOffline, useRemoveWorkspaceMembers, useRenameChat, useRenameFolder, useRequestEmailChange, useRequestWorkspaceAccess, useRespondToEvent, useResumeCalendarAccountConnect, useResumeWorkspaceTransfer, useRevokeAgentAccess, useRooms, useRunConversation, useRunWorkflow, useSaveAgentConfig, useSaveBookingPage, useSaveCalendarSettings, useSaveConfig, useSaveConfigField, useSaveMailDraft, useSaveSkill, useSearchContacts, useSearchDatabaseRows, useSearchFacts, useSemanticSearch, useSendBackStep, useSendMail, useSessions, useSetDeploymentHouseTemplate, useSetSkillVisibility, useSetWorkspaceHouseTemplate, useSetWorkspaceMemberRoles, useShareCalendar, useShellWorkspaces, useSignOut, useSkillSource, useSkills, useSlackConnection, useStartAgentSession, useStartCalendarAccountOAuth, useStartTaskQuery, useStartWorkspaceTransfer, useStorageActions, useStorageItemNames, useStorageItems, useStorageProjects, useStorageSnapshots, useStreamHandlers, useSubscribeCalendar, useSwitchWorkspace, useSyncAccountsOnOpen, useSyncCalendarAccount, useTerminateSession, useThinkingContent, useThreadDocument, useTriggerDriveSync, useTriggerMailboxSync, useUnarchiveWorkspace, useUnreadByPeer, useUnshareCalendar, useUpdateCalendar, useUpdateCalendarAccount, useUpdateContact, useUpdateConversation, useUpdateDatabase, useUpdateDatabaseRow, useUpdateDocTag, useUpdateDocuments, useUpdateEvent, useUpdateFact, useUpdateMailMessage, useUpdateProjectAddonSettings, useUpdateProjectFields, useUpdateProjectNextPeriodAddons, useUpdateWorkflow, useUpdateWorkspace, useUploadDocuments, useUploadFiles, useUploadFromUrls, useUploadSkillFiles, useUploadUrls, useVideoRecorder, useWorkItems, useWorkNotifications, useWorkflowRuns, useWorkflows, useWorkspaceArchive, useWorkspaceDocs, useWorkspaceExportDownload, useWorkspaceNotificationLevel, useWorkspaceProcessing, useWorkspaceRole, useWorkspaceTransfer, useWorkspaceTransfers, useWorkspaceTrash, useWorkspaceUsers, userDisplayName, userInitials, waitForResponseId, wipeOfflineDocuments, withRelativePath, workflowStepOf, workspaceHouseTemplateId };
14269
+ export { AGENT_CONTROL_COMMANDS, AGGREGATE_FIELDS, ALLOWED_PORTAL_ORIGINS, ARCHIVE_POLL_MS, ASSISTANT_MENTION_LABEL, AUTO_CHAT_MODEL, ActivityFeed, AiActionCard, AiAnswer, AppleIcon, ArbiBotIcon, ArbiHost2 as ArbiHost, ArbiWebSocketProvider, ArtifactCanvas, BOX_SEAT_REFUSED, BOX_SEAT_REFUSED_ACTION, BOX_SEAT_REFUSED_TITLE, BUILTIN_DATA_SOURCES, CONVERSATION_SWITCH_MEASURE, ChatBubble, CitationRenderer, CommandPalette, CommandPaletteProvider, ConversationList, ConversationScope, DATABASE_RELATION_PICK_LIMIT, DATABASE_ROWS_PAGE, DEFAULT_ASPECT_OPTIONS, DEFAULT_CONVERSATIONS_SOURCE_LABELS, DEFAULT_DATABASE_SOURCE_LABELS, DEFAULT_DOCUMENTS_SOURCE_LABELS, DEFAULT_PASSWORD_CHANGE_FORM_MESSAGES, DEFAULT_PROJECTS_SOURCE_LABELS, DEFAULT_USAGE_SOURCE_LABELS, DEFAULT_WORKSPACES_SOURCE_LABELS, DateSeparator, DmAvatar, DmComposer, DocQaPanel, DocSearch, DocumentCardMenu, DocumentReview, DraftTitleControls, EMPTY_GROUP_LABEL, FIRST_TOKEN_MEASURE, FileIcon, GitHubIcon, ImageCropModal, ImageCropper, LIVE_UPDATE_TYPES, LinkedInIcon, MAIL_DRAFT_REPLACED_EVENT, MAX_DASHBOARD_SPEC_CHARS, MAX_SERIES, MIN_NARRATION_DWELL_MS, MODEL_GROUP_LABELS, MailOfflineUnavailableError, MessageArtifactCard, PENDING_SYNC_PREDICATE, POLL_EVERY_MS, PhotoCapture, RUN_WINDOW_MS, SIGNATURE_NOTIFICATION_TYPES, SLOW_AFTER_MS, STILL_WORKING, StorageActionError, TRANSFER_POLL_MS, TaskThreadPendingError, TypingIndicator, UPLOAD_ACCEPT, UPLOAD_MAX_FILE_SIZE, VideoCapture, VoiceNoteRecorder, WORK_NOTIFICATION_LABELS, __resetPendingFinalCommitsForTests, __resetStreamingTokenBufferForTests, accountPath, addAssistantMessageToCache, addUserMessageToCache, adoptNewChatDocument, aggregateDataset, aliasTakenMessage, allConversationThreads, annotateThread, announceMailDraftReplaced, appendTokenToMessage, applyConversationEvent, applyFinalContextToMessage, applyLiveUpdate, applyNotificationRow, applyOptimisticDocumentEdit, applyOutputItemToMessage, applyTaskEvent, arbiMailClient, archiveName, archivedWorkspaceMessage, bindThreadDocument, boundDocumentOf, bucketOf, bucketRange, buildDocumentMetadataRows, buildMentionCandidates, buildPendingFirstTurn, buildPendingSyncItem, buildWorkspaceArchive, cacheThreadBinding, cachedAssistantMode, cachedMentionCandidates, cachedQuotaUsedUp, calendarNotificationMeta, callNotificationMeta, captureFrameAsBlob, clearLoadingState, clearUserInputRequest, commitFinalMessage, completeQueuedUserMessageByContent, connectOAuthCalendarAccount, connectorErrorStatus, connectorReturnTo, createConversationsSource, createDataSourceRegistry, createDatabaseSource, createDocumentsSource, createMailClient, createMemoryDashboardStore, createProjectsSource, createSkillPack, createStreamHandlers, createUsageSource, createWorkspaceSwitch, createWorkspacesSource, cropImage, dayKey, defaultMailAlias, defineRowsSource, deploymentUserMeta, describeActivity, describeCalendarNotification, describeServerNotification, discardStreamingTokensForMessage, disconnectAttachedRun, documentActivityMeta, documentActivityPhrase, documentDisplayName, docxMentionMeta, downloadRecoveryFile, ensureAssistantMessageLoading, extractZipFile, fallbackFileName, fileAttachment, filesFromDrop, fillTimeGaps, filterRows, flushStreamingTokens, forgetUploadedDocumentFolder, formatConfigValidationError, formatIdentityPrice, getInterjectionText, getNotificationTypeMeta, getOfflineDocument, getOrphanedLastMessage, getRelatedLabels, getRelatedTotal, getRunStartedAt, getThreadsQueryKey, getWorkspaceActionText, getWorkspaceKind, getWorkspaceSentPhrase, hasPendingFinalCommit, hasVideoTrack, identityStepFor, inputRequestTitle, invalidateCalendarEvents, invalidateCalendars, invalidateConversationActivity, isActivityKey, isAliasTakenError, isArchiveMoving, isCommentToPeople, isDeploymentAdmin, isDeploymentUserNotification, isFullConfig, isMessageRunning, isNotificationRow, isOfflineReadableArbiQuery, isOrphanedUserMessage, isQueuedCalendarWrite, isReplayableArbiMutation, isRestorableArbiQueryOnline, isSignatureNotificationType, isTableViewOf, isTransferFinished, isTransferResumable, isWorkspaceArchivedError, isWorkspaceNotificationType, isZipFile, loadOfflineDocument, mailDraftIdFromContent, mailJson, markMessageAsFailed, markNarrationSettled, migrateLegacyThreadDocuments, mountDiditVerification, nextAliasSuggestion, notificationUserName, openAccessRequest, parseActivityContent, parseDashboardSpec, parseDeleteAccountBlockers, pendingChatModelSave, peopleDirectory, personOfUser, pickRecentWorkspaces, prepareUploadFiles, queryOfChart, recordsOf, redlineStats, refuseChatWhenOffline, registerArbiMutationDefaults, registerAttachedRun, removeSettledNarration, requestPersistentStorage, resetCalendarAccountSyncState, resetMessageContent, resolveActiveWorkspace, resolveConfigModel, resolveReplyTarget, rollbackOptimisticDocumentEdit, safePortalUrl, serializeDashboardSpec, serverNotificationBellEntry, setMessageContent, setUserInputRequest, signatureNotificationPhrase, signatureRequestMeta, subscribeDocumentReads, supportsHouseTemplates, textToArtifact, threadBinding, threadEndingAtContains, titleFromQuestion, toChatCitations, toNotificationPreferences, toRedlineMarkdown, toShellWorkspace, updateMessageWithMetadata, updateUserMessageInCache, updateUserMessageStateInCache, uploadFolderOf, uploadedDocumentFolder, useActOnStep, useActiveConfigId, useAddChatMembers, useAddDatabaseRows, useAddHolidayCalendar, useAddProjectAddonBlock, useAddWorkspaceMembers, useAddonQuote, useAgentChats, useAgentConfig, useAgentDmStatus, useAgentModels, useAgentRunControl, useAgentSession, useAgentWorkspaces, useAiTask, useAnswerAgentQuestion, useApplyChatModel, useArbiConnected, useArbiShellWorkspaces, useArbiWebSocket, useArbiWsContext, useArbiWsMessage, useArbiWsStatus, useArchiveProgressPolling, useArchiveWorkspace, useAskAgain, useAssignDocTags, useAuthorizeLimits, useAutoSendDraft, useBookingPages, useBranchNavigation, useCalDavProfiles, useCalendarAccounts, useCalendarEvent, useCalendarEventByUid, useCalendarEvents, useCalendarInvitations, useCalendarOutbox, useCalendarOverlays, useCalendarSettings, useCalendarShares, useCalendarSupport, useCalendars, useCameraStream, useCanEditShared, useCancelDriveSync, useCancelMailboxSync, useCancelManyPendingSync, useCancelProjectSubscription, useCancelWorkspaceTransfer, useChangeProjectPlan, useChargeWatch, useChatArrivals, useChatPost, useChatSummaries, useChatThread, useChatUnreadTotal, useChats, useClaimNativeAlias, useCloseAgentSession, useCommandPalette, useConfigSchema, useConfirmEmailChange, useConnectCalDavAccount, useConnectMailAccount, useConnectOAuthAccount, useConnectRunStream, useConnectorAutoSync, useConnectorCatalog, useConnectorVendorVisibility, useContacts, useConversation, useConversationActions, useConversationActivity, useConversationData, useConversationDocuments, useConversationIsShared, useConversationItems, useConversationPendingAuth, useConversationSearch, useConversationTurn, useConversationUsage, useCreateAgent, useCreateCalendar, useCreateContact, useCreateDatabase, useCreateEvent, useCreateFact, useCreateFacts, useCreateGroupChat, useCreateProject, useCreateProjectCheckout, useCreateRoom, useCreateWork, useCreateWorkflow, useCreateWorkspace, useCurrentSessionId, useCurrentWorkspace, useDashboardStore, useDataSources, useDatabase, useDatabaseAggregate, useDatabaseDashboardStore, useDatabaseRows, useDatabases, useDecideCounter, useDeleteAccount, useDeleteAccountFlow, useDeleteBookingPage, useDeleteCalendar, useDeleteChatMessage, useDeleteConfig, useDeleteContact, useDeleteConversation, useDeleteDashboard, useDeleteDatabase, useDeleteDatabaseRows, useDeleteDocuments, useDeleteEvent, useDeleteFact, useDeleteMessage, useDeleteNotifications, useDeleteProject, useDeleteSkill, useDeleteWorkflow, useDeleteWorkspaces, useDisconnectCalendarAccount, useDisconnectConnector, useDisconnectMailAccount, useDisconnectSlack, useDismissedTips, useDocumentAutoAdd, useDocumentHostActions, useDocumentPendingSync, useDocumentThumbnails, useDocumentsSupport, useDownloadDocuments, useDriveFolderChildren, useDriveFolderDocCount, useDriveFolders, useDriveSyncEstimate, useDriveSyncProgress, useEmailChange, useEnableDriveSync, useEnableMailboxSync, useExportDatabase, useFacts, useFetchCalendarEvent, useFilteredProjects, useFinaliseTranslation, useFindTime, useFollowThread, useFreeBusy, useGenerateAgentAvatar, useGenerateDocTags, useGrantAgentAccess, useHolidayCountries, useHouseTemplateCandidates, useIdentityVerification, useIdentityVerificationFlow, useImportCalendar, useImportContacts, useImportDatabase, useImportDatabaseRows, useInstallSkillPack, useInvalidateAfterTransfer, useInvalidateProjects, useInvalidateStorage, useInviteContacts, useIsSlow, useIsWorkspaceOwner, useKeepDocumentsOffline, useLinkContact, useMailAccounts, useMailAttachmentText, useMailCache, useMailClient, useMailDraftCompose, useMailDraftEditor, useMailDraftReplaced, useMailFolders, useMailMessage, useMailMessages, useMailOnline, useMailPolicy, useMailProjects, useMailUnlock, useMailboxFolders, useMailboxSyncProgress, useMarkChatRead, useMarkDocumentShared, useMarkNotificationsRead, useMcpTools, useMentionCandidates, useMessageTimer, useMoveEvent, useMoveWorkspaceToProject, useMyConnectors, useNotificationPreferences, useNotifications, useNotifyConversation, useOfflineDocumentIds, useOpenSelectedWorkspace, useOpenViewerDocumentId, usePanelDataset, usePassageQuotes, usePasswordChange, usePasswordChangeForm, usePendingContacts, usePendingSyncCounts, usePendingSyncItems, usePeople, usePeopleSearch, usePlanQuote, usePlanWork, usePlanWorkspaceTransfer, usePreviewProjectPlanChange, useProcessingTask, useProcessingTasks, useProducts, useProjectBillingPortal, useProjectConversationUsage, useProjectEvents, usePublishCalendar, useRefreshCalendar, useRefreshConnectorsOnRunEnd, useRefreshProject, useRelatedDocuments, useRemoveChatMember, useRemoveDocTags, useRemoveDocumentsOffline, useRemoveWorkspaceMembers, useRenameChat, useRenameFolder, useRequestEmailChange, useRequestWorkspaceAccess, useRespondToEvent, useResumeCalendarAccountConnect, useResumeWorkspaceTransfer, useRevokeAgentAccess, useRooms, useRunConversation, useRunWorkflow, useSaveAgentConfig, useSaveBookingPage, useSaveCalendarSettings, useSaveConfig, useSaveConfigField, useSaveDashboard, useSaveMailDraft, useSaveSkill, useSavedDashboards, useSearchContacts, useSearchDatabaseRows, useSearchFacts, useSemanticSearch, useSendBackStep, useSendMail, useSessions, useSetDeploymentHouseTemplate, useSetSkillVisibility, useSetWorkspaceHouseTemplate, useSetWorkspaceMemberRoles, useShareCalendar, useShellWorkspaces, useSignOut, useSkillSource, useSkills, useSlackConnection, useStartAgentSession, useStartCalendarAccountOAuth, useStartTaskQuery, useStartWorkspaceTransfer, useStorageActions, useStorageItemNames, useStorageItems, useStorageProjects, useStorageSnapshots, useStreamHandlers, useSubscribeCalendar, useSwitchWorkspace, useSyncAccountsOnOpen, useSyncCalendarAccount, useTerminateSession, useThinkingContent, useThreadDocument, useTriggerDriveSync, useTriggerMailboxSync, useUnarchiveWorkspace, useUnreadByPeer, useUnshareCalendar, useUpdateCalendar, useUpdateCalendarAccount, useUpdateContact, useUpdateConversation, useUpdateDatabase, useUpdateDatabaseRow, useUpdateDocTag, useUpdateDocuments, useUpdateEvent, useUpdateFact, useUpdateMailMessage, useUpdateProjectAddonSettings, useUpdateProjectFields, useUpdateProjectNextPeriodAddons, useUpdateWorkflow, useUpdateWorkspace, useUploadDocuments, useUploadFiles, useUploadFromUrls, useUploadSkillFiles, useUploadUrls, useVideoRecorder, useWorkItems, useWorkNotifications, useWorkflowRuns, useWorkflows, useWorkspaceArchive, useWorkspaceDocs, useWorkspaceExportDownload, useWorkspaceNotificationLevel, useWorkspaceProcessing, useWorkspaceRole, useWorkspaceTransfer, useWorkspaceTransfers, useWorkspaceTrash, useWorkspaceUsers, userDisplayName, userInitials, viewsOfTable, waitForResponseId, wipeOfflineDocuments, withRelativePath, workflowStepOf, workspaceHouseTemplateId };
13106
14270
  //# sourceMappingURL=index.js.map
13107
14271
  //# sourceMappingURL=index.js.map