@arbidocs/react 0.5.60 → 0.5.62
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ProductionDialog.d-CpzslFn0.d.cts +51 -0
- package/dist/ProductionDialog.d-CpzslFn0.d.ts +51 -0
- package/dist/annotations/freeze/index.cjs +14 -14
- package/dist/annotations/freeze/index.js +3 -3
- package/dist/annotations/index.d.cts +3 -2
- package/dist/annotations/index.d.ts +3 -2
- package/dist/artifacts/index.cjs +12 -12
- package/dist/artifacts/index.js +5 -5
- package/dist/bundle-IC65W2AO.cjs +14 -0
- package/dist/{bundle-DCWPYNGD.cjs.map → bundle-IC65W2AO.cjs.map} +1 -1
- package/dist/bundle-YNOX7VIL.js +5 -0
- package/dist/{bundle-JCKKGEJE.js.map → bundle-YNOX7VIL.js.map} +1 -1
- package/dist/calls/livekit/index.cjs +54 -54
- package/dist/calls/livekit/index.js +6 -6
- package/dist/{chunk-S2W3ZOWG.js → chunk-2LV53J46.js} +85 -16
- package/dist/chunk-2LV53J46.js.map +1 -0
- package/dist/{chunk-H3HYKAS5.cjs → chunk-3BFSALPC.cjs} +3 -3
- package/dist/{chunk-H3HYKAS5.cjs.map → chunk-3BFSALPC.cjs.map} +1 -1
- package/dist/{chunk-2NFUEC5O.js → chunk-3NBPMR3X.js} +3 -3
- package/dist/{chunk-2NFUEC5O.js.map → chunk-3NBPMR3X.js.map} +1 -1
- package/dist/chunk-4DTTEUVY.js +1042 -0
- package/dist/chunk-4DTTEUVY.js.map +1 -0
- package/dist/{chunk-U64WCQP3.js → chunk-AOEJ744V.js} +25 -14
- package/dist/chunk-AOEJ744V.js.map +1 -0
- package/dist/{chunk-4E737GNX.cjs → chunk-BLBXADTN.cjs} +86 -73
- package/dist/chunk-BLBXADTN.cjs.map +1 -0
- package/dist/{chunk-X7JXQT6F.cjs → chunk-DVL7EFZZ.cjs} +42 -46
- package/dist/chunk-DVL7EFZZ.cjs.map +1 -0
- package/dist/{chunk-VAMPYLQ4.cjs → chunk-DZUBZ45Y.cjs} +78 -2
- package/dist/chunk-DZUBZ45Y.cjs.map +1 -0
- package/dist/{chunk-OSWKXZTJ.js → chunk-ER4LFZG3.js} +12 -16
- package/dist/chunk-ER4LFZG3.js.map +1 -0
- package/dist/{chunk-5HDC43MF.js → chunk-G4Z3IP4J.js} +72 -3
- package/dist/chunk-G4Z3IP4J.js.map +1 -0
- package/dist/chunk-GOJHU7RZ.cjs +1122 -0
- package/dist/chunk-GOJHU7RZ.cjs.map +1 -0
- package/dist/{chunk-G76ASVVH.cjs → chunk-GQAXAZN7.cjs} +25 -14
- package/dist/chunk-GQAXAZN7.cjs.map +1 -0
- package/dist/{chunk-TUPSNW3B.cjs → chunk-LMW46NBD.cjs} +11 -11
- package/dist/{chunk-TUPSNW3B.cjs.map → chunk-LMW46NBD.cjs.map} +1 -1
- package/dist/{chunk-KRH55LXW.js → chunk-NCMSQACC.js} +37 -24
- package/dist/chunk-NCMSQACC.js.map +1 -0
- package/dist/{chunk-A2XSLTIP.js → chunk-NIKPG4PW.js} +3 -3
- package/dist/{chunk-A2XSLTIP.js.map → chunk-NIKPG4PW.js.map} +1 -1
- package/dist/{chunk-B6I2HRRF.cjs → chunk-PC4O3JDV.cjs} +3 -3
- package/dist/{chunk-B6I2HRRF.cjs.map → chunk-PC4O3JDV.cjs.map} +1 -1
- package/dist/{chunk-M2SZQBCO.js → chunk-SI7DJWBT.js} +3 -3
- package/dist/{chunk-M2SZQBCO.js.map → chunk-SI7DJWBT.js.map} +1 -1
- package/dist/{chunk-3QK4VVPG.cjs → chunk-TGSEQGM3.cjs} +3 -3
- package/dist/{chunk-3QK4VVPG.cjs.map → chunk-TGSEQGM3.cjs.map} +1 -1
- package/dist/{chunk-LCSUCZVX.cjs → chunk-ZNQPUPX6.cjs} +118 -41
- package/dist/chunk-ZNQPUPX6.cjs.map +1 -0
- package/dist/{chunk-CMNZI4WQ.js → chunk-ZTPJNKF2.js} +4 -4
- package/dist/{chunk-CMNZI4WQ.js.map → chunk-ZTPJNKF2.js.map} +1 -1
- package/dist/document-tools/core.cjs +408 -0
- package/dist/document-tools/core.cjs.map +1 -0
- package/dist/document-tools/core.d.cts +957 -0
- package/dist/document-tools/core.d.ts +957 -0
- package/dist/document-tools/core.js +15 -0
- package/dist/document-tools/core.js.map +1 -0
- package/dist/document-tools/index.cjs +347 -1130
- package/dist/document-tools/index.cjs.map +1 -1
- package/dist/document-tools/index.d.cts +12 -950
- package/dist/document-tools/index.d.ts +12 -950
- package/dist/document-tools/index.js +13 -1034
- package/dist/document-tools/index.js.map +1 -1
- package/dist/index.cjs +1510 -1255
- package/dist/index.cjs.map +1 -1
- package/dist/{index.d-BLw5AN0H.d.cts → index.d-AT7wdTWC.d.cts} +50 -2
- package/dist/{index.d-BLw5AN0H.d.ts → index.d-AT7wdTWC.d.ts} +50 -2
- package/dist/{index.d-DPVj21h1.d.ts → index.d-B0dosFZc.d.cts} +6 -6
- package/dist/{index.d-DPVj21h1.d.cts → index.d-B0dosFZc.d.ts} +6 -6
- package/dist/index.d.cts +145 -69
- package/dist/index.d.ts +145 -69
- package/dist/index.js +346 -121
- package/dist/index.js.map +1 -1
- package/dist/{query-keys.d-DEEMzkLz.d.cts → query-keys.d-BFKQVevT.d.cts} +21 -12
- package/dist/{query-keys.d-DEEMzkLz.d.ts → query-keys.d-BFKQVevT.d.ts} +21 -12
- package/dist/shell/index.cjs +68 -40
- package/dist/shell/index.d.cts +1 -1
- package/dist/shell/index.d.ts +1 -1
- package/dist/shell/index.js +3 -3
- package/dist/store.d-DkFXbWDk.d.ts +35 -0
- package/dist/store.d-GADDvC7w.d.cts +35 -0
- package/dist/ui/index.cjs +149 -149
- package/dist/ui/index.d.cts +1 -1
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.js +2 -2
- package/package.json +11 -3
- package/dist/ProductionDialog.d-BDJwBSzj.d.ts +0 -84
- package/dist/ProductionDialog.d-DjRQFmQw.d.cts +0 -84
- package/dist/bundle-DCWPYNGD.cjs +0 -14
- package/dist/bundle-JCKKGEJE.js +0 -5
- package/dist/chunk-4E737GNX.cjs.map +0 -1
- package/dist/chunk-5HDC43MF.js.map +0 -1
- package/dist/chunk-G76ASVVH.cjs.map +0 -1
- package/dist/chunk-KRH55LXW.js.map +0 -1
- package/dist/chunk-LCSUCZVX.cjs.map +0 -1
- package/dist/chunk-OSWKXZTJ.js.map +0 -1
- package/dist/chunk-S2W3ZOWG.js.map +0 -1
- package/dist/chunk-U64WCQP3.js.map +0 -1
- package/dist/chunk-VAMPYLQ4.cjs.map +0 -1
- package/dist/chunk-X7JXQT6F.cjs.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/documents/documents-cache.ts","../src/entity-extraction.ts","../src/tags.ts","../src/documents/documents-loader.ts","../src/documents/processing-order.ts","../src/websocket/store.ts","../src/documents/documents-data.ts"],"names":["arbiQueryKeys","update","create","useArbi","useQueryClient","useCallback","arbiMutationKeys","tagOps","useMutation","useQuery","useSyncExternalStore","controller","openWorkspaceId"],"mappings":"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","file":"chunk-LCSUCZVX.cjs","sourcesContent":["/**\n * The workspace documents list in the query cache: one entry per workspace\n * (`arbiQueryKeys.documents(workspaceId)`), read once (progressively, see `documents-loader.ts`)\n * and then kept current in place. Every write goes through {@link patchDocuments}, which also\n * tells row listeners (a grid that applies row transactions instead of re-diffing the whole list)\n * exactly which rows were added, changed or removed.\n *\n * A single document's own entry (`arbiQueryKeys.document(id)`, read by a viewer) is patched next to\n * the list by {@link setCachedDocument}, so a viewer never blanks while a write settles.\n */\n\nimport type { QueryClient } from '@tanstack/react-query'\nimport type { components } from '@arbidocs/client'\nimport { arbiQueryKeys } from '../hooks'\n\n/** A document as the server lists it. */\nexport type WorkspaceDocument = components['schemas']['DocResponse']\n\n/** The rows one write added, changed and removed (removed: by id). */\nexport interface DocumentRowChange {\n workspaceId: string\n add: WorkspaceDocument[]\n update: WorkspaceDocument[]\n remove: string[]\n}\n\ntype RowListener = (change: DocumentRowChange) => void\n\nconst rowListeners = new Set<RowListener>()\n\n/**\n * Follow the row-level changes of every write to a workspace documents list (a grid applying them\n * as transactions). Returns the unsubscribe.\n */\nexport function subscribeDocumentRows(listener: RowListener): () => void {\n rowListeners.add(listener)\n return () => {\n rowListeners.delete(listener)\n }\n}\n\n/** The cached documents of a workspace (`undefined` before its list has been read). */\nexport function getCachedDocuments(\n qc: QueryClient,\n workspaceId: string | null | undefined\n): WorkspaceDocument[] | undefined {\n if (!workspaceId) return undefined\n return qc.getQueryData<WorkspaceDocument[]>(arbiQueryKeys.documents(workspaceId))\n}\n\n/** Every cached workspace documents list, with its workspace. */\nfunction cachedLists(qc: QueryClient): Array<[string, WorkspaceDocument[]]> {\n return qc\n .getQueriesData<WorkspaceDocument[]>({ queryKey: arbiQueryKeys.allDocuments() })\n .flatMap(([key, data]) =>\n typeof key[2] === 'string' && Array.isArray(data) ? [[key[2], data]] : []\n )\n}\n\n/** Diff two versions of a list by id. */\nfunction diffRows(\n workspaceId: string,\n before: WorkspaceDocument[],\n after: WorkspaceDocument[]\n): DocumentRowChange {\n const beforeById = new Map(before.map((doc) => [doc.external_id, doc]))\n const add: WorkspaceDocument[] = []\n const update: WorkspaceDocument[] = []\n const seen = new Set<string>()\n for (const doc of after) {\n seen.add(doc.external_id)\n const previous = beforeById.get(doc.external_id)\n if (!previous) add.push(doc)\n else if (previous !== doc) update.push(doc)\n }\n const remove = [...beforeById.keys()].filter((id) => !seen.has(id))\n return { workspaceId, add, update, remove }\n}\n\n/**\n * Apply `reducer` to a workspace's documents list, or (no `workspaceId`) to every cached one: the\n * one place a list is written after it was read. Returning the same array is a no-op. Row\n * listeners get the diff; a document that moved to a new version makes the open version lists\n * re-read. A workspace whose list has not been read is left alone (its first read brings it).\n */\nexport function patchDocuments(\n qc: QueryClient,\n reducer: (documents: WorkspaceDocument[]) => WorkspaceDocument[],\n workspaceId?: string | null\n): void {\n const lists: Array<[string, WorkspaceDocument[]]> = workspaceId\n ? (() => {\n const current = getCachedDocuments(qc, workspaceId)\n return current ? [[workspaceId, current] as [string, WorkspaceDocument[]]] : []\n })()\n : cachedLists(qc)\n for (const [id, before] of lists) {\n const after = reducer(before)\n if (after === before) continue\n qc.setQueryData(arbiQueryKeys.documents(id), after)\n const change = diffRows(id, before, after)\n const beforeById = new Map(before.map((doc) => [doc.external_id, doc]))\n if (\n change.update.some(\n (doc) => doc.current_version !== beforeById.get(doc.external_id)?.current_version\n )\n )\n void qc.invalidateQueries({ queryKey: arbiQueryKeys.allDocumentVersions() })\n if (change.add.length || change.update.length || change.remove.length)\n for (const listener of rowListeners) listener(change)\n }\n}\n\n/** Put `doc` in its list in place, or at the end when the list does not hold it yet. */\nexport function upsertDocuments(\n qc: QueryClient,\n documents: WorkspaceDocument[],\n workspaceId?: string | null\n): void {\n if (!documents.length) return\n const byId = new Map(documents.map((doc) => [doc.external_id, doc]))\n const byWorkspace = new Map<string, WorkspaceDocument[]>()\n for (const doc of documents) {\n const ws = workspaceId ?? doc.workspace_ext_id\n byWorkspace.set(ws, [...(byWorkspace.get(ws) ?? []), doc])\n }\n for (const [ws, incoming] of byWorkspace) {\n patchDocuments(\n qc,\n (old) => {\n const known = new Set(old.map((doc) => doc.external_id))\n return [\n ...old.map((doc) => byId.get(doc.external_id) ?? doc),\n ...incoming.filter((doc) => !known.has(doc.external_id)),\n ]\n },\n ws\n )\n }\n}\n\n/** Write a document's own entry (what `useDocument` reads), keeping a viewer current. */\nexport function setCachedDocument(qc: QueryClient, doc: WorkspaceDocument): void {\n qc.setQueryData(arbiQueryKeys.document(doc.external_id), doc)\n}\n\n/** Apply `reducer` to a document's own entry, when one is cached. */\nexport function patchCachedDocument(\n qc: QueryClient,\n docId: string,\n reducer: (doc: WorkspaceDocument) => WorkspaceDocument\n): void {\n const current = qc.getQueryData<WorkspaceDocument | null>(arbiQueryKeys.document(docId))\n if (current) qc.setQueryData(arbiQueryKeys.document(docId), reducer(current))\n}\n\n/** A deleted tag leaves every cached document that carried it: the lists' rows and their entries. */\nexport function dropTagFromCachedDocuments(qc: QueryClient, tagId: string): void {\n const strip = (doc: WorkspaceDocument): WorkspaceDocument => {\n const doctags = doc.doctags?.filter((dt) => dt.tag_ext_id !== tagId)\n return doctags && doctags.length !== doc.doctags?.length ? { ...doc, doctags } : doc\n }\n const carriers: string[] = []\n patchDocuments(qc, (docs) => {\n const next = docs.map(strip)\n next.forEach((doc, i) => doc !== docs[i] && carriers.push(doc.external_id))\n return carriers.length ? next : docs\n })\n for (const id of carriers) patchCachedDocument(qc, id, strip)\n}\n\n/** Forget everything cached about deleted documents, so nothing re-reads them into a 404. */\nexport function forgetDocuments(qc: QueryClient, docIds: string[]): void {\n for (const id of docIds) {\n qc.removeQueries({ queryKey: arbiQueryKeys.document(id) })\n qc.removeQueries({ queryKey: arbiQueryKeys.documentVersions(id) })\n qc.removeQueries({ queryKey: arbiQueryKeys.parsedDocument(id) })\n }\n}\n","/**\n * The documents whose people and organisations are being found (`useExtractEntities`), from the\n * request until the live connection says the batch is done (`batch_complete`, `entity_extract`):\n * the package's WebSocket (`ArbiWebSocketProvider`) ends it, and a host on its own connection calls\n * `finishEntityExtraction` from its handler.\n */\n\nimport { create } from 'zustand'\n\nconst useEntityExtractionStore = create<{ docIds: readonly string[] }>(() => ({ docIds: [] }))\n\nfunction update(docIds: readonly string[], running: boolean): void {\n if (!docIds.length) return\n useEntityExtractionStore.setState((state) => {\n const ids = new Set(state.docIds)\n docIds.forEach((id) => (running ? ids.add(id) : ids.delete(id)))\n return { docIds: [...ids] }\n })\n}\n\n/** The documents an extraction was started on are running. */\nexport function startEntityExtraction(docIds: readonly string[]): void {\n update(docIds, true)\n}\n\n/** The extraction of these documents is done. */\nexport function finishEntityExtraction(docIds: readonly string[]): void {\n update(docIds, false)\n}\n\n/** The documents being extracted now. */\nexport function useEntityExtractionDocIds(): readonly string[] {\n return useEntityExtractionStore((state) => state.docIds)\n}\n","/**\n * Tags: the open workspace's tag list (`useTags()`), the writes (create, update, delete, values,\n * entity extraction), and tag kinds — a kind's fields in the workspace are the columns of a table\n * of its tags (`useTagKindSchema('issue')`), whose rows are the tag list filtered by kind with\n * links (`useTags(workspaceId, { kind, include })`).\n *\n * Everything is cached under the workspace's tags (`arbiQueryKeys.tags`). The whole list is kept\n * current in place: every write here patches it ({@link patchWorkspaceTags}, which a host also\n * uses for its own writes that move a tag's counts, e.g. applying it to documents) and refreshes\n * the filtered lists (the tables). Anything that invalidates the workspace's tags (a document batch\n * finishing, {@link useInvalidateTagData} after a doctag or fact change) refreshes them all.\n *\n * Creating a tag can be queued while offline and replayed after a reload: see `offline.ts`.\n *\n * Requires an `ArbiHost` (with an `arbi`) and a React Query client above it.\n */\n\nimport { useCallback } from 'react'\nimport { useMutation, useQuery, useQueryClient, type QueryClient } from '@tanstack/react-query'\nimport type { ArbiClient } from '@arbidocs/client'\nimport {\n tags as tagOps,\n type TagChange,\n type TagFieldDefinition,\n type TagKind,\n type TagKindSchema,\n type TagResponse,\n} from '@arbidocs/sdk/browser'\nimport { useArbi } from './useArbi'\nimport { dropTagFromCachedDocuments } from './documents/documents-cache'\nimport { startEntityExtraction } from './entity-extraction'\nimport { arbiMutationKeys, arbiQueryKeys } from './hooks'\n\n/** The workspace open on `arbi`, or `null` (`getWorkspaceId()` throws when none is open). */\nfunction openWorkspaceId(arbi: ReturnType<typeof useArbi>): string | null {\n return arbi.hasWorkspace ? arbi.getWorkspaceId() : null\n}\n\n/**\n * Apply `reducer` to a workspace's cached tag list (nothing cached: nothing to do). The list is\n * read once, then kept current by these patches; a host's own write that changes a tag (applying\n * it to documents moves its `doctag_count`) patches it here too.\n */\nexport function patchWorkspaceTags(\n qc: QueryClient,\n workspaceId: string,\n reducer: (tags: TagResponse[]) => TagResponse[]\n): void {\n const key = arbiQueryKeys.tags(workspaceId)\n const current = qc.getQueryData<TagResponse[]>(key)\n if (!current) return\n const next = reducer(current)\n if (next !== current) qc.setQueryData(key, next)\n}\n\n/** Refetch a workspace's tables of tags (its filtered lists), not the whole list. */\nexport function invalidateTagTables(qc: QueryClient, workspaceId: string): Promise<void> {\n return qc.invalidateQueries({ queryKey: arbiQueryKeys.tagLists(workspaceId) })\n}\n\n/** Refresh what a tag, doctag or fact change affects: the workspace's tags, tables and facts. */\nexport function invalidateTagData(qc: QueryClient, workspaceId: string): Promise<unknown> {\n return Promise.all([\n qc.invalidateQueries({ queryKey: arbiQueryKeys.tags(workspaceId) }),\n qc.invalidateQueries({ queryKey: arbiQueryKeys.facts(workspaceId) }),\n ])\n}\n\n/** {@link invalidateTagData} for the open workspace: call it after a doctag or fact write. */\nexport function useInvalidateTagData(): () => Promise<unknown> {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useCallback(() => {\n const workspaceId = openWorkspaceId(arbi)\n return workspaceId ? invalidateTagData(qc, workspaceId) : Promise.resolve()\n }, [arbi, qc])\n}\n\n/**\n * What a new tag is: its name, and optionally kind, format, parent, values, sharing, and the workspace it goes in\n * (absent: the open one).\n */\nexport type CreateTagInput = Parameters<typeof tagOps.createTag>[1]\n\n/** A created tag joins its workspace's list; the tables re-read. */\nfunction settleCreatedTag(qc: QueryClient, created: TagResponse): Promise<void> {\n const workspaceId = created.workspace_ext_id\n patchWorkspaceTags(qc, workspaceId, (old) =>\n old.some((t) => t.external_id === created.external_id) ? old : [...old, created]\n )\n return invalidateTagTables(qc, workspaceId)\n}\n\n/** A changed tag replaces its entry in the list; the tables re-read. */\nfunction settleChangedTag(qc: QueryClient, tag: TagResponse): Promise<void> {\n const workspaceId = tag.workspace_ext_id\n patchWorkspaceTags(qc, workspaceId, (old) =>\n old.map((t) => (t.external_id === tag.external_id ? { ...t, ...tag } : t))\n )\n return invalidateTagTables(qc, workspaceId)\n}\n\n/**\n * The tag writes a host may queue while offline and replay after a reload (`offline.ts`): each\n * key's request on a bare client, and what its success does to the cache.\n */\nexport const replayableTagMutations = [\n {\n mutationKey: arbiMutationKeys.createTag(),\n run: (client: ArbiClient, input: CreateTagInput) => tagOps.createTag(client, input),\n settle: (qc: QueryClient, created: TagResponse) => settleCreatedTag(qc, created),\n },\n] as const\n\n/**\n * Create a tag in the open workspace, or `workspaceId` (`{ name, kind: 'issue' }`, `{ name, parentId }`, …): it is\n * added to the tag list and the tables re-read. Resolves with the new tag. Offline it is held and\n * sent on reconnect (a host that registers `registerArbiMutationDefaults` keeps it across reloads).\n */\nexport function useCreateTag() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationKey: arbiMutationKeys.createTag(),\n mutationFn: (input: CreateTagInput): Promise<TagResponse> => arbi.tags.create(input),\n onSuccess: (created) => settleCreatedTag(qc, created),\n })\n}\n\n/**\n * Whether a tag of this name (any case) is being created right now: a second create of the same\n * name (a double Enter) is skipped instead of making a duplicate.\n */\nexport function useIsCreatingTag(): (name: string) => boolean {\n const qc = useQueryClient()\n return useCallback(\n (name: string) => {\n const wanted = name.trim().toLowerCase()\n return (\n qc.getMutationCache().findAll({\n mutationKey: arbiMutationKeys.createTag(),\n predicate: (m) =>\n m.state.status === 'pending' &&\n (m.state.variables as CreateTagInput | undefined)?.name.trim().toLowerCase() === wanted,\n }).length > 0\n )\n },\n [qc]\n )\n}\n\n/** Change a tag (name, format, instruction, parent, sharing, values): patched in the list. */\nexport function useUpdateTag() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationKey: arbiMutationKeys.updateTag(),\n mutationFn: ({ tagId, change }: { tagId: string; change: TagChange }): Promise<TagResponse> =>\n arbi.tags.update(tagId, change),\n onSuccess: (tag) => settleChangedTag(qc, tag),\n })\n}\n\n/** Merge-patch a tag's values for its kind's fields (`null` clears one); its tables refresh. */\nexport function useSetTagValues() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationKey: arbiMutationKeys.updateTag(),\n mutationFn: ({\n tagId,\n values,\n }: {\n tagId: string\n values: Record<string, unknown>\n }): Promise<TagResponse> => arbi.tags.setValues(tagId, values),\n onSuccess: (tag) => settleChangedTag(qc, tag),\n })\n}\n\n/**\n * Delete a tag: it leaves the list (its sub-tags move to the top level on the server, so the list\n * re-reads them), and the tables and facts re-read. A host that shows the tag on its own items\n * (documents' tags) follows `arbiMutationKeys.deleteTag()` to drop it there.\n */\nexport function useDeleteTag() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationKey: arbiMutationKeys.deleteTag(),\n mutationFn: (tagId: string) => arbi.tags.delete(tagId),\n onSuccess: (_data, tagId) => {\n // Its pills come off the documents grid in place (and off any open document).\n dropTagFromCachedDocuments(qc, tagId)\n const workspaceId = openWorkspaceId(arbi)\n if (!workspaceId) return\n patchWorkspaceTags(qc, workspaceId, (old) =>\n old\n .filter((t) => t.external_id !== tagId)\n .map((t) => (t.parent_ext_id === tagId ? { ...t, parent_ext_id: null } : t))\n )\n return Promise.all([\n invalidateTagTables(qc, workspaceId),\n qc.invalidateQueries({ queryKey: arbiQueryKeys.facts(workspaceId) }),\n ])\n },\n })\n}\n\n/**\n * Find the people and organisations documents name and link each to its entity tag. Accepted at\n * once with the documents' ids, which show as running (`useEntityExtractionDocIds`) until a\n * `batch_complete` (`entity_extract`) WebSocket message says they are done.\n */\nexport function useExtractEntities() {\n const arbi = useArbi()\n return useMutation({\n mutationKey: arbiMutationKeys.extractEntities(),\n mutationFn: (docIds: string[]) => arbi.tags.extractEntities(docIds),\n onSuccess: (data) => startEntityExtraction(data.doc_ext_ids),\n })\n}\n\n/**\n * A kind's fields in the open workspace (`'issue'`: its issue fields): the columns of a table of\n * that kind's tags. The built-in ones (`is_default`) until the workspace sets its own.\n */\nexport function useTagKindSchema(\n kind: TagKind | null | undefined,\n options?: { enabled?: boolean }\n) {\n const arbi = useArbi()\n const workspaceId = openWorkspaceId(arbi) ?? ''\n return useQuery({\n queryKey: arbiQueryKeys.tagKind(workspaceId, kind ?? ''),\n queryFn: (): Promise<TagKindSchema> =>\n arbi.readInWorkspace(workspaceId, () => arbi.tagKinds.get(kind as TagKind)),\n enabled: (options?.enabled ?? true) && !!kind && !!workspaceId,\n })\n}\n\n/**\n * Set a kind's fields in full (a field with its `id` keeps its values; one without is new; one\n * left out is removed). The kind's schema and the workspace's tags refresh.\n */\nexport function useUpdateTagKindSchema() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationKey: arbiMutationKeys.updateTagKindSchema(),\n mutationFn: ({\n kind,\n fields,\n }: {\n kind: TagKind\n fields: TagFieldDefinition[]\n }): Promise<TagKindSchema> => arbi.tagKinds.update(kind, fields),\n onSuccess: (schema) => {\n const workspaceId = openWorkspaceId(arbi)\n if (!workspaceId) return\n qc.setQueryData(arbiQueryKeys.tagKind(workspaceId, schema.kind), schema)\n return invalidateTagData(qc, workspaceId)\n },\n })\n}\n","/**\n * Reading a workspace's documents progressively: the first page is the query's result, so the\n * list shows within a few hundred milliseconds even for 100k documents, and the remaining pages\n * are appended to the same cache entry in the background as they arrive. One background read per\n * workspace; opening another workspace stops the previous one. Whether a background read is\n * running is observable ({@link useDocumentsLoading}), for a \"still loading\" indicator.\n */\n\nimport { useSyncExternalStore } from 'react'\nimport type { QueryClient } from '@tanstack/react-query'\nimport type { Arbi } from '@arbidocs/sdk/browser'\nimport { patchDocuments, type WorkspaceDocument } from './documents-cache'\n\n/** First page: small, so rows are on screen in a few hundred ms even in a large workspace. */\nexport const DOCUMENTS_FIRST_PAGE_SIZE = 500\n\n/** Later pages: larger, fewer round trips (the server caps a page at 10 000). */\nexport const DOCUMENTS_PAGE_SIZE = 2000\n\n/**\n * The time to the first page, as a `performance` measure of this name (a host reporting\n * performance can observe it).\n */\nexport const DOCUMENTS_FIRST_PAGE_MEASURE = 'arbi:document-list:page1'\nconst FIRST_PAGE_MEASURE = DOCUMENTS_FIRST_PAGE_MEASURE\nconst FIRST_PAGE_START = 'arbi:document-list:start'\n\nfunction mark(name: string): void {\n try {\n performance.mark(name)\n } catch {\n // No performance timeline here (an old runtime, a test): nothing to record.\n }\n}\n\nfunction measure(name: string, start: string): void {\n try {\n performance.measure(name, start)\n } catch {\n // The start mark is missing: nothing to record.\n }\n}\n\nconst backgroundReads = new Map<string, AbortController>()\nconst loadingListeners = new Set<() => void>()\n\nfunction emitLoading(): void {\n for (const listener of loadingListeners) listener()\n}\n\nfunction subscribeLoading(listener: () => void): () => void {\n loadingListeners.add(listener)\n return () => {\n loadingListeners.delete(listener)\n }\n}\n\n/** Whether a workspace's remaining document pages are being read in the background. */\nexport function isDocumentsLoading(): boolean {\n return backgroundReads.size > 0\n}\n\n/** True while the remaining pages of a documents list are still arriving. */\nexport function useDocumentsLoading(): boolean {\n return useSyncExternalStore(subscribeLoading, isDocumentsLoading, () => false)\n}\n\n/** Stop a workspace's background read (closing the workspace). */\nexport function stopDocumentsLoading(workspaceId: string): void {\n const controller = backgroundReads.get(workspaceId)\n if (!controller) return\n controller.abort()\n backgroundReads.delete(workspaceId)\n emitLoading()\n}\n\n/**\n * Read a workspace's documents: resolves with the first page and appends the rest to\n * `arbiQueryKeys.documents(workspaceId)` in the background. The query function of `useDocuments`.\n */\nexport async function loadDocuments(\n qc: QueryClient,\n arbi: Arbi,\n workspaceId: string,\n signal?: AbortSignal\n): Promise<WorkspaceDocument[]> {\n let stopped = false\n for (const [id, controller] of backgroundReads) {\n if (id === workspaceId) continue\n controller.abort()\n backgroundReads.delete(id)\n stopped = true\n }\n if (stopped) emitLoading()\n\n const controller = new AbortController()\n signal?.addEventListener('abort', () => controller.abort(), { once: true })\n // Named, not the session's open workspace: the pages are this workspace's whatever the server\n // session is in, so a list read across a workspace switch can never be another's.\n const pages = arbi.documents.listPaginated({\n workspaceId,\n pageSize: DOCUMENTS_PAGE_SIZE,\n firstPageSize: DOCUMENTS_FIRST_PAGE_SIZE,\n signal: controller.signal,\n })\n mark(FIRST_PAGE_START)\n const first = await pages.next()\n const firstPage = first.done ? [] : first.value\n measure(FIRST_PAGE_MEASURE, FIRST_PAGE_START)\n if (first.done || firstPage.length < DOCUMENTS_FIRST_PAGE_SIZE) return firstPage\n if (backgroundReads.has(workspaceId)) {\n controller.abort()\n return firstPage\n }\n\n backgroundReads.set(workspaceId, controller)\n emitLoading()\n void appendRemainingPages(qc, workspaceId, pages, controller.signal).finally(() => {\n if (backgroundReads.get(workspaceId) !== controller) return\n backgroundReads.delete(workspaceId)\n emitLoading()\n })\n return firstPage\n}\n\nasync function appendRemainingPages(\n qc: QueryClient,\n workspaceId: string,\n pages: AsyncGenerator<WorkspaceDocument[]>,\n signal: AbortSignal\n): Promise<void> {\n // Let the query store the first page before the second is appended to it.\n await Promise.resolve()\n try {\n for await (const page of pages) {\n if (signal.aborted) return\n // A write may already have added some of these (an upload finishing meanwhile).\n patchDocuments(\n qc,\n (old) => {\n const known = new Set(old.map((doc) => doc.external_id))\n const fresh = page.filter((doc) => !known.has(doc.external_id))\n return fresh.length ? [...old, ...fresh] : old\n },\n workspaceId\n )\n }\n } catch (error) {\n if (!signal.aborted) console.error(`Reading the documents of ${workspaceId} failed:`, error)\n }\n}\n\n/** Test-only: stop every background read. @internal */\nexport function resetDocumentsLoadingForTests(): void {\n for (const controller of backgroundReads.values()) controller.abort()\n backgroundReads.clear()\n emitLoading()\n}\n","/**\n * Which is newer: a document's live processing status or its row as last read?\n *\n * Every `task_update` carries `seq`, taken by the server from one sequence for all documents and\n * all of its instances, so a higher seq is a later event however the events arrive. A document row\n * carries `status_seq`: the seq of the last time its processing ended (a finished status written or\n * broadcast). The two compare:\n * - an event at or below the seq of the one already held is stale (overtaken), and is dropped;\n * - a row whose `status_seq` is above the live status's seq finished after it: the live status is\n * over (its final event was lost), and the row wins;\n * - a live status above the row's `status_seq` is newer than the row: the document is being\n * processed again (AI fields being filled) although the row still says it finished.\n *\n * Without the seqs (an optimistic \"queued\" set here, a server before them) the older rule stands:\n * a live in-flight status wins, then a finished row, then whatever was heard live.\n */\n\n/** Statuses after which a document's processing is over (`low-content`: indexed, little text). */\nexport const FINISHED_DOCUMENT_STATUSES: ReadonlySet<string> = new Set([\n 'completed',\n 'low-content',\n 'failed',\n 'skipped',\n 'empty',\n])\n\n/** A live processing status and its order (`task_update.seq`). */\nexport interface SequencedTask {\n status: string\n seq?: number | null\n}\n\n/** A document row's status and the order of its last finished status (`status_seq`). */\nexport interface SequencedRow {\n status?: string | null\n status_seq?: number | null\n}\n\n/** Statuses of a document still being processed. */\nexport const IN_FLIGHT_DOCUMENT_STATUSES: ReadonlySet<string> = new Set([\n 'uploading',\n 'queued',\n 'parsing',\n 'encrypting',\n 'indexing',\n 'analysing',\n])\n\nfunction ordered(value: number | null | undefined): value is number {\n return typeof value === 'number'\n}\n\n/** Whether `next` is older than (or the same event as) the live status already held. */\nexport function isStaleTaskUpdate(held: SequencedTask | undefined, next: SequencedTask): boolean {\n return !!held && ordered(held.seq) && ordered(next.seq) && next.seq <= held.seq\n}\n\n/**\n * Whether the row is newer than the live status: `true` / `false` when both are ordered, `undefined`\n * when they cannot be compared.\n */\nexport function isRowNewer(row: SequencedRow, task: SequencedTask): boolean | undefined {\n if (!ordered(row.status_seq) || !ordered(task.seq)) return undefined\n return row.status_seq > task.seq\n}\n\n/** The status a document shows now: its row's, or the live one when that is newer. */\nexport function resolveDocumentStatus(row: SequencedRow, task: SequencedTask | undefined): string {\n const rowStatus = (row.status ?? '').toLowerCase()\n const live = task?.status\n if (!task || !live) return rowStatus\n const rowNewer = isRowNewer(row, task)\n if (rowNewer !== undefined) return rowNewer ? rowStatus || live : live\n if (IN_FLIGHT_DOCUMENT_STATUSES.has(live)) return live\n if (FINISHED_DOCUMENT_STATUSES.has(rowStatus)) return rowStatus\n return live\n}\n\n/**\n * The live statuses a read of `rows` ends: each in-flight one whose row has since finished. Ordered,\n * the row must be newer (so a reprocess the row predates keeps its progress); unordered, a finished\n * row is enough (the older rule). Returns each such task with the row's status and order. Cheap when\n * nothing is in flight (it runs on every read of a list).\n */\nexport function settledByRows<T extends SequencedTask & { doc_ext_id: string }>(\n tasks: Readonly<Record<string, T>>,\n rows: ReadonlyArray<SequencedRow & { external_id: string }>\n): T[] {\n const inFlight = new Map<string, T>()\n for (const task of Object.values(tasks))\n if (IN_FLIGHT_DOCUMENT_STATUSES.has(task.status)) inFlight.set(task.doc_ext_id, task)\n if (!inFlight.size) return []\n const settled: T[] = []\n for (const row of rows) {\n const task = inFlight.get(row.external_id)\n if (!task) continue\n const rowStatus = (row.status ?? '').toLowerCase()\n if (!FINISHED_DOCUMENT_STATUSES.has(rowStatus) || isRowNewer(row, task) === false) continue\n settled.push({ ...task, status: rowStatus, seq: row.status_seq ?? task.seq })\n }\n return settled\n}\n","/**\n * Canonical WebSocket state, shared across apps.\n *\n * One store for every site's live connection: its status, people's presence and each document's\n * live processing. `ArbiWebSocketProvider` feeds it; components read it with the selector hooks in\n * `./hooks` and the documents hooks (`useProcessingTasks`, `useWorkspaceProcessing`).\n */\n\nimport { create } from 'zustand'\nimport type { WsTaskUpdateMessage, WsPresenceUpdateMessage } from '@arbidocs/client'\nimport {\n FINISHED_DOCUMENT_STATUSES,\n isStaleTaskUpdate,\n settledByRows,\n type SequencedRow,\n} from '../documents/processing-order'\n\n/** `error`: the host's socket failed. */\nexport type ArbiWsStatus = 'disconnected' | 'connecting' | 'connected' | 'reconnecting' | 'error'\n\n/**\n * A document's live processing: its last `task_update` (or a status set here, such as \"queued\"\n * while a write sends it back into processing), with when it was first seen (`startTime`) and\n * when it finished (`endTime`), both on this device's clock.\n */\nexport type LiveTask = Omit<WsTaskUpdateMessage, 'type' | 'seq'> & {\n type?: 'task_update'\n seq?: number | null\n startTime?: number\n endTime?: number\n}\n\n/** How long a document's tasks stay dismissed (late updates of a deleted upload are dropped). */\nexport const DISMISSED_TASK_TTL_MS = 10 * 60 * 1000\n\nexport interface ArbiWsState {\n /** Live connection status of the shared socket. */\n status: ArbiWsStatus\n /** Latest processing status per document id (the `task_update` stream). */\n tasks: Record<string, LiveTask>\n /** Documents whose processing rows were dismissed (deleted, cleared), with when. */\n dismissed: Record<string, number>\n /** The most recent `task_update` — a convenient single-value change trigger. */\n lastTaskUpdate: WsTaskUpdateMessage | null\n /** Online status keyed by user id (the `presence_update` stream). */\n presence: Record<string, string>\n /**\n * The server closed this socket for a newer session of the same user (another device, close\n * code 1008). The socket stays closed: reconnecting would only be evicted again.\n */\n evicted: boolean\n setStatus: (status: ArbiWsStatus) => void\n setEvicted: (evicted: boolean) => void\n /**\n * Take a `task_update`, unless it is older than the one held for its document (`seq`) or the\n * document was dismissed a moment ago. Resolves whether it was taken.\n */\n applyTaskUpdate: (msg: WsTaskUpdateMessage) => boolean\n /** Set a document's live processing directly (an optimistic status, or an undo). */\n putTask: (task: LiveTask) => void\n /** Drop a document's processing row, and ignore its late updates for a while. */\n clearTask: (docId: string) => void\n /** Drop every finished processing row (the in-flight ones stay). */\n clearFinishedTasks: () => void\n /** End the in-flight statuses that documents read since say finished after them. */\n settleTasks: (rows: ReadonlyArray<SequencedRow & { external_id: string }>) => void\n applyPresence: (msg: WsPresenceUpdateMessage) => void\n reset: () => void\n}\n\nconst finished = (status: string) => FINISHED_DOCUMENT_STATUSES.has(status)\n\nexport const useArbiWsStore = create<ArbiWsState>((set, get) => ({\n status: 'disconnected',\n tasks: {},\n dismissed: {},\n lastTaskUpdate: null,\n presence: {},\n evicted: false,\n setStatus: (status) => set({ status }),\n setEvicted: (evicted) => set({ evicted }),\n applyTaskUpdate: (msg) => {\n const { tasks, dismissed } = get()\n const dismissedAt = dismissed[msg.doc_ext_id]\n if (dismissedAt !== undefined && Date.now() - dismissedAt < DISMISSED_TASK_TTL_MS) return false\n const held = tasks[msg.doc_ext_id]\n if (isStaleTaskUpdate(held, msg)) return false\n const now = Date.now()\n const task: LiveTask = {\n ...msg,\n startTime: held?.startTime ?? now,\n endTime: finished(msg.status) ? (held?.endTime ?? now) : undefined,\n }\n set({ tasks: { ...tasks, [msg.doc_ext_id]: task }, lastTaskUpdate: msg })\n return true\n },\n putTask: (task) => set((s) => ({ tasks: { ...s.tasks, [task.doc_ext_id]: task } })),\n clearTask: (docId) =>\n set((s) => {\n const tasks = { ...s.tasks }\n delete tasks[docId]\n return { tasks, dismissed: { ...s.dismissed, [docId]: Date.now() } }\n }),\n clearFinishedTasks: () =>\n set((s) => ({\n tasks: Object.fromEntries(Object.entries(s.tasks).filter(([, t]) => !finished(t.status))),\n })),\n settleTasks: (rows) =>\n set((s) => {\n const settled = settledByRows(s.tasks, rows)\n if (!settled.length) return s\n const tasks = { ...s.tasks }\n const now = Date.now()\n for (const task of settled)\n tasks[task.doc_ext_id] = { ...(task as LiveTask), endTime: task.endTime ?? now }\n return { tasks }\n }),\n applyPresence: (msg) => set((s) => ({ presence: { ...s.presence, [msg.user_id]: msg.status } })),\n reset: () =>\n set({ status: 'disconnected', tasks: {}, dismissed: {}, lastTaskUpdate: null, presence: {} }),\n}))\n","/**\n * Reading documents: a workspace's list (`useDocuments`, progressive, read once and then patched in\n * place), one document (`useDocument`, for a viewer), a set of documents by id, near-duplicate pairs\n * (`useSimilarDocuments`), and {@link refreshDocuments}, which re-reads just the documents an event\n * named and patches them into every cache that shows them.\n */\n\nimport { useCallback } from 'react'\nimport { useQuery, useQueryClient, type QueryClient } from '@tanstack/react-query'\nimport type { Arbi } from '@arbidocs/sdk/browser'\nimport { useArbi } from '../useArbi'\nimport { arbiQueryKeys } from '../hooks'\nimport { invalidateTagTables, patchWorkspaceTags } from '../tags'\nimport {\n getCachedDocuments,\n setCachedDocument,\n upsertDocuments,\n type WorkspaceDocument,\n} from './documents-cache'\nimport { loadDocuments } from './documents-loader'\nimport { FINISHED_DOCUMENT_STATUSES, isRowNewer } from './processing-order'\nimport { useArbiWsStore } from '../websocket/store'\n\nexport { FINISHED_DOCUMENT_STATUSES }\n\n/** The workspace open on `arbi`, or `null`. */\nfunction openWorkspaceId(arbi: Arbi): string | null {\n return arbi.hasWorkspace ? arbi.getWorkspaceId() : null\n}\n\n/**\n * A workspace's documents (default: the open one). Read progressively: the first page is the\n * result, the remaining pages arrive in the background (`useDocumentsLoading`). After that the list\n * is never re-read on its own (mounting, focus, reconnecting): writes, processing events and\n * {@link refreshDocuments} patch it in place, as re-reading 100k documents is slow and tells\n * nothing new. Invalidating it re-reads it.\n */\nexport function useDocuments(workspaceId?: string | null, options?: { enabled?: boolean }) {\n const arbi = useArbi()\n const qc = useQueryClient()\n const workspace = workspaceId ?? openWorkspaceId(arbi) ?? ''\n return useQuery({\n queryKey: arbiQueryKeys.documents(workspace),\n queryFn: ({ signal }) => {\n if (openWorkspaceId(arbi) !== workspace)\n return Promise.reject(new Error('The selected workspace changed.'))\n return loadDocuments(qc, arbi, workspace, signal)\n },\n enabled: (options?.enabled ?? true) && !!workspace && arbi.hasWorkspace,\n staleTime: Infinity,\n refetchOnMount: false,\n refetchOnReconnect: false,\n refetchOnWindowFocus: false,\n })\n}\n\n/** How often a document still being processed is re-read (`useDocument`'s `pollWhileProcessing`). */\nexport const DOCUMENT_STATUS_POLL_MS = 4000\n\n/** Re-read a document while it is processing (a viewer waiting for its pages). */\nfunction processingInterval(doc: WorkspaceDocument | null | undefined): number | false {\n return doc?.status && !FINISHED_DOCUMENT_STATUSES.has(doc.status)\n ? DOCUMENT_STATUS_POLL_MS\n : false\n}\n\n/**\n * One document (`null`: not found or not visible). `pollWhileProcessing` re-reads it every few\n * seconds until its processing is over. Writes here keep it current.\n */\nexport function useDocument(\n docId: string | null | undefined,\n options?: { enabled?: boolean; pollWhileProcessing?: boolean }\n) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.document(docId ?? ''),\n queryFn: async (): Promise<WorkspaceDocument | null> =>\n (await arbi.documents.get([docId as string]))[0] ?? null,\n enabled: (options?.enabled ?? true) && !!docId && arbi.isLoggedIn,\n refetchInterval: options?.pollWhileProcessing\n ? (query) => processingInterval(query.state.data)\n : false,\n })\n}\n\n/** Several documents by id, in one request (cited documents, a selection from elsewhere). */\nexport function useDocumentsById(docIds: string[], options?: { enabled?: boolean }) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.documentsById(docIds),\n queryFn: () => arbi.documents.get(docIds),\n enabled: (options?.enabled ?? true) && docIds.length > 0 && arbi.isLoggedIn,\n })\n}\n\n/**\n * The similarity at or above which two documents count as near duplicates (the Related column).\n * The server keeps every pair above 0.75 but returns only those at or above what is asked.\n */\nexport const SIMILARITY_THRESHOLD = 0.98\n\n/** Near-duplicate document pairs in the open workspace, at or above {@link SIMILARITY_THRESHOLD}. */\nexport function useSimilarDocuments(options?: { enabled?: boolean }) {\n const arbi = useArbi()\n const workspace = openWorkspaceId(arbi) ?? ''\n return useQuery({\n queryKey: arbiQueryKeys.similarDocuments(workspace, SIMILARITY_THRESHOLD),\n queryFn: () =>\n arbi.readInWorkspace(workspace, () =>\n arbi.documents.similar({ threshold: SIMILARITY_THRESHOLD })\n ),\n enabled: (options?.enabled ?? true) && !!workspace,\n })\n}\n\n// Each re-read gets a number; only the latest one issued for a document may write it. Events can\n// return out of order, and an older read must not undo tags a newer one applied.\nlet readSeq = 0\nconst latestReadByDoc = new Map<string, number>()\n\n/**\n * Re-read `docIds` and patch them into the caches that show them: their workspace's list (added\n * when new), their own entries, and the tag list's document counts (tags the server applied, e.g.\n * AI fields). For events that name documents (a batch finished, a version saved, an upload): the\n * list is never re-read for them. A failed read leaves the caches as they were.\n */\nexport async function refreshDocuments(\n qc: QueryClient,\n arbi: Arbi,\n docIds: string[]\n): Promise<WorkspaceDocument[]> {\n if (!docIds.length) return []\n const seq = ++readSeq\n for (const id of docIds) latestReadByDoc.set(id, seq)\n try {\n const read = await arbi.documents.get(docIds)\n const fresh = read\n .filter((doc) => latestReadByDoc.get(doc.external_id) === seq)\n .map((doc) => {\n // A finished status heard live wins over a read that predates it (the row may not be\n // committed yet), never over a row that finished after it.\n const live = useArbiWsStore.getState().tasks[doc.external_id]\n return live &&\n FINISHED_DOCUMENT_STATUSES.has(live.status) &&\n doc.status !== live.status &&\n isRowNewer(doc, live) !== true\n ? { ...doc, status: live.status }\n : doc\n })\n if (!fresh.length) return []\n reconcileTagCounts(qc, fresh)\n upsertDocuments(qc, fresh)\n for (const doc of fresh) setCachedDocument(qc, doc)\n return fresh\n } catch (error) {\n // Leave the caches as they were: re-reading the whole list would shrink it to its first page.\n console.error('Re-reading documents failed; the cached ones are kept:', error)\n return []\n } finally {\n for (const id of docIds) if (latestReadByDoc.get(id) === seq) latestReadByDoc.delete(id)\n }\n}\n\n/** `refreshDocuments` on this host's cache and `Arbi`, for a component or a hook. */\nexport function useRefreshDocuments(): (docIds: string[]) => Promise<WorkspaceDocument[]> {\n const qc = useQueryClient()\n const arbi = useArbi()\n return useCallback((docIds: string[]) => refreshDocuments(qc, arbi, docIds), [qc, arbi])\n}\n\n/** Move each tag's document count by the tags the re-read documents gained or lost. */\nfunction reconcileTagCounts(qc: QueryClient, fresh: WorkspaceDocument[]): void {\n const byWorkspace = new Map<string, Map<string, number>>()\n for (const doc of fresh) {\n const cached = getCachedDocuments(qc, doc.workspace_ext_id)?.find(\n (d) => d.external_id === doc.external_id\n )\n const before = new Set((cached?.doctags ?? []).map((dt) => dt.tag_ext_id))\n const after = new Set((doc.doctags ?? []).map((dt) => dt.tag_ext_id))\n const delta = byWorkspace.get(doc.workspace_ext_id) ?? new Map<string, number>()\n for (const id of after) if (!before.has(id)) delta.set(id, (delta.get(id) ?? 0) + 1)\n for (const id of before) if (!after.has(id)) delta.set(id, (delta.get(id) ?? 0) - 1)\n byWorkspace.set(doc.workspace_ext_id, delta)\n }\n for (const [workspaceId, delta] of byWorkspace) adjustTagCounts(qc, workspaceId, delta)\n}\n\n/** Add `delta` (tag id → change) to the tags' document counts; the tag tables re-read. */\nexport function adjustTagCounts(\n qc: QueryClient,\n workspaceId: string,\n delta: Map<string, number>\n): void {\n if (![...delta.values()].some(Boolean)) return\n patchWorkspaceTags(qc, workspaceId, (tags) =>\n tags.map((tag) => {\n const change = delta.get(tag.external_id)\n return change ? { ...tag, doctag_count: Math.max(0, tag.doctag_count + change) } : tag\n })\n )\n void invalidateTagTables(qc, workspaceId)\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/session/layout.ts","../src/session/workspace.ts","../src/chat/run-state.ts","../src/session/store.ts","../src/session/drafts.ts","../src/session/session-hooks.ts","../src/session/signed-in.ts","../src/session/persist.ts","../src/usage-metered.ts","../src/hooks.ts"],"names":["useSyncExternalStore","useMemo"],"mappings":"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","file":"chunk-OSWKXZTJ.js","sourcesContent":["/**\n * The layout part of the session state: the shell (the page on screen, the sidebar, the panels and\n * where each one shows, the area with focus), the open tabs (direct messages, projects), each\n * page's view (its tab, its filters, other view settings) and the grids' saved state. Kits and the\n * host read and change it through the session store; the parts a person arranges (the page, the\n * pinned sidebar, the panels, the views, the grids) are kept across reloads by the host's\n * {@link ArbiSessionPersist}.\n */\n\nimport type { ArbiSessionPersist } from './persist'\n\n/** Where a panel shows: the page's area, docked beside it, over it, or in its own window. */\nexport type ArbiPanelMode = 'main' | 'docked' | 'overlay' | 'popout'\n\nexport interface ArbiPanelsState {\n /** The panel in each place (one each): filling the page, docked, over the page, popped out. */\n main: string | null\n docked: string | null\n overlay: string | null\n popout: string | null\n /** Where each panel last showed (it opens there again). */\n modes: Readonly<Record<string, ArbiPanelMode>>\n /** A floating panel's size. */\n sizes: Readonly<Record<string, { width: number; height: number }>>\n}\n\nexport interface ArbiSidebarState {\n /** Pinned open (on wide screens; phones show a drawer). */\n pinned: boolean\n /** The rail is expanded under the pointer. */\n hovering: boolean\n /** The phone drawer is open. */\n drawerOpen: boolean\n}\n\nexport interface ArbiShellState {\n /** The page on screen (a host's page id). */\n page: string\n sidebar: ArbiSidebarState\n panels: ArbiPanelsState\n /** The area with focus: `main` or a panel id. */\n focusedArea: string\n}\n\n/** A direct-message tab: a person's or agent's id, a group chat's id, or null (a new message). */\nexport interface ArbiDmTab {\n recipientId: string | null\n}\n\nexport interface ArbiTabsState {\n dm: readonly ArbiDmTab[]\n activeDm: string | null\n /** The message a direct-message tab scrolls to once open. */\n dmMessageId: string | null\n projects: readonly string[]\n activeProject: string | null\n}\n\nexport interface ArbiViewsState {\n /** Each page's tab, by page. */\n tabs: Readonly<Record<string, string>>\n /** Each list's quick filters, by list. */\n filters: Readonly<Record<string, unknown>>\n /** Other view settings, by key (a page's view mode, a zoom, a filter box's text). */\n values: Readonly<Record<string, unknown>>\n /** View state kept for this session only, by key (a search's results); not saved. */\n transient: Readonly<Record<string, unknown>>\n}\n\nexport interface ArbiGridLayoutState {\n /** Each grid's saved state (columns, widths, sort), by grid id. */\n states: Readonly<Record<string, unknown>>\n /** Each grid's row height. */\n rowHeights: Readonly<Record<string, number>>\n /** Each timeline's label column width. */\n labelWidths: Readonly<Record<string, number>>\n /** Views an earlier build saved on this device, by grid id (moved to user settings once). */\n savedViews: Readonly<Record<string, readonly unknown[]>>\n}\n\nexport interface ArbiLayoutState {\n shell: ArbiShellState\n tabs: ArbiTabsState\n views: ArbiViewsState\n grid: ArbiGridLayoutState\n}\n\n/** What is kept across reloads. */\nexport interface ArbiSavedLayout {\n version: 1\n /** The pieces an earlier build's own saved state was brought in for (the host's migration). */\n migrated: string[]\n shell: {\n page: string\n sidebarPinned: boolean\n panels: { main: string | null; docked: string | null } & Pick<\n ArbiPanelsState,\n 'modes' | 'sizes'\n >\n }\n views: Omit<ArbiViewsState, 'transient'>\n grid: ArbiGridLayoutState\n}\n\nconst PANEL_MODES: readonly ArbiPanelMode[] = ['main', 'docked', 'overlay', 'popout']\n\n/** Phones start with the sidebar as a drawer, wider screens pinned. */\nconst defaultPinned = () => typeof window === 'undefined' || window.innerWidth >= 640\n\nexport function defaultLayoutState(): ArbiLayoutState {\n return {\n shell: {\n page: 'home',\n sidebar: { pinned: defaultPinned(), hovering: false, drawerOpen: false },\n panels: { main: null, docked: null, overlay: null, popout: null, modes: {}, sizes: {} },\n focusedArea: 'main',\n },\n tabs: { dm: [], activeDm: null, dmMessageId: null, projects: [], activeProject: null },\n views: { tabs: {}, filters: {}, values: {}, transient: {} },\n grid: { states: {}, rowHeights: {}, labelWidths: {}, savedViews: {} },\n }\n}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\nconst recordOf = <T>(value: unknown, keep: (entry: unknown) => entry is T): Record<string, T> =>\n isRecord(value)\n ? (Object.fromEntries(Object.entries(value).filter(([, v]) => keep(v))) as Record<string, T>)\n : {}\n\nconst isString = (v: unknown): v is string => typeof v === 'string'\nconst isNumber = (v: unknown): v is number => typeof v === 'number' && Number.isFinite(v)\nconst isAny = (v: unknown): v is unknown => v !== undefined\nconst isMode = (v: unknown): v is ArbiPanelMode => PANEL_MODES.includes(v as ArbiPanelMode)\nconst isSize = (v: unknown): v is { width: number; height: number } =>\n isRecord(v) && isNumber(v.width) && isNumber(v.height)\nconst isList = (v: unknown): v is unknown[] => Array.isArray(v)\nconst stringOrNull = (v: unknown): string | null => (isString(v) ? v : null)\n\n/**\n * A saved layout as this build reads it: whatever an earlier or a broken save left is dropped\n * rather than read. Never throws; null when there is nothing usable.\n */\nexport function parseSavedLayout(saved: unknown): ArbiSavedLayout | null {\n if (!isRecord(saved) || saved.version !== 1) return null\n const shell = isRecord(saved.shell) ? saved.shell : {}\n const panels = isRecord(shell.panels) ? shell.panels : {}\n const views = isRecord(saved.views) ? saved.views : {}\n const grid = isRecord(saved.grid) ? saved.grid : {}\n const defaults = defaultLayoutState()\n return {\n version: 1,\n migrated: isList(saved.migrated) ? saved.migrated.filter(isString) : [],\n shell: {\n page: isString(shell.page) ? shell.page : defaults.shell.page,\n sidebarPinned:\n typeof shell.sidebarPinned === 'boolean'\n ? shell.sidebarPinned\n : defaults.shell.sidebar.pinned,\n panels: {\n main: stringOrNull(panels.main),\n docked: stringOrNull(panels.docked),\n modes: recordOf(panels.modes, isMode),\n sizes: recordOf(panels.sizes, isSize),\n },\n },\n views: {\n tabs: recordOf(views.tabs, isString),\n filters: recordOf(views.filters, isAny),\n values: recordOf(views.values, isAny),\n },\n grid: {\n states: recordOf(grid.states, isRecord),\n rowHeights: recordOf(grid.rowHeights, isNumber),\n labelWidths: recordOf(grid.labelWidths, isNumber),\n savedViews: recordOf(grid.savedViews, isList),\n },\n }\n}\n\n/** What of a layout is saved. */\nexport function savedLayoutOf(layout: ArbiLayoutState, migrated: string[]): ArbiSavedLayout {\n const { shell, views, grid } = layout\n return {\n version: 1,\n migrated,\n shell: {\n page: shell.page,\n sidebarPinned: shell.sidebar.pinned,\n // A panel over the page or in its own window does not come back after a reload.\n panels: {\n main: shell.panels.main,\n docked: shell.panels.docked,\n modes: shell.panels.modes,\n sizes: shell.panels.sizes,\n },\n },\n views: { tabs: views.tabs, filters: views.filters, values: views.values },\n grid,\n }\n}\n\n/** The layout a saved one restores (the parts not saved keep their current values). */\nexport function restoreLayout(current: ArbiLayoutState, saved: ArbiSavedLayout): ArbiLayoutState {\n return {\n ...current,\n shell: {\n ...current.shell,\n page: saved.shell.page,\n sidebar: { ...current.shell.sidebar, pinned: saved.shell.sidebarPinned },\n panels: { ...current.shell.panels, ...saved.shell.panels },\n },\n views: { ...saved.views, transient: current.views.transient },\n grid: saved.grid,\n }\n}\n\n// ── Changes ─────────────────────────────────────────────────────────────────────────────────────\n\n/** Show a panel in a place: it leaves the place it was in, and what was in that place closes. */\nexport function openPanelIn(\n panels: ArbiPanelsState,\n panelId: string,\n mode: ArbiPanelMode\n): ArbiPanelsState {\n const leave = (slot: string | null) => (slot === panelId ? null : slot)\n const next: ArbiPanelsState = {\n ...panels,\n main: leave(panels.main),\n docked: leave(panels.docked),\n overlay: leave(panels.overlay),\n popout: leave(panels.popout),\n modes: { ...panels.modes, [panelId]: mode },\n }\n // Docked and over the page are both the secondary surface beside the page: one at a time.\n if (mode === 'docked') return { ...next, docked: panelId, overlay: null }\n if (mode === 'overlay') return { ...next, overlay: panelId, docked: null }\n return { ...next, [mode]: panelId }\n}\n\nexport function closePanelIn(panels: ArbiPanelsState, panelId: string): ArbiPanelsState {\n const leave = (slot: string | null) => (slot === panelId ? null : slot)\n return {\n ...panels,\n main: leave(panels.main),\n docked: leave(panels.docked),\n overlay: leave(panels.overlay),\n popout: leave(panels.popout),\n }\n}\n\n/** Where a panel shows now, or null while it is closed. */\nexport function panelPlace(panels: ArbiPanelsState, panelId: string): ArbiPanelMode | null {\n return PANEL_MODES.find((mode) => panels[mode] === panelId) ?? null\n}\n\n/** Whether a panel is open (anywhere). */\nexport const isPanelOpen = (state: { shell: ArbiShellState }, panelId: string): boolean =>\n panelPlace(state.shell.panels, panelId) !== null\n\nexport const dmTabId = (tab: ArbiDmTab): string => tab.recipientId ?? 'new'\n\n/** The actions on the layout (part of {@link ArbiSessionStore}). */\nexport interface ArbiLayoutActions {\n /** Show a page; the focus goes to the page area. */\n setPage(page: string): void\n setSidebar(change: Partial<ArbiSidebarState>): void\n /** Show a panel in a place (`mode`), focused. */\n openPanel(panelId: string, mode: ArbiPanelMode): void\n closePanel(panelId: string): void\n /** Where a panel shows: an open one moves there, a closed one opens there next time. */\n setPanelMode(panelId: string, mode: ArbiPanelMode): void\n setPanelSize(panelId: string, size: { width: number; height: number }): void\n setFocusedArea(area: string): void\n /** Open (or show) a direct-message tab, optionally scrolled to a message. */\n openDmTab(recipientId: string | null, messageId?: string): void\n closeDmTab(tabId: string): void\n /** null: no direct-message tab (the panel's own). */\n selectDmTab(tabId: string | null): void\n clearDmTabs(): void\n setDmMessageId(messageId: string | null): void\n openProjectTab(projectId: string): void\n closeProjectTab(projectId: string): void\n /** null: the projects list. */\n selectProjectTab(projectId: string | null): void\n setPageTab(page: string, tab: string): void\n setViewFilter(key: string, value: unknown): void\n setViewValue(key: string, value: unknown): void\n /** Set (or with `undefined`, drop) view state kept for this session only. */\n setTransientView(key: string, value: unknown): void\n setGridState(gridId: string, state: unknown): void\n clearGridState(gridId: string): void\n setGridRowHeight(gridId: string, height: number): void\n setGridLabelWidth(gridId: string, width: number): void\n setGridSavedViews(gridId: string, views: readonly unknown[]): void\n /**\n * Start over: a sign-in shows the home page with the sidebar at its default and no panel, tab\n * or page tab open; a sign-out also forgets the grids.\n */\n resetLayout(variant: 'login' | 'logout'): void\n}\n\n/** A store of the layout alone; the session stores are built on it. */\nexport interface ArbiLayoutStore extends ArbiLayoutActions {\n getLayout(): ArbiLayoutState\n /** Back to the defaults, everything (unit tests; a reset from an error screen). */\n reset(): void\n subscribe(listener: () => void): () => void\n /** Resolves once the saved layout has been read (at once without a `persist`). */\n hydrated(): Promise<void>\n isHydrated(): boolean\n}\n\nexport interface ArbiLayoutStoreOptions {\n persist?: ArbiSessionPersist<ArbiSavedLayout>\n}\n\nexport function createArbiLayoutStore({ persist }: ArbiLayoutStoreOptions = {}): ArbiLayoutStore {\n let layout = defaultLayoutState()\n let migrated: string[] = []\n let isHydrated = !persist\n const listeners = new Set<() => void>()\n const save = () => {\n // Nothing is saved before the saved layout is read: it would overwrite it with the defaults.\n if (persist && isHydrated) persist.save(savedLayoutOf(layout, migrated))\n }\n const update = (next: ArbiLayoutState) => {\n if (next === layout) return\n const persisted =\n next.views.tabs !== layout.views.tabs ||\n next.views.filters !== layout.views.filters ||\n next.views.values !== layout.views.values ||\n next.grid !== layout.grid ||\n next.shell.page !== layout.shell.page ||\n next.shell.sidebar.pinned !== layout.shell.sidebar.pinned ||\n next.shell.panels !== layout.shell.panels\n layout = next\n listeners.forEach((listener) => listener())\n if (persisted) save()\n }\n const shell = (change: Partial<ArbiShellState>) =>\n update({ ...layout, shell: { ...layout.shell, ...change } })\n const tabs = (change: Partial<ArbiTabsState>) =>\n update({ ...layout, tabs: { ...layout.tabs, ...change } })\n const views = (change: Partial<ArbiViewsState>) =>\n update({ ...layout, views: { ...layout.views, ...change } })\n const grid = (change: Partial<ArbiGridLayoutState>) =>\n update({ ...layout, grid: { ...layout.grid, ...change } })\n\n const hydration: Promise<void> = persist\n ? persist.load().then(\n (saved) => {\n const parsed = parseSavedLayout(saved)\n if (parsed) {\n migrated = parsed.migrated\n layout = restoreLayout(layout, parsed)\n }\n isHydrated = true\n listeners.forEach((listener) => listener())\n },\n () => {\n isHydrated = true\n listeners.forEach((listener) => listener())\n }\n )\n : Promise.resolve()\n\n return {\n getLayout: () => layout,\n reset: () => update(defaultLayoutState()),\n subscribe: (listener) => {\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n hydrated: () => hydration,\n isHydrated: () => isHydrated,\n setPage: (page) => {\n if (layout.shell.page !== page || layout.shell.focusedArea !== 'main')\n shell({ page, focusedArea: 'main' })\n },\n setSidebar: (change) => {\n const sidebar = { ...layout.shell.sidebar, ...change }\n const current = layout.shell.sidebar\n if (\n sidebar.pinned !== current.pinned ||\n sidebar.hovering !== current.hovering ||\n sidebar.drawerOpen !== current.drawerOpen\n )\n shell({ sidebar })\n },\n openPanel: (panelId, mode) =>\n shell({ panels: openPanelIn(layout.shell.panels, panelId, mode), focusedArea: panelId }),\n closePanel: (panelId) =>\n shell({ panels: closePanelIn(layout.shell.panels, panelId), focusedArea: 'main' }),\n setPanelMode: (panelId, mode) => {\n const panels = layout.shell.panels\n if (panelPlace(panels, panelId) !== null)\n shell({ panels: openPanelIn(panels, panelId, mode), focusedArea: panelId })\n else if (panels.modes[panelId] !== mode)\n shell({ panels: { ...panels, modes: { ...panels.modes, [panelId]: mode } } })\n },\n setPanelSize: (panelId, size) => {\n const panels = layout.shell.panels\n shell({ panels: { ...panels, sizes: { ...panels.sizes, [panelId]: size } } })\n },\n setFocusedArea: (focusedArea) => {\n if (layout.shell.focusedArea !== focusedArea) shell({ focusedArea })\n },\n openDmTab: (recipientId, messageId) => {\n const id = recipientId ?? 'new'\n const dm = layout.tabs.dm.some((tab) => dmTabId(tab) === id)\n ? layout.tabs.dm\n : [...layout.tabs.dm, { recipientId }]\n tabs({ dm, activeDm: id, ...(messageId ? { dmMessageId: messageId } : {}) })\n },\n closeDmTab: (tabId) => {\n const dm = layout.tabs.dm.filter((tab) => dmTabId(tab) !== tabId)\n if (dm.length === layout.tabs.dm.length) return\n if (dm.length === 0) return tabs({ dm, activeDm: null })\n if (layout.tabs.activeDm !== tabId) return tabs({ dm })\n // The tab beside the closed one shows.\n const index = layout.tabs.dm.findIndex((tab) => dmTabId(tab) === tabId)\n tabs({ dm, activeDm: dmTabId(dm[Math.min(index, dm.length - 1)]) })\n },\n selectDmTab: (activeDm) => {\n if (layout.tabs.activeDm !== activeDm) tabs({ activeDm })\n },\n clearDmTabs: () => tabs({ dm: [], activeDm: null }),\n setDmMessageId: (dmMessageId) => {\n if (layout.tabs.dmMessageId !== dmMessageId) tabs({ dmMessageId })\n },\n openProjectTab: (projectId) =>\n tabs({\n projects: layout.tabs.projects.includes(projectId)\n ? layout.tabs.projects\n : [...layout.tabs.projects, projectId],\n activeProject: projectId,\n }),\n closeProjectTab: (projectId) => {\n const projects = layout.tabs.projects.filter((id) => id !== projectId)\n if (projects.length === layout.tabs.projects.length) return\n if (layout.tabs.activeProject !== projectId) return tabs({ projects })\n const index = layout.tabs.projects.indexOf(projectId)\n tabs({\n projects,\n activeProject: projects.length ? projects[Math.min(index, projects.length - 1)] : null,\n })\n },\n selectProjectTab: (activeProject) => {\n if (layout.tabs.activeProject !== activeProject) tabs({ activeProject })\n },\n setPageTab: (page, tab) => {\n if (layout.views.tabs[page] !== tab) views({ tabs: { ...layout.views.tabs, [page]: tab } })\n },\n setViewFilter: (key, value) => views({ filters: { ...layout.views.filters, [key]: value } }),\n setViewValue: (key, value) => {\n if (layout.views.values[key] !== value)\n views({ values: { ...layout.views.values, [key]: value } })\n },\n setTransientView: (key, value) => {\n if (layout.views.transient[key] === value) return\n const transient = { ...layout.views.transient }\n if (value === undefined) delete transient[key]\n else transient[key] = value\n views({ transient })\n },\n setGridState: (gridId, state) => grid({ states: { ...layout.grid.states, [gridId]: state } }),\n clearGridState: (gridId) => {\n if (!(gridId in layout.grid.states)) return\n const states = { ...layout.grid.states }\n delete states[gridId]\n grid({ states })\n },\n setGridRowHeight: (gridId, height) =>\n grid({ rowHeights: { ...layout.grid.rowHeights, [gridId]: height } }),\n setGridLabelWidth: (gridId, width) =>\n grid({ labelWidths: { ...layout.grid.labelWidths, [gridId]: width } }),\n setGridSavedViews: (gridId, saved) =>\n grid({ savedViews: { ...layout.grid.savedViews, [gridId]: saved } }),\n resetLayout: (variant) => {\n const fresh = defaultLayoutState()\n update({\n shell: {\n ...fresh.shell,\n panels: {\n ...fresh.shell.panels,\n modes: layout.shell.panels.modes,\n sizes: layout.shell.panels.sizes,\n },\n },\n tabs: fresh.tabs,\n views: { ...layout.views, tabs: {}, transient: {} },\n grid: variant === 'logout' ? { ...layout.grid, states: {} } : layout.grid,\n })\n },\n }\n}\n","/**\n * The session's selected workspace (`workspaceId`) and where it stands on the server session\n * (`workspaceStatus`). `useSwitchWorkspace` moves both; a session store reads them from here.\n *\n * The selection is kept per tab (sessionStorage), so a reload stays in the workspace and each tab\n * can be in a different one; a new sign-in starts with none ({@link ArbiWorkspaceStore.reset}).\n * The status is never kept: after a reload the server session is new, and\n * `useOpenSelectedWorkspace` opens the kept selection again.\n */\n\nimport type { ArbiWorkspaceStatus } from './store'\n\n/** Where the selection is kept across reloads. */\nexport interface ArbiWorkspaceStorage {\n load(): string | null\n save(workspaceId: string | null): void\n}\n\n/** The selection and its status. */\nexport interface ArbiWorkspaceState {\n workspaceId: string | null\n workspaceStatus: ArbiWorkspaceStatus\n}\n\nexport interface ArbiWorkspaceStore {\n getState(): ArbiWorkspaceState\n subscribe(listener: () => void): () => void\n setWorkspaceId(workspaceId: string | null): void\n setWorkspaceStatus(status: ArbiWorkspaceStatus): void\n /** No workspace, closed (a sign-in or sign-out: the next person starts on the workspace list). */\n reset(): void\n}\n\nexport interface ArbiWorkspaceStoreOptions {\n storage?: ArbiWorkspaceStorage\n /** The selection to start with instead of the kept one. */\n workspaceId?: string | null\n}\n\nexport function createArbiWorkspaceStore({\n storage,\n workspaceId = storage?.load() ?? null,\n}: ArbiWorkspaceStoreOptions = {}): ArbiWorkspaceStore {\n let state: ArbiWorkspaceState = { workspaceId, workspaceStatus: 'closed' }\n const listeners = new Set<() => void>()\n const update = (patch: Partial<ArbiWorkspaceState>) => {\n state = { ...state, ...patch }\n listeners.forEach((listener) => listener())\n }\n const setWorkspaceId = (id: string | null) => {\n storage?.save(id)\n if (state.workspaceId !== id) update({ workspaceId: id })\n }\n return {\n getState: () => state,\n subscribe: (listener) => {\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n setWorkspaceId,\n setWorkspaceStatus: (workspaceStatus) => {\n if (state.workspaceStatus !== workspaceStatus) update({ workspaceStatus })\n },\n reset: () => {\n storage?.save(null)\n if (state.workspaceId !== null || state.workspaceStatus !== 'closed')\n update({ workspaceId: null, workspaceStatus: 'closed' })\n },\n }\n}\n\n/** The sessionStorage key of the selection (per tab). */\nexport const WORKSPACE_STORAGE_KEY = 'arbi_workspace_id'\n/** The localStorage key of when each workspace was last opened (per browser). */\nexport const WORKSPACE_LAST_OPENED_KEY = 'arbi_workspace_last_opened'\n\nexport interface BrowserWorkspaceStorageOptions {\n /** Default {@link WORKSPACE_STORAGE_KEY}. */\n key?: string\n /** Default {@link WORKSPACE_LAST_OPENED_KEY}. */\n lastOpenedKey?: string\n}\n\n/**\n * The browser's: the selection per tab (sessionStorage), and when each workspace was last opened\n * per browser (localStorage, read with {@link readWorkspaceLastOpened}: \"recently opened\" is a\n * history that outlives a tab, the selection deliberately does not).\n */\nexport function browserWorkspaceStorage({\n key = WORKSPACE_STORAGE_KEY,\n lastOpenedKey = WORKSPACE_LAST_OPENED_KEY,\n}: BrowserWorkspaceStorageOptions = {}): ArbiWorkspaceStorage {\n return {\n load() {\n try {\n return window.sessionStorage.getItem(key)\n } catch {\n return null\n }\n },\n save(workspaceId) {\n try {\n if (!workspaceId) {\n window.sessionStorage.removeItem(key)\n return\n }\n window.sessionStorage.setItem(key, workspaceId)\n const lastOpened = readWorkspaceLastOpened(lastOpenedKey)\n lastOpened[workspaceId] = Date.now()\n window.localStorage.setItem(lastOpenedKey, JSON.stringify(lastOpened))\n } catch {\n // Storage unavailable (private mode, quota): the selection lives in memory only.\n }\n },\n }\n}\n\n/** When each workspace was last opened in this browser (`external_id` → epoch ms). */\nexport function readWorkspaceLastOpened(\n lastOpenedKey = WORKSPACE_LAST_OPENED_KEY\n): Record<string, number> {\n try {\n const raw = window.localStorage.getItem(lastOpenedKey)\n const parsed: unknown = raw ? JSON.parse(raw) : null\n return parsed && typeof parsed === 'object' && !Array.isArray(parsed)\n ? (parsed as Record<string, number>)\n : {}\n } catch {\n return {}\n }\n}\n","/**\n * The live state of a running turn that is not in the threads cache: follow-ups waiting in the\n * agent bar's queue box, and the run-control state (pause / resume / report). Both are keyed by the\n * streaming answer's id (the response id) and live in the session (`ArbiSessionState`); these are\n * the pure updates every session store applies.\n */\n\nimport type { ProbeAnswerEvent } from '@arbidocs/sdk/browser'\n\n/** A follow-up the person sent while a turn ran, shown in the agent bar until it is its own turn. */\nexport interface QueuedMessage {\n /** The client's own id, unique across turns. */\n clientId: string\n content: string\n /** The stored user message, once the server confirmed the follow-up. */\n serverId: string | null\n acknowledged: boolean\n /** When it was queued (epoch ms): a follow-up stays readable for a moment. */\n createdAt: number\n}\n\n/** Queued follow-ups per running answer (response id). */\nexport type QueuedMessages = Readonly<Record<string, readonly QueuedMessage[]>>\n\n/**\n * Control state of a running agent turn:\n * - `running` normal streaming.\n * - `pausing` the person sent /pause; awaiting the server's confirmed halt (optimistic).\n * - `paused` the server confirmed the loop halted at a boundary.\n * - `resuming` the person sent /resume; awaiting the stream to flow again (optimistic).\n */\nexport type AgentRunControlState = 'running' | 'pausing' | 'paused' | 'resuming'\n\n/** How long a confirmed follow-up stays in the queue box at least, so it can be read. */\nexport const MIN_QUEUED_MESSAGE_VISIBILITY_MS = 800\n\nconst mapQueues = (\n queues: QueuedMessages,\n update: (messages: readonly QueuedMessage[]) => QueuedMessage[]\n): QueuedMessages =>\n Object.fromEntries(Object.entries(queues).map(([id, messages]) => [id, update(messages)]))\n\n/**\n * The client ids of the queued prompts a steering interjection delivered.\n *\n * The backend joins every prompt it steers into one run with a blank line, in the order they were\n * sent. Prompts the backend queued as turns of their own stay in the queue between them, so the\n * steered ones need not be first, or even adjacent: walk the queue in order and take each prompt\n * that is the next part of the delivered text. Nothing is taken unless the whole text is accounted\n * for.\n */\nfunction findConsumedMessages(\n messages: readonly QueuedMessage[],\n combinedContent: string\n): Set<string> {\n const text = combinedContent.trim()\n const taken = new Set<string>()\n let cursor = 0\n for (const message of messages) {\n if (cursor >= text.length) break\n const content = message.content.trim()\n if (!content) continue\n const separator = cursor === 0 ? '' : '\\n\\n'\n if (text.startsWith(separator + content, cursor)) {\n taken.add(message.clientId)\n cursor += separator.length + content.length\n }\n }\n return cursor === text.length ? taken : new Set()\n}\n\n/** The queue updates. Client ids are unique, so the per-entry ones find it under any turn. */\nexport const queuedMessages = {\n add: (q: QueuedMessages, responseId: string, message: QueuedMessage): QueuedMessages => ({\n ...q,\n [responseId]: [...(q[responseId] ?? []), message],\n }),\n acknowledge: (q: QueuedMessages, clientId: string, serverId: string | null): QueuedMessages =>\n mapQueues(q, (messages) =>\n messages.map((m) => (m.clientId === clientId ? { ...m, serverId, acknowledged: true } : m))\n ),\n remove: (q: QueuedMessages, clientId: string): QueuedMessages =>\n mapQueues(q, (messages) => messages.filter((m) => m.clientId !== clientId)),\n removeByServerId: (q: QueuedMessages, serverId: string): QueuedMessages =>\n mapQueues(q, (messages) => messages.filter((m) => m.serverId !== serverId)),\n removeByContent: (q: QueuedMessages, responseId: string, content: string): QueuedMessages => {\n let removed = false\n return {\n ...q,\n [responseId]: (q[responseId] ?? []).filter((m) => {\n if (!removed && m.content === content) {\n removed = true\n return false\n }\n return true\n }),\n }\n },\n /** Take out the prompts a steering interjection delivered into the run. */\n consume: (q: QueuedMessages, responseId: string, combinedContent: string): QueuedMessages => {\n const messages = q[responseId] ?? []\n const consumed = findConsumedMessages(messages, combinedContent)\n return { ...q, [responseId]: messages.filter((m) => !consumed.has(m.clientId)) }\n },\n clear: (q: QueuedMessages, responseId: string): QueuedMessages => ({ ...q, [responseId]: [] }),\n /** Move the entries still waiting on a finished turn to the turn that is now running. */\n move: (q: QueuedMessages, fromResponseId: string, toResponseId: string): QueuedMessages => {\n const waiting = q[fromResponseId] ?? []\n if (fromResponseId === toResponseId || waiting.length === 0) return q\n return { ...q, [fromResponseId]: [], [toResponseId]: [...(q[toResponseId] ?? []), ...waiting] }\n },\n /** Find a queued follow-up by its client id, under whichever turn holds it. */\n find: (q: QueuedMessages, clientId: string): QueuedMessage | undefined =>\n Object.values(q)\n .flat()\n .find((m) => m.clientId === clientId),\n}\n\n/** The transient control state of the running turns, per response id. */\nexport interface AgentControlMaps {\n agentControlStates: Readonly<Record<string, AgentRunControlState>>\n agentProbeAnswers: Readonly<Record<string, ProbeAnswerEvent>>\n agentProbePending: Readonly<Record<string, boolean>>\n}\n\nconst without = <T>(record: Readonly<Record<string, T>>, key: string): Record<string, T> => {\n const next = { ...record }\n delete next[key]\n return next\n}\n\n/** The control updates. */\nexport const agentControl = {\n setState: (c: AgentControlMaps, id: string, state: AgentRunControlState): AgentControlMaps => ({\n ...c,\n agentControlStates: { ...c.agentControlStates, [id]: state },\n }),\n /** A probe answered: the latest answer, and nothing pending any more. */\n setProbeAnswer: (c: AgentControlMaps, id: string, probe: ProbeAnswerEvent): AgentControlMaps => ({\n ...c,\n agentProbeAnswers: { ...c.agentProbeAnswers, [id]: probe },\n agentProbePending: { ...c.agentProbePending, [id]: false },\n }),\n setProbePending: (c: AgentControlMaps, id: string, pending: boolean): AgentControlMaps => ({\n ...c,\n agentProbePending: { ...c.agentProbePending, [id]: pending },\n }),\n /** The turn is over: drop its control state. */\n clear: (c: AgentControlMaps, id: string): AgentControlMaps => ({\n agentControlStates: without(c.agentControlStates, id),\n agentProbeAnswers: without(c.agentProbeAnswers, id),\n agentProbePending: without(c.agentProbePending, id),\n }),\n}\n","/**\n * The session state every block reads and writes: the selected workspace, the current conversation,\n * the document being viewed, the document selection, generation per conversation, Personal\n * Assistant mode and the documents in each conversation.\n *\n * An {@link ArbiSessionStore} is the adapter a host gives as its configuration's `session`:\n * a host with its own state (ARBI-frontend's zustand store) maps its fields onto\n * {@link ArbiSessionState} and its actions onto the setters, so there is one source of truth.\n * Other hosts use {@link createArbiSessionStore}, an in-memory store.\n */\n\nimport type { components } from '@arbidocs/client'\nimport type { ProbeAnswerEvent } from '@arbidocs/sdk/browser'\nimport { parseVersionRef } from '../artifacts/versions'\nimport type { ArbiDraftStorage } from './drafts'\nimport {\n createArbiLayoutStore,\n defaultLayoutState,\n type ArbiLayoutActions,\n type ArbiLayoutState,\n type ArbiLayoutStore,\n type ArbiSavedLayout,\n} from './layout'\nimport type { ArbiSessionPersist } from './persist'\nimport { createArbiWorkspaceStore, type ArbiWorkspaceStore } from './workspace'\nimport {\n agentControl,\n queuedMessages,\n type AgentControlMaps,\n type AgentRunControlState,\n type QueuedMessage,\n type QueuedMessages,\n} from '../chat/run-state'\n\n/** The document being viewed. */\nexport interface ArbiViewingDocument {\n /** The document (`doc-…`), or a version reference (`doc-…@v2`) while an earlier version shows. */\n id: string\n /** The page being read, when known. */\n page: number | null\n /** The passage being read, when one is. */\n passageId: string | null\n}\n\n/** A tab of the document viewer. */\nexport type ArbiViewerTab = 'pdf' | 'edit' | 'html' | 'docx' | 'xlsx' | 'versions' | 'preview'\n\n/**\n * The document viewer's own state, shared with whatever opens documents (a citation opens the text\n * view, Compare from a documents list opens the redline): the open tab, the document compared with\n * the one viewed, and a tab asked for when a document was opened (applied once it has loaded).\n */\nexport interface ArbiDocumentViewerState {\n tab: ArbiViewerTab\n /** The document (or version reference) compared with the viewed one, or null. */\n compareId: string | null\n /** A tab to show once `documentId` has loaded (a signature request opens on the PDF). */\n tabRequest: { documentId: string; tab: ArbiViewerTab } | null\n /** The text view's size, a multiplier of the normal size: a reading preference. */\n textScale: number\n /** A phone user picked the PDF by hand: documents stop opening on the text view. */\n phonePdfChosen: boolean\n}\n\n/** Generation in one conversation. */\nexport interface ArbiConversationGeneration {\n isGenerating: boolean\n error: string | null\n /** When the running turn started (epoch ms). */\n startTime: number | null\n /** The answer being streamed (its response id), once the server named it. */\n streamingAssistantId?: string | null\n /** The server's elapsed time for the running turn (seconds). */\n backendElapsed?: number | null\n /** The question of a send that failed, for Retry. */\n lastFailedMessage?: string | null\n /** The local stream of the running turn, which Stop aborts (absent for an attached run). */\n abortController?: AbortController | null\n}\n\n/** A document in a conversation's context; a pinned one stays there across turns. */\nexport interface ArbiConversationDocument {\n docId: string\n isPinned: boolean\n}\n\n/**\n * Where the selected workspace stands on the server session: `opening` while a switch waits for\n * `/open` (the host may cover the page), `open` once workspace-scoped requests may run.\n */\nexport type ArbiWorkspaceStatus = 'closed' | 'opening' | 'open'\n\nexport interface ArbiSessionState extends AgentControlMaps, ArbiLayoutState {\n /** The selected workspace (`wrk-…`). */\n workspaceId: string | null\n /** Whether it is open on the server session (`useSwitchWorkspace` moves it). */\n workspaceStatus: ArbiWorkspaceStatus\n /** The open conversation, or null for a new one / none. */\n conversationId: string | null\n viewingDocument: ArbiViewingDocument | null\n documentViewer: ArbiDocumentViewerState\n /** The documents selected in document lists. */\n selectedDocumentIds: readonly string[]\n /** Generation state per conversation id. */\n generating: Readonly<Record<string, ArbiConversationGeneration>>\n /** Personal Assistant mode for new conversations. */\n paMode: boolean\n /** The documents in each conversation's context, per conversation id. */\n conversationDocuments: Readonly<Record<string, readonly ArbiConversationDocument[]>>\n /**\n * Per conversation id: true while an empty chat follows the workspace's documents (set by\n * {@link useDocumentAutoAdd}); any other change of its documents is a choice and turns it off.\n * Missing for a selection made before this was recorded.\n */\n conversationDocumentAutoAdd: Readonly<Record<string, boolean>>\n /** The facts in each conversation's context, per conversation id (`new` for a new chat). */\n conversationFacts: Readonly<Record<string, readonly string[]>>\n /** The document read in full with each turn (one at a time). */\n pinnedDocumentId: string | null\n /** The message the open conversation continues from: the leaf of the line being viewed. */\n cursor: string | null\n /** A follow-up the backend suggested for a conversation, offered in its composer. */\n suggestedQuery: { conversationExtId: string; text: string } | null\n /** Follow-ups waiting in a running turn's agent bar, per response id. */\n queuedMessages: QueuedMessages\n /**\n * What is typed in each conversation's composer, per conversation id (`new` for a new chat).\n * The open conversation's is {@link selectDraft}. A host may keep them across reloads, stored\n * locally and encrypted ({@link ArbiDraftStorage}).\n */\n drafts: Readonly<Record<string, string>>\n /** The question being edited in the open conversation (sent as a new branch), or null. */\n editingMessageId: string | null\n /** A message a link opened the conversation at: its thread opens and the view goes to it. */\n deepLinkMessageId: string | null\n /** The citation whose sources are open (`<message id>-<citation number>`), or null. */\n activeCitationKey: string | null\n /** The config (model) chosen for the open conversation; absent: the person's last one. */\n chatModel: string | undefined\n /** The model name the open conversation's picker shows (an edit or a launch sets it). */\n chatModelName: string | undefined\n /** The open thread tabs, least recently used first (`ConnectedThreadTabs` shows them). */\n threadTabs: readonly ArbiThreadTab[]\n /** The thread tab on screen (`threadTabId`), or null while the thread list is. */\n activeThreadTabId: string | null\n /** The mode a new conversation starts in: `always` answers, `mentioned` only when @mentioned. */\n newConversationAssistantMode: 'always' | 'mentioned'\n /** Structured tools a launch wants on the next send (the send consumes them). */\n pendingTools: TurnTools | null\n /**\n * Send the open composer's draft as soon as the conversation is ready (a launch that composed it);\n * the send clears it.\n */\n autoSendDraft: boolean\n /** The owned agent each agent chat runs through, per conversation id. */\n agentChatOwners: Readonly<Record<string, string>>\n /** A new agent chat about to start: its agent and workspace. */\n newAgentChat: { agentId: string; workspaceId: string } | null\n /**\n * The document a new chat about to start is bound to (`doc-…`): set only by starting a chat from\n * a document (\"Chat about this document\") or attaching it in the new chat, never by a document\n * merely being open. Starting another new chat clears it; the first turn moves it to the\n * conversation (`chat/thread-document`).\n */\n newChatDocumentId: string | null\n /** Each answer's timer, saved when it stops showing (`<conversation id>:<message id>`). */\n messageTimers: Readonly<Record<string, ArbiMessageTimer>>\n}\n\n/** An answer's timer: when its run started (epoch ms) and how long it took (seconds). */\nexport interface ArbiMessageTimer {\n startTime: number\n elapsedTime: number\n}\n\n/** A thread tab: a conversation's, or a new chat's (`conversationId` null). */\nexport interface ArbiThreadTab {\n conversationId: string | null\n}\n\n/** A thread tab's id: its conversation's id, or `new` for a new chat. */\nexport const threadTabId = (tab: ArbiThreadTab): string => tab.conversationId ?? 'new'\n\n/** The most thread tabs kept (the least recently used goes first). */\nexport const MAX_THREAD_TABS = 12\n\n/** A send's structured tools (`MessageInput.tools`). */\nexport type TurnTools = components['schemas']['MessageInput']['tools']\n\n/** What to view: page and passage are left unchanged when omitted. */\nexport interface ArbiViewingDocumentInput {\n id: string\n page?: number | null\n passageId?: string | null\n}\n\nexport interface ArbiSessionStore extends ArbiLayoutActions {\n /** The current state. The same object until something in it changes. */\n getState(): ArbiSessionState\n /** Resolves once the saved layout has been read (at once when none is kept). */\n layoutHydrated(): Promise<void>\n /** Whether the saved layout has been read. */\n isLayoutHydrated(): boolean\n /** Be told when the state may have changed. Returns the unsubscribe. */\n subscribe(listener: () => void): () => void\n setWorkspaceId(id: string | null): void\n setWorkspaceStatus(status: ArbiWorkspaceStatus): void\n /**\n * Drop everything scoped to the workspace being left (the open conversation and its generation,\n * the viewed document, the selection, the context documents and facts), before a switch. A host\n * with workspace-scoped state of its own clears that too.\n */\n leaveWorkspace(): void\n setConversationId(id: string | null): void\n /**\n * View a document, or none. Viewing another document resets the page; `page` and `passageId`\n * set them when given.\n */\n setViewingDocument(document: ArbiViewingDocumentInput | null): void\n /** Change the document viewer's state; fields not given stay. */\n setDocumentViewer(change: Partial<ArbiDocumentViewerState>): void\n setSelectedDocumentIds(ids: string[]): void\n /** Start or end a conversation's turn; `abortController` is its local stream, which Stop aborts. */\n setConversationGenerating(\n conversationId: string,\n isGenerating: boolean,\n abortController?: AbortController | null\n ): void\n setPaMode(enabled: boolean): void\n /** Set a conversation's documents; `autoAdd` marks an automatic pick (default: the user's). */\n setConversationDocuments(\n conversationId: string,\n documents: ArbiConversationDocument[],\n autoAdd?: boolean\n ): void\n setConversationFacts(conversationId: string, factIds: string[]): void\n setPinnedDocumentId(id: string | null): void\n /** The answer a conversation is streaming; `startTime` defaults to now (a re-attach passes the run's). */\n setStreamingAssistantId(conversationId: string, assistantId: string, startTime?: number): void\n setBackendElapsed(conversationId: string, seconds: number): void\n /**\n * A new chat got its server id: its generation, documents and facts move from `fromId` (`new`) to\n * `toId`, and it stays the open conversation.\n */\n moveConversation(fromId: string, toId: string): void\n setCursor(messageId: string | null): void\n setSuggestedQuery(suggestion: ArbiSessionState['suggestedQuery']): void\n addQueuedMessage(responseId: string, message: QueuedMessage): void\n acknowledgeQueuedMessage(clientId: string, serverId: string | null): void\n removeQueuedMessage(clientId: string): void\n removeQueuedMessageByServerId(serverId: string): void\n consumeQueuedMessage(responseId: string, combinedContent: string): void\n clearQueuedMessages(responseId: string): void\n moveQueuedMessages(fromResponseId: string, toResponseId: string): void\n setAgentControlState(responseId: string, state: AgentRunControlState): void\n setAgentProbeAnswer(responseId: string, probe: ProbeAnswerEvent): void\n setAgentProbePending(responseId: string, pending: boolean): void\n clearAgentControl(responseId: string): void\n /** Set what is typed in the open conversation's composer. */\n setDraft(text: string): void\n /** The config (model) the open conversation's turns use; undefined: the person's last one. */\n setChatModel(model: string | undefined): void\n setChatModelName(model: string | undefined): void\n /**\n * Show a conversation in its thread tab (null: a new chat), opening the tab when it is not open.\n * Returns the tab's id.\n */\n openThreadTab(conversationId: string | null): string\n /** Close a thread tab; closing the one on screen shows the last other, else the thread list. */\n closeThreadTab(tabId: string): void\n /** Show a thread tab's conversation, or (null) the thread list; the tabs stay open. */\n selectThreadTab(tabId: string | null): void\n setNewConversationAssistantMode(mode: 'always' | 'mentioned'): void\n /** Start a new chat with an owned agent (null: an ordinary new chat). */\n setNewAgentChat(chat: { agentId: string; workspaceId: string } | null): void\n /** Bind the new chat to a document (null: unbound). Opening a new chat's tab clears it. */\n setNewChatDocumentId(documentId: string | null): void\n /** Edit a question: the composer holds it (its draft and line come back on cancel). */\n startEditing(messageId: string, content: string): void\n /** Leave the edit: the composer gets its draft back, and the view the line it was on. */\n cancelEditing(): void\n /** The edit was sent: leave it. */\n completeEditing(): void\n setDeepLinkMessageId(messageId: string | null): void\n setActiveCitationKey(key: string | null): void\n setPendingTools(tools: TurnTools | null): void\n setAutoSendDraft(on: boolean): void\n setAgentChatOwner(conversationId: string, agentId: string): void\n /** Save an answer's timer (`<conversation id>:<message id>`). */\n setMessageTimer(key: string, timer: ArbiMessageTimer): void\n clearMessageTimer(key: string): void\n /** A send failed: the turn stops, with the server's words and the question to retry. */\n setConversationError(\n conversationId: string,\n error: string | null,\n lastFailedMessage?: string | null\n ): void\n clearConversationError(conversationId: string): void\n /** Stop the conversation's local stream and end its turn. */\n abortConversationGeneration(conversationId: string): void\n /** Leave the open conversation for a new one (its conversation was deleted). */\n startNewConversation(): void\n}\n\nexport const DEFAULT_DOCUMENT_VIEWER_STATE: ArbiDocumentViewerState = {\n tab: 'pdf',\n compareId: null,\n tabRequest: null,\n textScale: 1,\n phonePdfChosen: false,\n}\n\nexport const EMPTY_SESSION_STATE: ArbiSessionState = {\n workspaceId: null,\n workspaceStatus: 'closed',\n conversationId: null,\n viewingDocument: null,\n documentViewer: DEFAULT_DOCUMENT_VIEWER_STATE,\n selectedDocumentIds: [],\n generating: {},\n paMode: false,\n conversationDocuments: {},\n conversationDocumentAutoAdd: {},\n conversationFacts: {},\n pinnedDocumentId: null,\n cursor: null,\n suggestedQuery: null,\n queuedMessages: {},\n agentControlStates: {},\n agentProbeAnswers: {},\n agentProbePending: {},\n drafts: {},\n editingMessageId: null,\n deepLinkMessageId: null,\n activeCitationKey: null,\n chatModel: undefined,\n chatModelName: undefined,\n threadTabs: [],\n activeThreadTabId: null,\n newConversationAssistantMode: 'always',\n pendingTools: null,\n autoSendDraft: false,\n agentChatOwners: {},\n newAgentChat: null,\n newChatDocumentId: null,\n messageTimers: {},\n ...defaultLayoutState(),\n}\n\n/** The viewed document itself (`doc-…`), also while one of its earlier versions is on screen. */\nexport const selectViewingDocumentId = (state: ArbiSessionState): string | null =>\n state.viewingDocument ? parseVersionRef(state.viewingDocument.id).docId : null\n\n/** The conversation key drafts and context are kept under: its id, or `new` for a new chat. */\nexport const conversationKey = (state: ArbiSessionState): string => state.conversationId ?? 'new'\n\n/** What is typed in the open conversation's composer. */\nexport const selectDraft = (state: ArbiSessionState): string =>\n state.drafts[conversationKey(state)] ?? ''\n\n/** Whether `conversationId` is generating. */\nexport const selectIsGenerating =\n (conversationId: string | null | undefined) =>\n (state: ArbiSessionState): boolean =>\n !!conversationId && !!state.generating[conversationId]?.isGenerating\n\n/** The next viewing document, given the current one (shared by every store implementation). */\nexport function nextViewingDocument(\n current: ArbiViewingDocument | null,\n input: ArbiViewingDocumentInput | null\n): ArbiViewingDocument | null {\n if (!input) return null\n const same = current?.id === input.id\n return {\n id: input.id,\n page: input.page !== undefined ? input.page : same ? (current?.page ?? null) : null,\n passageId: input.passageId !== undefined ? input.passageId : (current?.passageId ?? null),\n }\n}\n\n/** Options of {@link createArbiSessionStore}. */\nexport interface ArbiSessionStoreOptions {\n /** Keep the composers' drafts across reloads (see {@link createSealedDraftStorage}). */\n draftStorage?: ArbiDraftStorage\n /** Keep the layout across reloads (see {@link createStoragePersist}). */\n persist?: ArbiSessionPersist<ArbiSavedLayout>\n /**\n * The selected workspace and its status (default: in memory, from `initial.workspaceId`). Give\n * one kept per tab (`createArbiWorkspaceStore({ storage: browserWorkspaceStorage() })`) for a\n * reload to stay in the workspace.\n */\n workspace?: ArbiWorkspaceStore\n}\n\n/** The layout actions of a session store, on its layout store. */\nexport function layoutActionsOf(layout: ArbiLayoutStore): ArbiLayoutActions {\n const actions = { ...layout } as Partial<ArbiLayoutStore>\n delete actions.getLayout\n delete actions.subscribe\n delete actions.hydrated\n delete actions.isHydrated\n delete actions.reset\n return actions as ArbiLayoutActions\n}\n\n/** An in-memory session store: the default for hosts without state of their own. */\n/** A per-conversation record without the unsent new chat's entry. */\nfunction withoutNew<T>(record: Readonly<Record<string, T>>): Record<string, T> {\n const { new: _new, ...saved } = record\n return saved\n}\n\nexport function createArbiSessionStore(\n initial: Partial<ArbiSessionState> = {},\n {\n draftStorage,\n persist,\n workspace = createArbiWorkspaceStore({ workspaceId: initial.workspaceId ?? null }),\n }: ArbiSessionStoreOptions = {}\n): ArbiSessionStore {\n const layout = createArbiLayoutStore({ persist })\n if (initial.workspaceStatus) workspace.setWorkspaceStatus(initial.workspaceStatus)\n let state: ArbiSessionState = {\n ...EMPTY_SESSION_STATE,\n ...layout.getLayout(),\n ...initial,\n ...workspace.getState(),\n }\n const listeners = new Set<() => void>()\n const update = (patch: Partial<ArbiSessionState>) => {\n state = { ...state, ...patch }\n listeners.forEach((listener) => listener())\n }\n layout.subscribe(() => update(layout.getLayout()))\n workspace.subscribe(() => update(workspace.getState()))\n // The draft and line the composer had when an edit began, given back when it is cancelled.\n let preEdit: { draft: string; cursor: string | null } = { draft: '', cursor: null }\n // The saved drafts come back once the person's key is there (it is not before sign-in); a draft\n // typed meanwhile wins over its saved copy.\n let draftsRestored = !draftStorage\n // Whose drafts the store holds: another person's never carry over to the next sign-in.\n let draftsOwner = draftStorage?.owner() ?? null\n const restoreDrafts = () => {\n if (!draftStorage) return\n const owner = draftStorage.owner()\n if (owner !== draftsOwner) {\n if (draftsOwner !== null) update({ drafts: {} })\n draftsOwner = owner\n draftsRestored = false\n }\n if (draftsRestored) return\n draftsRestored = true\n void draftStorage.load().then(\n (saved) => {\n if (saved && draftStorage.owner() === owner)\n update({ drafts: { ...saved, ...state.drafts } })\n else draftsRestored = false\n },\n () => {\n draftsRestored = false\n }\n )\n }\n // The session ended: what was typed goes with it.\n draftStorage?.onClear(() => {\n draftsRestored = false\n draftsOwner = null\n preEdit = { draft: '', cursor: null }\n if (Object.keys(state.drafts).length > 0) update({ drafts: {} })\n })\n restoreDrafts()\n const setDrafts = (drafts: Record<string, string>) => {\n update({ drafts })\n draftStorage?.save(drafts)\n }\n const setDraftOf = (key: string, text: string) => {\n if ((state.drafts[key] ?? '') === text) return\n const drafts = { ...state.drafts }\n if (text) drafts[key] = text\n else delete drafts[key]\n setDrafts(drafts)\n }\n return {\n ...layoutActionsOf(layout),\n layoutHydrated: () => layout.hydrated(),\n isLayoutHydrated: () => layout.isHydrated(),\n getState: () => state,\n subscribe: (listener) => {\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n setWorkspaceId: (workspaceId) => {\n workspace.setWorkspaceId(workspaceId)\n // A workspace opens once signed in: the key that opens the saved drafts is there now.\n restoreDrafts()\n },\n setWorkspaceStatus: (workspaceStatus) => workspace.setWorkspaceStatus(workspaceStatus),\n leaveWorkspace: () => {\n // A turn streaming in the workspace being left stops here (the server finishes it).\n Object.values(state.generating).forEach((generation) => generation.abortController?.abort())\n workspace.setWorkspaceStatus('closed')\n update({\n conversationId: null,\n cursor: null,\n viewingDocument: null,\n selectedDocumentIds: [],\n generating: {},\n // Saved conversations keep their documents; the unsent new chat's belong to this workspace.\n conversationDocuments: withoutNew(state.conversationDocuments),\n conversationDocumentAutoAdd: withoutNew(state.conversationDocumentAutoAdd),\n conversationFacts: {},\n pinnedDocumentId: null,\n newAgentChat: null,\n newChatDocumentId: null,\n messageTimers: {},\n threadTabs: [],\n activeThreadTabId: null,\n })\n },\n setConversationId: (conversationId) => {\n // Another conversation opens on its own line, not on the edit or line of the one before.\n if (state.conversationId !== conversationId)\n update({ conversationId, cursor: null, editingMessageId: null })\n },\n setViewingDocument: (input) =>\n update({ viewingDocument: nextViewingDocument(state.viewingDocument, input) }),\n setDocumentViewer: (change) => {\n const next = { ...state.documentViewer, ...change }\n const keys = Object.keys(change) as (keyof ArbiDocumentViewerState)[]\n if (keys.some((key) => next[key] !== state.documentViewer[key]))\n update({ documentViewer: next })\n },\n setSelectedDocumentIds: (ids) => update({ selectedDocumentIds: ids }),\n setConversationGenerating: (conversationId, isGenerating, abortController = null) => {\n const current = state.generating[conversationId]\n update({\n generating: {\n ...state.generating,\n [conversationId]: {\n ...current,\n isGenerating,\n error: isGenerating ? null : (current?.error ?? null),\n startTime: isGenerating ? Date.now() : null,\n streamingAssistantId: isGenerating ? (current?.streamingAssistantId ?? null) : null,\n backendElapsed: isGenerating ? (current?.backendElapsed ?? null) : null,\n abortController,\n },\n },\n })\n },\n setStreamingAssistantId: (conversationId, streamingAssistantId, startTime = Date.now()) => {\n const current = state.generating[conversationId]\n update({\n generating: {\n ...state.generating,\n [conversationId]: {\n ...(current ?? { isGenerating: false, error: null }),\n streamingAssistantId,\n startTime,\n },\n },\n })\n },\n setBackendElapsed: (conversationId, backendElapsed) => {\n const current = state.generating[conversationId] ?? {\n isGenerating: false,\n error: null,\n startTime: null,\n }\n update({\n generating: { ...state.generating, [conversationId]: { ...current, backendElapsed } },\n })\n },\n moveConversation: (fromId, toId) => {\n const move = <T>(record: Readonly<Record<string, T>>): Record<string, T> => {\n const next = { ...record }\n if (fromId in next) {\n next[toId] = next[fromId]\n delete next[fromId]\n }\n return next\n }\n update({\n generating: move(state.generating),\n conversationDocuments: move(state.conversationDocuments),\n conversationDocumentAutoAdd: move(state.conversationDocumentAutoAdd),\n conversationFacts: move(state.conversationFacts),\n conversationId: state.conversationId ?? toId,\n // The new chat's tab is now the conversation's.\n threadTabs: state.threadTabs.map((tab) =>\n threadTabId(tab) === fromId ? { conversationId: toId } : tab\n ),\n activeThreadTabId: state.activeThreadTabId === fromId ? toId : state.activeThreadTabId,\n })\n // What is typed stays in the composer it was typed in.\n if (fromId in state.drafts) setDrafts(move(state.drafts))\n },\n setConversationFacts: (conversationId, factIds) =>\n update({ conversationFacts: { ...state.conversationFacts, [conversationId]: factIds } }),\n setPinnedDocumentId: (pinnedDocumentId) => update({ pinnedDocumentId }),\n setCursor: (cursor) => {\n if (state.cursor !== cursor) update({ cursor })\n },\n setSuggestedQuery: (suggestedQuery) => update({ suggestedQuery }),\n addQueuedMessage: (id, message) =>\n update({ queuedMessages: queuedMessages.add(state.queuedMessages, id, message) }),\n acknowledgeQueuedMessage: (clientId, serverId) =>\n update({\n queuedMessages: queuedMessages.acknowledge(state.queuedMessages, clientId, serverId),\n }),\n removeQueuedMessage: (clientId) =>\n update({ queuedMessages: queuedMessages.remove(state.queuedMessages, clientId) }),\n removeQueuedMessageByServerId: (serverId) =>\n update({ queuedMessages: queuedMessages.removeByServerId(state.queuedMessages, serverId) }),\n consumeQueuedMessage: (id, content) =>\n update({ queuedMessages: queuedMessages.consume(state.queuedMessages, id, content) }),\n clearQueuedMessages: (id) =>\n update({ queuedMessages: queuedMessages.clear(state.queuedMessages, id) }),\n moveQueuedMessages: (from, to) =>\n update({ queuedMessages: queuedMessages.move(state.queuedMessages, from, to) }),\n setAgentControlState: (id, control) => update(agentControl.setState(state, id, control)),\n setAgentProbeAnswer: (id, probe) => update(agentControl.setProbeAnswer(state, id, probe)),\n setAgentProbePending: (id, pending) => update(agentControl.setProbePending(state, id, pending)),\n clearAgentControl: (id) => update(agentControl.clear(state, id)),\n setDraft: (text) => setDraftOf(conversationKey(state), text),\n setChatModel: (chatModel) => {\n if (state.chatModel !== chatModel) update({ chatModel })\n },\n openThreadTab: (conversationId) => {\n const id = conversationId ?? 'new'\n const others = state.threadTabs.filter((tab) => threadTabId(tab) !== id)\n const threadTabs = [...others, { conversationId }].slice(-MAX_THREAD_TABS)\n // Starting a new chat starts it unbound, whatever document is open.\n update({\n threadTabs,\n activeThreadTabId: id,\n ...(conversationId === null ? { newChatDocumentId: null } : {}),\n })\n if (state.conversationId !== conversationId)\n update({ conversationId, cursor: null, editingMessageId: null })\n return id\n },\n closeThreadTab: (tabId) => {\n const threadTabs = state.threadTabs.filter((tab) => threadTabId(tab) !== tabId)\n if (threadTabs.length === state.threadTabs.length) return\n if (state.activeThreadTabId !== tabId) return update({ threadTabs })\n const next = threadTabs.at(-1)\n update({ threadTabs, activeThreadTabId: next ? threadTabId(next) : null })\n if (next && state.conversationId !== next.conversationId)\n update({ conversationId: next.conversationId, cursor: null, editingMessageId: null })\n },\n selectThreadTab: (tabId) => {\n if (tabId === null) {\n if (state.activeThreadTabId !== null) update({ activeThreadTabId: null })\n return\n }\n const tab = state.threadTabs.find((t) => threadTabId(t) === tabId)\n if (!tab) return\n update({ activeThreadTabId: tabId })\n if (state.conversationId !== tab.conversationId)\n update({ conversationId: tab.conversationId, cursor: null, editingMessageId: null })\n },\n setChatModelName: (chatModelName) => {\n if (state.chatModelName !== chatModelName) update({ chatModelName })\n },\n setNewConversationAssistantMode: (newConversationAssistantMode) => {\n if (state.newConversationAssistantMode !== newConversationAssistantMode)\n update({ newConversationAssistantMode })\n },\n setNewAgentChat: (newAgentChat) => {\n const current = state.newAgentChat\n if (\n current?.agentId !== newAgentChat?.agentId ||\n current?.workspaceId !== newAgentChat?.workspaceId\n )\n update({ newAgentChat })\n },\n setNewChatDocumentId: (newChatDocumentId) => {\n if (state.newChatDocumentId !== newChatDocumentId) update({ newChatDocumentId })\n },\n startEditing: (messageId, content) => {\n preEdit = { draft: selectDraft(state), cursor: state.cursor }\n update({ editingMessageId: messageId })\n setDraftOf(conversationKey(state), content)\n },\n cancelEditing: () => {\n if (!state.editingMessageId) return\n update({ editingMessageId: null, cursor: preEdit.cursor })\n setDraftOf(conversationKey(state), preEdit.draft)\n preEdit = { draft: '', cursor: null }\n },\n completeEditing: () => {\n preEdit = { draft: '', cursor: null }\n if (state.editingMessageId) update({ editingMessageId: null })\n },\n setDeepLinkMessageId: (deepLinkMessageId) => {\n if (state.deepLinkMessageId !== deepLinkMessageId) update({ deepLinkMessageId })\n },\n setActiveCitationKey: (activeCitationKey) => {\n if (state.activeCitationKey !== activeCitationKey) update({ activeCitationKey })\n },\n setPendingTools: (pendingTools) => update({ pendingTools }),\n setAutoSendDraft: (autoSendDraft) => {\n if (state.autoSendDraft !== autoSendDraft) update({ autoSendDraft })\n },\n setAgentChatOwner: (conversationId, agentId) =>\n update({ agentChatOwners: { ...state.agentChatOwners, [conversationId]: agentId } }),\n setMessageTimer: (key, timer) =>\n update({ messageTimers: { ...state.messageTimers, [key]: timer } }),\n clearMessageTimer: (key) => {\n if (!(key in state.messageTimers)) return\n const messageTimers = { ...state.messageTimers }\n delete messageTimers[key]\n update({ messageTimers })\n },\n setConversationError: (conversationId, error, lastFailedMessage) => {\n const current = state.generating[conversationId]\n update({\n generating: {\n ...state.generating,\n [conversationId]: {\n ...current,\n isGenerating: false,\n error,\n startTime: current?.startTime ?? null,\n lastFailedMessage: lastFailedMessage ?? current?.lastFailedMessage ?? null,\n },\n },\n })\n },\n clearConversationError: (conversationId) => {\n const current = state.generating[conversationId]\n update({\n generating: {\n ...state.generating,\n [conversationId]: {\n ...(current ?? { isGenerating: false, startTime: null }),\n error: null,\n lastFailedMessage: null,\n },\n },\n })\n },\n abortConversationGeneration: (conversationId) => {\n const current = state.generating[conversationId]\n current?.abortController?.abort()\n update({\n generating: {\n ...state.generating,\n [conversationId]: {\n ...(current ?? { error: null, startTime: null }),\n isGenerating: false,\n abortController: null,\n },\n },\n })\n },\n startNewConversation: () =>\n update({\n conversationId: null,\n cursor: null,\n editingMessageId: null,\n newChatDocumentId: null,\n }),\n setPaMode: (paMode) => {\n if (state.paMode !== paMode) update({ paMode })\n },\n setConversationDocuments: (conversationId, documents, autoAdd = false) =>\n update({\n conversationDocuments: { ...state.conversationDocuments, [conversationId]: documents },\n conversationDocumentAutoAdd: {\n ...state.conversationDocumentAutoAdd,\n [conversationId]: autoAdd,\n },\n }),\n }\n}\n","/**\n * The composers' drafts kept across reloads: stored locally and encrypted, sealed to the signed-in\n * person's own key like the other data kept on the device, so nothing typed is readable at rest.\n *\n * Bound to the person: a record is kept under the user it belongs to and opened only while that\n * user is signed in (`owner`), never by whoever's key happens to be on the device, so a signed-out\n * page, a demo session or another account never sees it. Like the offline mail, the drafts never\n * outlive the session: a sign-out clears them (`clearSealedDrafts`).\n */\n\nimport { getUserEncryptionKeypair, sealedBoxDecrypt, sealedBoxEncrypt } from '@arbidocs/client'\n\n/** Where a session store keeps its drafts (see `createArbiSessionStore`). */\nexport interface ArbiDraftStorage {\n /** The saved drafts, or null while they cannot be opened yet (no one is signed in). */\n load(): Promise<Record<string, string> | null>\n /** Save the drafts (all of them: the record replaces what was saved). */\n save(drafts: Readonly<Record<string, string>>): void\n /** Who the drafts belong to now: the signed-in user, `null` signed out. */\n owner(): string | null\n /** Forget the saved drafts and any write still pending (the session ended). */\n clear(): void\n /** Be told when the drafts were cleared (the session store drops its copy). */\n onClear(listener: () => void): () => void\n}\n\n/** A key-value store the drafts are written to (`localStorage` by default). */\nexport interface DraftKeyValueStore {\n getItem(key: string): string | null\n setItem(key: string, value: string): void\n removeItem(key: string): void\n}\n\n/** How long typing settles before the drafts are written. */\nconst SAVE_DELAY_MS = 500\n\nconst encoder = new TextEncoder()\nconst decoder = new TextDecoder()\n\n/** What is stored: the drafts sealed to the owner's key, and who the owner is. */\ninterface StoredDrafts {\n owner: string\n sealed: string\n}\n\nfunction parseStored(raw: string | null): StoredDrafts | null {\n if (!raw) return null\n try {\n const parsed = JSON.parse(raw) as Partial<StoredDrafts> | null\n return parsed && typeof parsed.owner === 'string' && typeof parsed.sealed === 'string'\n ? { owner: parsed.owner, sealed: parsed.sealed }\n : null\n } catch {\n return null\n }\n}\n\n/** Every sealed draft storage made on this page, so a sign-out clears them all. */\nconst storages = new Set<ArbiDraftStorage>()\n\n/** The session ended (sign-out, or it could not be recovered): clear every saved draft. */\nexport function clearSealedDrafts(): void {\n for (const storage of [...storages]) storage.clear()\n}\n\nexport interface SealedDraftStorageOptions {\n /** The record's key in `storage`. */\n key?: string\n storage?: DraftKeyValueStore\n /**\n * The signed-in user (a stable id, e.g. the user's external id), `null` when no one is: the\n * drafts are opened and written only for them.\n */\n owner: () => string | null\n}\n\n/**\n * Drafts sealed to the signed-in person's key, in `storage` under `key`, for `owner` only. A record\n * of another user is removed unread; one that cannot be opened (damaged) reads as no drafts.\n */\nexport function createSealedDraftStorage({\n key = 'arbi-drafts',\n storage = typeof localStorage === 'undefined' ? undefined : localStorage,\n owner,\n}: SealedDraftStorageOptions): ArbiDraftStorage {\n let timer: ReturnType<typeof setTimeout> | undefined\n // Bumped by clear(): a write that started before it never lands after it.\n let generation = 0\n const listeners = new Set<() => void>()\n\n const remove = () => {\n try {\n storage?.removeItem(key)\n } catch {\n // Storage blocked: nothing was kept either.\n }\n }\n\n const write = async (drafts: Readonly<Record<string, string>>, written: number) => {\n if (!storage) return\n try {\n const user = owner()\n if (!user) return\n if (Object.keys(drafts).length === 0) {\n if (parseStored(storage.getItem(key))?.owner === user) storage.removeItem(key)\n return\n }\n const keypair = await getUserEncryptionKeypair()\n if (!keypair || written !== generation || owner() !== user) return\n // A plain Uint8Array of this realm, which is what the sealing accepts.\n const plain = Uint8Array.from(encoder.encode(JSON.stringify(drafts)))\n const record: StoredDrafts = {\n owner: user,\n sealed: sealedBoxEncrypt(plain, keypair.publicKey),\n }\n storage.setItem(key, JSON.stringify(record))\n } catch {\n // Storage full or blocked: the drafts stay in memory for this visit.\n }\n }\n\n const draftStorage: ArbiDraftStorage = {\n owner,\n load: async () => {\n const user = owner()\n if (!user) return null\n const keypair = await getUserEncryptionKeypair()\n if (!keypair || owner() !== user) return null\n try {\n const raw = storage?.getItem(key) ?? null\n if (!raw) return {}\n const stored = parseStored(raw)\n if (!stored || stored.owner !== user) {\n // Another user's (or an unreadable) record is not this person's to keep or open.\n remove()\n return {}\n }\n const plain = sealedBoxDecrypt(stored.sealed, keypair.secretKey)\n const drafts = JSON.parse(decoder.decode(plain)) as unknown\n if (!drafts || typeof drafts !== 'object') return {}\n return Object.fromEntries(\n Object.entries(drafts).filter((entry): entry is [string, string] => {\n return typeof entry[1] === 'string'\n })\n )\n } catch {\n return {}\n }\n },\n save: (drafts) => {\n clearTimeout(timer)\n const written = generation\n timer = setTimeout(() => void write(drafts, written), SAVE_DELAY_MS)\n },\n clear: () => {\n clearTimeout(timer)\n timer = undefined\n generation++\n remove()\n for (const listener of [...listeners]) listener()\n },\n onClear: (listener) => {\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n }\n storages.add(draftStorage)\n return draftStorage\n}\n","/**\n * The session state the blocks share (see `./store`). A host passes its own {@link ArbiSessionStore}\n * as the host configuration's `session` (ARBI-frontend backs it with its zustand store). Without\n * one, each top-level `<ArbiHost>` keeps an in-memory one, and blocks rendered with no host share a\n * module default, so a standalone block still coordinates with its siblings. A host's own store\n * keeps the composers' drafts across reloads, sealed to the person signed in on the host's `Arbi`\n * and only for them; the module default (no host, so no one signed in) keeps them in memory.\n */\n\nimport { useCallback, useSyncExternalStore } from 'react'\nimport { useArbiHost, type ArbiHostConfig } from '../host/config'\nimport { OWN_SESSION_SLOT } from '../host/merge'\nimport { createArbiSessionStore, type ArbiSessionState, type ArbiSessionStore } from './store'\nimport { createSealedDraftStorage } from './drafts'\n\n/** Who is signed in on the host's `Arbi` (its session), `null` when no one is. */\nfunction signedInUser(host: ArbiHostConfig): string | null {\n const state = host.arbi?.session?.getState()\n return state?.signedIn && state.userExtId ? state.userExtId : null\n}\n\n/** A host's own session: in memory, with its drafts kept sealed for the signed-in person. */\nconst createOwnStore = (host: ArbiHostConfig) =>\n createArbiSessionStore(\n {},\n { draftStorage: createSealedDraftStorage({ owner: () => signedInUser(host) }) }\n )\n\nlet moduleDefault: ArbiSessionStore | null = null\nconst defaultStore = () => (moduleDefault ??= createArbiSessionStore())\n\n/** The session store: its setters, and `getState()` for the state as of now (in callbacks). */\nexport function useArbiSessionStore(): ArbiSessionStore {\n const host = useArbiHost()\n if (host.session) return host.session\n const own = (host as Record<string, unknown>)[OWN_SESSION_SLOT] as\n { current: ArbiSessionStore | null } | undefined\n if (own) return (own.current ??= createOwnStore(host))\n return defaultStore()\n}\n\n/**\n * A slice of the session state; re-renders when it changes. The selector returns a value from the\n * state or a primitive (a new object each call would never settle).\n */\nexport function useArbiSessionState<T>(selector: (state: ArbiSessionState) => T): T {\n const store = useArbiSessionStore()\n const select = () => selector(store.getState())\n return useSyncExternalStore(store.subscribe, select, select)\n}\n\n/**\n * A view setting kept in the session and saved across reloads (`views.values`: a page's view\n * mode, a zoom, a filter box's text), and its setter. `fallback` while none is set.\n */\nexport function useSessionView<T>(key: string, fallback: T): [T, (value: T) => void] {\n const store = useArbiSessionStore()\n const value = useArbiSessionState((state) => state.views.values[key]) as T | undefined\n const set = useCallback((next: T) => store.setViewValue(key, next), [store, key])\n return [value === undefined ? fallback : value, set]\n}\n\n/**\n * View state kept for this session only (`views.transient`: a search's results, a one-shot\n * request), and its setter (`undefined` drops it). `fallback` while none is set.\n */\nexport function useTransientView<T>(key: string, fallback: T): [T, (value: T | undefined) => void] {\n const store = useArbiSessionStore()\n const value = useArbiSessionState((state) => state.views.transient[key]) as T | undefined\n const set = useCallback((next: T | undefined) => store.setTransientView(key, next), [store, key])\n return [value === undefined ? fallback : value, set]\n}\n\n/** A page's selected tab, kept across reloads; the host supplies its default tab. */\nexport function useSessionPageTab(\n page: string,\n fallback: string\n): {\n activeTab: string\n setActiveTab: (tab: string) => void\n} {\n const store = useArbiSessionStore()\n const activeTab = useArbiSessionState((state) => state.views.tabs[page]) || fallback\n const setActiveTab = useCallback((tab: string) => store.setPageTab(page, tab), [store, page])\n return { activeTab, setActiveTab }\n}\n","/**\n * Who is signed in: the host `Arbi`'s session (`arbi.session`, the client's session state), the\n * one source for the user, the sign-in status and the SSO mode. Re-renders when it changes.\n */\n\nimport { useMemo, useSyncExternalStore } from 'react'\nimport type { SessionManager, SessionState, SessionUser } from '@arbidocs/client'\nimport { useArbiHost } from '../host/config'\n\nexport type ArbiSessionStatus = 'signed-out' | 'signed-in'\n\nexport interface ArbiSignedInSession {\n /** `signed-in` once a login finished on this device (also before this tab has a token). */\n status: ArbiSessionStatus\n /** The signed-in user; `null` signed out. */\n user: SessionUser | null\n /** The account signs in through SSO. */\n isSso: boolean\n /** This tab holds a server session (a token). A new tab or an offline unlock does not, yet. */\n hasToken: boolean\n /** The server session key workspace keys are sealed to; `null` until known. */\n serverSessionKey: Uint8Array | null\n}\n\nconst SIGNED_OUT: ArbiSignedInSession = {\n status: 'signed-out',\n user: null,\n isSso: false,\n hasToken: false,\n serverSessionKey: null,\n}\n\nconst noSubscription = () => () => {}\n\n/** The signed-in session of the host's `Arbi`; signed out without one. */\nexport function useArbiSession(): ArbiSignedInSession {\n return useSignedInSession(useArbiHost().arbi?.session ?? null)\n}\n\n/** The same for a session the caller holds (the host building its `Arbi` on it). */\nexport function useSignedInSession(session: SessionManager | null): ArbiSignedInSession {\n const state = useSyncExternalStore<SessionState | null>(\n session ? session.subscribe : noSubscription,\n () => session?.getState() ?? null,\n () => session?.getState() ?? null\n )\n return useMemo(\n () =>\n state?.signedIn\n ? {\n status: 'signed-in',\n user: state.user,\n isSso: state.isSsoMode,\n hasToken: !!state.accessToken,\n serverSessionKey: state.serverSessionKey,\n }\n : { ...SIGNED_OUT, isSso: state?.isSsoMode ?? false },\n [state]\n )\n}\n","/**\n * Keeping the session's layout across reloads: a host gives the session store a\n * {@link ArbiSessionPersist} (where the saved layout is read and written), and the store reads it\n * once at start and writes it after each change. {@link createStoragePersist} makes one from any\n * key-value storage (IndexedDB, `localStorage`), writing at most once per quiet period and on page\n * exit, so a stream of changes (dragging a column) is one write and a reload never loses the last.\n */\n\n/** Where a session store keeps its saved layout. */\nexport interface ArbiSessionPersist<T = unknown> {\n /** The saved value, or null when none (or it cannot be read). Never rejects. */\n load(): Promise<T | null>\n /** Save the latest value (may be written later; the latest one wins). */\n save(value: T): void\n /** Forget the saved value (signing out). */\n clear?(): Promise<void>\n}\n\n/** A key-value storage, asynchronous or not (IndexedDB, `localStorage`). */\nexport interface ArbiKeyValueStorage {\n get(key: string): Promise<string | null> | string | null\n set(key: string, value: string): Promise<void> | void\n remove(key: string): Promise<void> | void\n}\n\nexport interface DebouncedWriterOptions {\n /** Performs the write. Errors are reported through `onError`, never thrown to the caller. */\n write: (key: string, value: string) => Promise<void> | void\n /** Trailing-edge quiet period. */\n delayMs: number\n /** Longest a pending value may wait from its first unwritten change. */\n maxWaitMs: number\n onError?: (key: string, error: unknown) => void\n}\n\nexport interface DebouncedWriter {\n /** Queue `value` as the latest value of `key`. */\n schedule: (key: string, value: string) => void\n /** The value queued for `key` but not yet written, if any. */\n pending: (key: string) => string | undefined\n /** Drop the queued value of `key` without writing it. */\n cancel: (key: string) => void\n /** Write every queued value now. */\n flushAll: () => void\n}\n\ninterface Pending {\n value: string\n timer: ReturnType<typeof setTimeout>\n /** When the first change not yet written was queued. */\n firstQueuedAt: number\n}\n\n/**\n * Per-key debounced writer. Rapid successive writes of one key collapse into a single\n * trailing-edge write `delayMs` after the last call; `maxWaitMs` caps how long a steady stream of\n * changes can postpone it.\n */\nexport function createDebouncedWriter({\n write,\n delayMs,\n maxWaitMs,\n onError,\n}: DebouncedWriterOptions): DebouncedWriter {\n const queue = new Map<string, Pending>()\n\n const run = (key: string, value: string) => {\n try {\n void Promise.resolve(write(key, value)).catch((error: unknown) => onError?.(key, error))\n } catch (error) {\n onError?.(key, error)\n }\n }\n\n const flush = (key: string) => {\n const entry = queue.get(key)\n if (!entry) return\n clearTimeout(entry.timer)\n queue.delete(key)\n run(key, entry.value)\n }\n\n return {\n schedule(key, value) {\n const now = Date.now()\n const existing = queue.get(key)\n if (existing) clearTimeout(existing.timer)\n const firstQueuedAt = existing?.firstQueuedAt ?? now\n const wait = Math.max(0, Math.min(delayMs, firstQueuedAt + maxWaitMs - now))\n queue.set(key, { value, firstQueuedAt, timer: setTimeout(() => flush(key), wait) })\n },\n pending: (key) => queue.get(key)?.value,\n cancel(key) {\n const entry = queue.get(key)\n if (!entry) return\n clearTimeout(entry.timer)\n queue.delete(key)\n },\n flushAll() {\n for (const key of Array.from(queue.keys())) flush(key)\n },\n }\n}\n\n/**\n * Flush `writer` whenever the page may be about to go away: `pagehide`, `visibilitychange` to\n * hidden (often the last event a mobile browser delivers) and `beforeunload`. Returns a function\n * that removes the listeners.\n */\nexport function flushOnPageExit(writer: Pick<DebouncedWriter, 'flushAll'>): () => void {\n if (typeof window === 'undefined' || typeof document === 'undefined') return () => {}\n const flush = () => writer.flushAll()\n const onVisibility = () => {\n if (document.visibilityState === 'hidden') writer.flushAll()\n }\n window.addEventListener('beforeunload', flush)\n window.addEventListener('pagehide', flush)\n document.addEventListener('visibilitychange', onVisibility)\n return () => {\n window.removeEventListener('beforeunload', flush)\n window.removeEventListener('pagehide', flush)\n document.removeEventListener('visibilitychange', onVisibility)\n }\n}\n\nexport interface StoragePersistOptions<T> {\n storage: ArbiKeyValueStorage\n /** The storage key. */\n key: string\n /** Read a value saved under `key` by an earlier build (default: as JSON). Never throws. */\n parse?: (saved: unknown) => T | null\n /**\n * Bring in what an earlier build saved elsewhere: called on every load with what is saved under\n * `key` (null: nothing yet), it returns the value to start from. A value other than the one given\n * is saved under `key` at once, so each piece is brought in once.\n */\n migrate?: (saved: T | null) => Promise<T | null>\n /** Quiet period before a write (default 250 ms), and the longest wait (default 1 s). */\n delayMs?: number\n maxWaitMs?: number\n}\n\n/** A {@link ArbiSessionPersist} on a key-value storage, debounced and flushed on page exit. */\nexport function createStoragePersist<T>({\n storage,\n key,\n parse = (saved) => saved as T,\n migrate,\n delayMs = 250,\n maxWaitMs = 1000,\n}: StoragePersistOptions<T>): ArbiSessionPersist<T> {\n const writer = createDebouncedWriter({\n write: (k, value) => storage.set(k, value),\n delayMs,\n maxWaitMs,\n onError: (k, error) => console.error(`[session] Failed to save ${k}:`, error),\n })\n flushOnPageExit(writer)\n const read = async (): Promise<T | null> => {\n // A queued write is the latest value.\n const pending = writer.pending(key)\n const raw = pending ?? (await storage.get(key))\n if (raw === null || raw === undefined) return null\n return parse(JSON.parse(raw))\n }\n return {\n async load() {\n try {\n const saved = await read()\n if (!migrate) return saved\n const migrated = await migrate(saved)\n if (migrated !== null && migrated !== saved)\n await storage.set(key, JSON.stringify(migrated))\n return migrated\n } catch (error) {\n console.warn('[session] The saved layout could not be read; starting from defaults', error)\n return null\n }\n },\n save: (value) => writer.schedule(key, JSON.stringify(value)),\n async clear() {\n writer.cancel(key)\n await storage.remove(key)\n },\n }\n}\n","/**\n * AI usage is reported in pounds (ex VAT).\n *\n * The usage endpoints (`/v1/user/projects/{id}/usage`, `/me/usage/today`) convert the metered\n * LiteLLM USD spend into £ at the API boundary (fractional, rounded to 2 decimals). The fields are\n * still named `spend` / `total_spend` in the schema, but they hold £, never dollars. Format them\n * with `formatGbp` (re-exported from `@arbidocs/sdk`).\n */\n\n/** The slice of a usage response that tells whether anything was recorded. */\nexport interface UsageTotals {\n total_spend: number\n total_tokens: number\n total_requests: number\n}\n\n/**\n * Was this usage actually metered? A `dev`-plan project with an all-zero response (no spend, no\n * tokens, no requests) is treated as \"not metered\", so the UI shows a note instead of silent\n * zeros. Any recorded tokens or requests mean usage was metered, even when the spend rounds to 0\n * (the backend records usage when billing is off, and a tiny spend can be £0.00).\n */\nexport function isUsageMetered(\n usage: UsageTotals,\n subscription: string | null | undefined\n): boolean {\n const empty = usage.total_spend === 0 && usage.total_tokens === 0 && usage.total_requests === 0\n return !(empty && subscription === 'dev')\n}\n","/**\n * React Query hooks that use the Arbi instance from context.\n */\n\nimport { useEffect, useMemo, useRef } from 'react'\nimport {\n useInfiniteQuery,\n useQuery,\n useQueries,\n useMutation,\n useQueryClient,\n} from '@tanstack/react-query'\nimport {\n ArbiApiError,\n type AskHandlers,\n type AskRequest,\n type SSEStreamResult,\n type TagListQuery,\n type ThreadsResponse,\n} from '@arbidocs/sdk/browser'\nimport { useArbi } from './useArbi'\nimport { useArbiSessionStore } from './session'\nimport type { ParsedDocument } from './documents/parsed-types'\nimport { isUsageMetered } from './usage-metered'\nimport { parseVersionRef } from './artifacts/versions'\n\n// ── Query keys ──────────────────────────────────────────────────────────────\n\n// The one key factory (every query and mutation key of the packages and the app): ./query-keys.\nexport { arbiQueryKeys, arbiMutationKeys } from './query-keys'\nimport { arbiQueryKeys } from './query-keys'\n\n// ── Hooks ───────────────────────────────────────────────────────────────────\n\n/** List the logged-in user's workspaces. */\nexport function useWorkspaces(options?: { enabled?: boolean }) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.workspaces(),\n queryFn: () => arbi.workspaces.list(),\n enabled: (options?.enabled ?? true) && arbi.isLoggedIn,\n })\n}\n\n/** Every version of the document `docId`, oldest first (`is_current` marks the current one). */\nexport function useDocumentVersionList(\n docId: string | null | undefined,\n options?: { enabled?: boolean }\n) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.documentVersions(docId ?? ''),\n queryFn: () => arbi.documents.versions(docId as string),\n enabled: (options?.enabled ?? true) && !!docId && arbi.hasWorkspace,\n })\n}\n\n/**\n * A workspace's conversations (threads and tasks). The list is kept current by its writers and the\n * workspace's events (`conversation-list`), so it is not re-read on every mount; `live` re-reads it\n * on a timer instead, faster while something is generating, for a view that follows runs by itself.\n */\nexport function useConversations(\n workspaceId: string | undefined,\n options?: { enabled?: boolean; live?: boolean }\n) {\n const arbi = useArbi()\n const live = options?.live === true\n return useQuery({\n queryKey: arbiQueryKeys.conversations(workspaceId ?? ''),\n queryFn: () => arbi.readInWorkspace(workspaceId as string, () => arbi.conversations.list()),\n enabled: (options?.enabled ?? true) && !!workspaceId && arbi.hasWorkspace,\n placeholderData: (previous) => previous,\n ...(live\n ? {\n refetchInterval: (query: { state: { data?: Array<{ status?: string | null }> } }) =>\n query.state.data?.some((conversation) => conversation.status === 'generating')\n ? 3000\n : 15000,\n }\n : { staleTime: Infinity, refetchOnMount: false, refetchOnReconnect: false }),\n })\n}\n\n/** The backend's built-in slash commands (`/compact`, `/goal`, …), for a slash menu. */\nexport function useBuiltinCommands() {\n const arbi = useArbi()\n const query = useQuery({\n queryKey: arbiQueryKeys.assistantCommands(),\n queryFn: () => arbi.assistant.commands(),\n staleTime: 30 * 1000,\n enabled: arbi.isLoggedIn,\n })\n // Stable identity so a menu's merge and filter memos do not rerun every render.\n const commands = useMemo(() => query.data ?? [], [query.data])\n return { commands, isLoading: query.isLoading }\n}\n\n/** One stored message with everything the server keeps on it (its trace and metadata). */\nexport function useMessageDetails(\n messageId: string | null | undefined,\n options?: { enabled?: boolean }\n) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.messageDetails(messageId ?? ''),\n queryFn: () => arbi.conversations.getMessage(messageId as string),\n enabled: (options?.enabled ?? true) && !!messageId && arbi.isLoggedIn,\n })\n}\n\n/**\n * A conversation's stored threads (each with its message history, citations data included). The\n * chat engine and the conversation's events keep the cache current, so it is re-read only when\n * stale (2 minutes) or when the page is shown again while this tab is not streaming the\n * conversation (a turn sent from another tab never reaches this one's socket). A conversation with\n * no messages yet (a new to-do, a workflow's task before its run) has no threads: the server's 404\n * is an empty conversation to write into. `live` re-reads it every few seconds.\n */\nexport function useConversationThreads(\n conversationId: string | undefined,\n options?: { enabled?: boolean; live?: boolean }\n) {\n const arbi = useArbi()\n const session = useArbiSessionStore()\n return useQuery({\n queryKey: arbiQueryKeys.conversationThreads(conversationId ?? ''),\n queryFn: async (): Promise<ThreadsResponse> => {\n try {\n return await arbi.conversations.getThreads(conversationId as string)\n } catch (error) {\n if (error instanceof ArbiApiError && error.status === 404) {\n return { conversation_ext_id: conversationId, threads: [] } as unknown as ThreadsResponse\n }\n throw error\n }\n },\n enabled: (options?.enabled ?? true) && !!conversationId && arbi.hasWorkspace,\n staleTime: 2 * 60 * 1000,\n refetchOnWindowFocus: () =>\n session.getState().generating[conversationId ?? '']?.isGenerating ? false : 'always',\n refetchInterval: options?.live ? 3000 : false,\n })\n}\n\n/** A tag list query as a stable cache key ('' for every tag). */\nconst tagListKey = (query: TagListQuery): string =>\n [\n query.kind ? `kind:${query.kind}` : '',\n query.parentId ? `parent:${query.parentId}` : '',\n query.ids?.length ? `ids:${query.ids.join(',')}` : '',\n query.include?.length ? `include:${query.include.join(',')}` : '',\n query.linksLimit !== undefined ? `links:${query.linksLimit}` : '',\n ]\n .filter(Boolean)\n .join('|')\n\n/**\n * List tags in a workspace (default: the open one) — all of them, or filtered: `{ kind: 'issue',\n * include: ['links'] }` is every issue with its documents, facts and threads (a table's rows; its\n * columns come from `useTagKindSchema`). `ids: []` asks for nothing.\n *\n * The whole list is read once and then kept current in place: the tag writes patch it\n * (`patchWorkspaceTags`), and an invalidation of the workspace's tags (a WebSocket event, a host\n * refresh) re-reads it. It is never re-read just for being mounted or the window being focused.\n */\nexport function useTags(\n workspaceId?: string | null,\n options?: TagListQuery & { enabled?: boolean }\n) {\n const arbi = useArbi()\n const { enabled, ...query } = options ?? {}\n const workspace = workspaceId ?? (arbi.hasWorkspace ? arbi.getWorkspaceId() : '')\n const key = tagListKey(query)\n return useQuery({\n queryKey: key ? arbiQueryKeys.tagList(workspace, key) : arbiQueryKeys.tags(workspace),\n queryFn: () => arbi.readInWorkspace(workspace, () => arbi.tags.list(key ? query : undefined)),\n enabled:\n (enabled ?? true) &&\n !!workspace &&\n arbi.hasWorkspace &&\n (query.ids === undefined || query.ids.length > 0),\n ...(key ? {} : { staleTime: Infinity }),\n })\n}\n\n/**\n * Batch-fetch first-page thumbnails for a set of documents. Returns a map of\n * doc external id → `data:image/webp` URI (or `null` when no thumbnail exists).\n * Cached for a few minutes since thumbnails are effectively immutable per doc.\n */\nexport function useThumbnails(docIds: string[], options?: { enabled?: boolean }) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.thumbnails(docIds),\n queryFn: () => arbi.documents.getThumbnails(docIds),\n enabled: (options?.enabled ?? true) && docIds.length > 0 && arbi.hasWorkspace,\n staleTime: 5 * 60_000,\n })\n}\n\n/**\n * Fetch a document's parsed content (chunks grouped by page) for the review\n * viewer. `stage` defaults to `final` (fully processed); `marker`/`subchunk`\n * expose earlier pipeline stages. `docId` may be a version reference (`doc-…@v2`).\n */\nexport function useParsedDocument(\n docId: string | undefined,\n stage: string = 'final',\n options?: { enabled?: boolean }\n) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.parsedDoc(docId ?? '', stage),\n queryFn: () => {\n // A version reference (`doc-…@v2`) reads that version's parse.\n const { docId: id, version } = parseVersionRef(docId as string)\n return arbi.documents.getParsedContent(\n id,\n stage,\n version ?? undefined\n ) as unknown as Promise<ParsedDocument>\n },\n enabled: (options?.enabled ?? true) && !!docId && arbi.hasWorkspace,\n })\n}\n\n/**\n * Ask the assistant (`arbi.assistant.ask`) as a mutation: one streaming turn, its frames to\n * `handlers`, resolving with the accumulated result.\n */\nexport function useAssistantQuery() {\n const arbi = useArbi()\n return useMutation<SSEStreamResult, Error, { request: AskRequest; handlers?: AskHandlers }>({\n mutationFn: ({ request, handlers }) => arbi.assistant.ask(request, handlers),\n })\n}\n\n/** List agents owned by the current user. */\nexport function useAgents(options?: { enabled?: boolean }) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.agents(),\n queryFn: () => arbi.agents.list(),\n enabled: (options?.enabled ?? true) && arbi.isLoggedIn,\n })\n}\n\n/**\n * Delete agents. Returns a mutation. Refreshes the agent list, the workflow list and the conversation list\n * (a deleted agent's workflows and work go with it), and drops the deleted agents' own config and workspace queries.\n */\nexport function useDeleteAgents() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation<unknown, Error, { agentExtIds: string[] }>({\n mutationFn: ({ agentExtIds }) => arbi.agents.delete(agentExtIds),\n onSuccess: (_result, { agentExtIds }) => {\n for (const id of agentExtIds) {\n qc.removeQueries({ queryKey: arbiQueryKeys.agentConfig(id) })\n qc.removeQueries({ queryKey: arbiQueryKeys.agentWorkspaces(id) })\n }\n return Promise.all([\n qc.invalidateQueries({ queryKey: arbiQueryKeys.agents() }),\n qc.invalidateQueries({ queryKey: arbiQueryKeys.workflows() }),\n qc.invalidateQueries({ queryKey: arbiQueryKeys.allConversations() }),\n qc.invalidateQueries({ queryKey: arbiQueryKeys.configs() }),\n ])\n },\n })\n}\n\n/** Authorize a delegated session (generates claim code). Returns a mutation. */\n\n/** Check backend health. */\nexport function useHealth(options?: { enabled?: boolean }) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.health(),\n queryFn: () => arbi.health.check(),\n enabled: options?.enabled,\n })\n}\n\n/**\n * The deployment's models with their tags (`Standard`, `Premium`), providers and per-token costs,\n * and the default premium model. Static per deployment: read once.\n */\nexport function useAvailableModels(options?: { enabled?: boolean }) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.availableModels(),\n queryFn: () => arbi.health.models(),\n staleTime: Infinity,\n enabled: (options?.enabled ?? true) && arbi.isLoggedIn,\n })\n}\n\n// ── Behaviour-template configs ───────────────────────────────────────────────\n\n/** List the caller's saved agent configurations (behaviour templates). */\nexport function useConfigs(options?: { enabled?: boolean }) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.configVersions(),\n queryFn: () => arbi.agentConfig.list(),\n enabled: options?.enabled ?? arbi.isLoggedIn,\n })\n}\n\n/** One saved agent configuration (its models, its tools). Configs change only on a save. */\nexport function useConfig(configId: string | null | undefined, options?: { enabled?: boolean }) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.config(configId ?? ''),\n queryFn: () => arbi.agentConfig.get(configId as string),\n staleTime: 10 * 60 * 1000,\n enabled: (options?.enabled ?? true) && !!configId && arbi.isLoggedIn,\n })\n}\n\n// ── Activity feed ─────────────────────────────────────────────────────────────\n\n/**\n * List the caller's durable activity feed, newest first.\n *\n * Activity entries are backend-originated, to-self log lines that are always\n * read — they are deliberately kept out of the normal notifications/DM feed and\n * never affect the unread badge, so this is a separate, opt-in query.\n */\nexport function useActivity(options?: { enabled?: boolean; limit?: number; offset?: number }) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.activity(),\n queryFn: () => arbi.dm.listActivity({ limit: options?.limit, offset: options?.offset }),\n enabled: options?.enabled ?? arbi.isLoggedIn,\n })\n}\n\n/**\n * A workspace's activity feed, newest first, a page at a time: thread history, people posting,\n * uploads, new versions and signatures, workflow runs. Only what the caller can see. The pages\n * are `data.pages`; `fetchNextPage` reads the next one while `hasNextPage`.\n */\nexport function useWorkspaceActivity(\n workspaceId: string | null | undefined,\n options?: {\n enabled?: boolean\n limit?: number\n /** Runs before each page, e.g. to (re)open the workspace so titles and names decrypt. */\n beforeFetch?: () => Promise<unknown>\n }\n) {\n const arbi = useArbi()\n return useInfiniteQuery({\n queryKey: arbiQueryKeys.workspaceActivity(workspaceId ?? ''),\n queryFn: async ({ pageParam }) => {\n await options?.beforeFetch?.()\n return arbi.workspaces.activity(workspaceId as string, {\n cursor: pageParam,\n limit: options?.limit,\n })\n },\n initialPageParam: null as string | null,\n getNextPageParam: (page) => page.next_cursor ?? undefined,\n enabled: (options?.enabled ?? true) && !!workspaceId && arbi.isLoggedIn,\n })\n}\n\n// ── Projects, usage & spend ───────────────────────────────────────────────────\n\n/** List the logged-in user's projects (billing accounts). */\nexport function useProjects(options?: { enabled?: boolean }) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.projects(),\n queryFn: () => arbi.projects.list(),\n enabled: options?.enabled ?? arbi.isLoggedIn,\n })\n}\n\n/**\n * AI usage breakdown for a project's billing period. `monthsBack` selects the period (0 =\n * current, 1 = previous month, …).\n *\n * The response's `total_spend` / `spend` fields are £ of AI usage (format with `formatGbp`).\n * `metered` is `false` when the deployment does not record usage (a `dev`-plan project with all\n * zeros): show \"usage is not metered here\" instead of zeros. It is `undefined` until the usage\n * has loaded.\n */\nexport function useProjectUsage(\n projectExtId: string | undefined,\n monthsBack: number = 0,\n options?: { enabled?: boolean }\n) {\n const arbi = useArbi()\n const usage = useQuery({\n queryKey: arbiQueryKeys.projectUsage(projectExtId ?? '', monthsBack),\n queryFn: () => arbi.projects.usage(projectExtId as string, monthsBack),\n enabled: (options?.enabled ?? true) && !!projectExtId && arbi.isLoggedIn,\n })\n const projects = useProjects({ enabled: !!projectExtId && (options?.enabled ?? true) })\n const subscription = projects.data?.find((p) => p.external_id === projectExtId)?.subscription\n const metered = usage.data ? isUsageMetered(usage.data, subscription) : undefined\n return { ...usage, metered }\n}\n\n/** One day of aggregated usage across projects (for a spend/token trend). */\nexport interface AggregatedDailyUsage {\n date: string\n /** £ of AI usage that day. */\n gbp: number\n totalTokens: number\n apiRequests: number\n}\n\n/** One model group's aggregated usage across projects (for a breakdown). */\nexport interface AggregatedModelGroupUsage {\n model: string\n /** £ of AI usage by this model group. */\n gbp: number\n totalTokens: number\n promptTokens: number\n completionTokens: number\n successfulRequests: number\n}\n\n/** Aggregated AI usage + spend across several projects. */\nexport interface ProjectsUsageAggregate {\n /** Summed usage across the projects, in £ (ex VAT). */\n totalGbp: number\n /** Summed token count across the projects. */\n totalTokens: number\n /** Summed API request count across the projects. */\n totalRequests: number\n /** Per-day totals merged across every project, oldest first. */\n daily: AggregatedDailyUsage[]\n /** Per-model-group totals merged across every project, most £ first. */\n modelGroups: AggregatedModelGroupUsage[]\n /**\n * False when none of the loaded projects records usage (billing is off on this deployment), so\n * zeros mean \"not metered\". True while anything real was recorded, or before data arrived.\n */\n metered: boolean\n /** True while any per-project query is still loading. */\n isLoading: boolean\n /** True if any per-project query errored. */\n isError: boolean\n}\n\n/**\n * Firm-wide AI usage + spend: aggregates {@link useProjectUsage} across several\n * projects (e.g. all of a firm's matters) in parallel and merges the real totals,\n * the daily trend, and the per-model breakdown. Shares the per-project query\n * cache, so it costs nothing extra where a project's usage is already loaded.\n * Numbers are genuine — zero projects (or zero billed work) yields zero totals;\n * callers render that honestly.\n */\nexport function useProjectsUsage(\n projectExtIds: string[],\n monthsBack: number = 0,\n options?: { enabled?: boolean }\n): ProjectsUsageAggregate {\n const arbi = useArbi()\n const enabled = (options?.enabled ?? true) && arbi.isLoggedIn\n const projects = useProjects({ enabled: enabled && projectExtIds.length > 0 })\n const results = useQueries({\n queries: projectExtIds.map((id) => ({\n queryKey: arbiQueryKeys.projectUsage(id, monthsBack),\n queryFn: () => arbi.projects.usage(id, monthsBack),\n enabled: enabled && !!id,\n })),\n })\n\n // Recompute only when a query's data actually changes (not on every parent\n // render — the dashboard re-renders often while a digest streams).\n const signature =\n results.map((r) => `${r.status}:${r.dataUpdatedAt ?? 0}`).join('|') +\n `#${projects.dataUpdatedAt}`\n\n return useMemo(() => {\n const dailyMap = new Map<string, AggregatedDailyUsage>()\n const modelMap = new Map<string, AggregatedModelGroupUsage>()\n let totalGbp = 0\n let anyData = false\n let anyMetered = false\n let totalTokens = 0\n let totalRequests = 0\n\n results.forEach((r, i) => {\n const d = r.data\n if (!d) return\n anyData = true\n const subscription = projects.data?.find(\n (p) => p.external_id === projectExtIds[i]\n )?.subscription\n if (isUsageMetered(d, subscription)) anyMetered = true\n totalGbp += d.total_spend ?? 0\n totalTokens += d.total_tokens ?? 0\n totalRequests += d.total_requests ?? 0\n\n for (const day of d.daily ?? []) {\n const cur = dailyMap.get(day.date) ?? {\n date: day.date,\n gbp: 0,\n totalTokens: 0,\n apiRequests: 0,\n }\n cur.gbp += day.spend ?? 0\n cur.totalTokens += day.total_tokens ?? 0\n cur.apiRequests += day.api_requests ?? 0\n dailyMap.set(day.date, cur)\n }\n\n for (const [model, mg] of Object.entries(d.model_groups ?? {})) {\n const cur = modelMap.get(model) ?? {\n model,\n gbp: 0,\n totalTokens: 0,\n promptTokens: 0,\n completionTokens: 0,\n successfulRequests: 0,\n }\n cur.gbp += mg.spend ?? 0\n cur.totalTokens += mg.total_tokens ?? 0\n cur.promptTokens += mg.prompt_tokens ?? 0\n cur.completionTokens += mg.completion_tokens ?? 0\n cur.successfulRequests += mg.successful_requests ?? 0\n modelMap.set(model, cur)\n }\n })\n\n return {\n totalGbp,\n totalTokens,\n totalRequests,\n daily: [...dailyMap.values()].sort((a, b) => a.date.localeCompare(b.date)),\n modelGroups: [...modelMap.values()].sort(\n (a, b) => b.gbp - a.gbp || b.totalTokens - a.totalTokens\n ),\n metered: !anyData || anyMetered,\n isLoading: results.some((r) => r.isLoading),\n isError: results.some((r) => r.isError),\n }\n }, [signature])\n}\n\n/** List the Stripe invoices for a project's subscription. */\nexport function useProjectInvoices(\n projectExtId: string | undefined,\n options?: { enabled?: boolean }\n) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.projectInvoices(projectExtId ?? ''),\n queryFn: () => arbi.projects.invoices(projectExtId as string),\n enabled: (options?.enabled ?? true) && !!projectExtId && arbi.isLoggedIn,\n })\n}\n\n/**\n * The signed-in user from `GET /v1/user/me`. Refetched on window focus, so a role granted or\n * removed elsewhere shows up without a reload; invalidate `arbiQueryKeys.currentUser()` after a\n * change you made yourself.\n */\nexport function useCurrentUser(options?: { enabled?: boolean }) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.currentUser(),\n queryFn: () => arbi.user.me(),\n enabled: options?.enabled ?? arbi.isLoggedIn,\n refetchOnWindowFocus: true,\n staleTime: 30_000,\n })\n}\n\n/**\n * The firm's pooled monthly £ of AI usage (Box deployments). A 403 (the caller is not a firm member\n * or Box admin) is not retried: treat an error like `has_pool: false` and show nothing.\n */\nexport function useFirmPool(options?: { enabled?: boolean }) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.firmPool(),\n queryFn: () => arbi.firm.pool(),\n enabled: (options?.enabled ?? true) && arbi.isLoggedIn,\n retry: false,\n refetchOnWindowFocus: true,\n staleTime: 60_000,\n })\n}\n\n/**\n * Whether this deployment runs under a Box licence (`isBox`) and whether the user administers it in\n * the ARBI portal (`isBoxAdmin`), from the firm pool. Anyone outside the firm gets a 403 (not\n * retried), read as no Box. The API has no Box-admin flag yet: `can_top_up` is true only for a Box\n * admin of a licence central can bill, so admins of a hand-set licence read as members for now.\n */\nexport function useBoxRole(options: { enabled?: boolean } = {}): {\n isBox: boolean\n isBoxAdmin: boolean\n} {\n const { data, isError } = useFirmPool(options)\n const isBox = !isError && !!data?.has_pool\n return { isBox, isBoxAdmin: isBox && !!data?.can_top_up }\n}\n\n/** Buy add-ons for the firm (Box admins). Refreshes the pool; the result may carry an invoice URL. */\nexport function useTopUpFirmPool() {\n const arbi = useArbi()\n const queryClient = useQueryClient()\n return useMutation({\n mutationFn: (aiAddons: number) => arbi.firm.topUp(aiAddons),\n onSuccess: (result) => {\n queryClient.setQueryData(arbiQueryKeys.firmPool(), result.pool)\n },\n })\n}\n\n/** Why \"New project\" / \"New workspace\" is unavailable to someone who may not create them. */\nexport const PROJECT_CREATION_DENIED_REASON =\n 'Only members of your firm can create projects and workspaces.'\n\n/**\n * Whether the signed-in user may create projects and workspaces. `undefined` while the user is\n * loading: callers should neither offer nor refuse creation until it is known.\n */\nexport function useCanCreateProjects(): boolean | undefined {\n const user = useCurrentUser()\n // A role granted or removed in a workspace can change it: re-read when the memberships do.\n const { data: workspaces } = useWorkspaces({ enabled: user.isSuccess })\n const membership = workspaces?.map((w) => w.external_id).join(',')\n const { refetch } = user\n const seen = useRef<string | undefined>(undefined)\n useEffect(() => {\n if (membership === undefined || membership === seen.current) return\n const first = seen.current === undefined\n seen.current = membership\n if (!first) void refetch()\n }, [membership, refetch])\n return user.data?.can_create_projects\n}\n\n/**\n * Today's deployment-wide AI usage (£, `used_gbp`) for the signed-in user: pair it with a project's\n * `daily_cap_per_user` for a \"£ used today\" indicator. Re-read on mount and window focus, and when\n * the host invalidates it after the user's own generation; never polled.\n */\nexport function useUserUsageToday(options?: { enabled?: boolean }) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.userUsageToday(),\n queryFn: () => arbi.user.usageToday(),\n enabled: (options?.enabled ?? true) && arbi.isLoggedIn,\n refetchOnWindowFocus: true,\n refetchOnMount: 'always',\n staleTime: 15_000,\n })\n}\n"]}
|