@trustgraph/react-state 1.5.1 → 1.5.3

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/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { SocketProvider, SocketContext, ConnectionStateContext, } from "@trustgraph/react-provider";
2
2
  export type { SocketProviderProps } from "@trustgraph/react-provider";
3
- export type { BaseApi, Triple, Term, IriTerm, BlankTerm, LiteralTerm, TripleTerm, ConnectionState, StreamingMetadata, RowEmbeddingsMatch, } from "@trustgraph/client";
3
+ export type { BaseApi, Triple, Term, IriTerm, BlankTerm, LiteralTerm, TripleTerm, ConnectionState, StreamingMetadata, RowEmbeddingsMatch, ChunkedUploadDocumentMetadata, UploadSession, } from "@trustgraph/client";
4
4
  export { NotificationProvider } from "./NotificationProvider";
5
5
  export type { NotificationProviderProps } from "./NotificationProvider";
6
6
  export type { NotificationHandler } from "./types";
@@ -49,6 +49,11 @@ export { useLLMModels } from "./state/llm-models";
49
49
  export { useFlowBlueprints, generateFlowBlueprintId } from "./state/flow-blueprints";
50
50
  export { useFlowParameters, useParameterValidation, } from "./state/flow-parameters";
51
51
  export { useNodeDetails } from "./state/node-details";
52
+ export { useChunkedUpload } from "./state/chunked-upload";
53
+ export type { UploadStatus, UploadProgress, ChunkedUploadOptions, ChunkedUploadParams, ResumeUploadParams, } from "./state/chunked-upload";
54
+ export { useChunkedDownload } from "./state/chunked-download";
55
+ export type { DownloadStatus, DownloadProgress, ChunkedDownloadOptions, DownloadParams, } from "./state/chunked-download";
56
+ export type { StreamDocumentResponse } from "@trustgraph/client";
52
57
  export type { Entity } from "./model/entity";
53
58
  export type { Message } from "./model/message";
54
59
  export type { Settings } from "./model/settings-types";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.esm.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { useSocket, useConnectionState } from '@trustgraph/react-provider';
2
2
  export { ConnectionStateContext, SocketContext, SocketProvider } from '@trustgraph/react-provider';
3
3
  import { jsx } from 'react/jsx-runtime';
4
- import { createContext, useContext, useEffect, useState, useMemo } from 'react';
4
+ import { createContext, useContext, useEffect, useState, useMemo, useRef, useCallback } from 'react';
5
5
  import { create } from 'zustand';
6
6
  import { useQueryClient, useQuery, useMutation } from '@tanstack/react-query';
7
7
  import { v4 } from 'uuid';
@@ -1399,9 +1399,9 @@ const useGraphSubgraph = ({ entityUri, flow, collection, }) => {
1399
1399
 
1400
1400
  /**
1401
1401
  * Custom hook for querying graph embeddings
1402
- * Finds graph entities similar to the provided embedding vectors
1402
+ * Finds graph entities similar to the provided embedding vector
1403
1403
  */
1404
- const useGraphEmbeddings = ({ flow, vecs, limit = 10, collection }) => {
1404
+ const useGraphEmbeddings = ({ flow, vec, limit = 10, collection }) => {
1405
1405
  const socket = useSocket();
1406
1406
  const notify = useNotification();
1407
1407
  const { settings } = useSettings();
@@ -1409,12 +1409,12 @@ const useGraphEmbeddings = ({ flow, vecs, limit = 10, collection }) => {
1409
1409
  const effectiveFlow = flow ?? sessionFlowId;
1410
1410
  const effectiveCollection = collection ?? settings.collection;
1411
1411
  const query = useQuery({
1412
- queryKey: ["graph-embeddings", { flow: effectiveFlow, vecs, limit, collection: effectiveCollection }],
1413
- enabled: !!vecs && vecs.length > 0 && !!effectiveFlow,
1412
+ queryKey: ["graph-embeddings", { flow: effectiveFlow, vec, limit, collection: effectiveCollection }],
1413
+ enabled: !!vec && vec.length > 0 && !!effectiveFlow,
1414
1414
  queryFn: () => {
1415
1415
  return socket
1416
1416
  .flow(effectiveFlow)
1417
- .graphEmbeddingsQuery(vecs, limit, effectiveCollection)
1417
+ .graphEmbeddingsQuery(vec, limit, effectiveCollection)
1418
1418
  .catch((err) => {
1419
1419
  const message = err instanceof Error ? err.message : String(err);
1420
1420
  notify.error(message);
@@ -1432,24 +1432,23 @@ const useGraphEmbeddings = ({ flow, vecs, limit = 10, collection }) => {
1432
1432
  };
1433
1433
  };
1434
1434
 
1435
- // Take the embeddings, and lookup entities using graph
1435
+ // Take the embedding vector, and lookup entities using graph
1436
1436
  // embeddings, add embedding to each entity row, just an easy
1437
1437
  // place to put it
1438
1438
  const getGraphEmbeddings = (socket, add, remove, limit, collection) => {
1439
- // Take the embeddings, and lookup entities using graph
1440
- // embeddings, add embedding to each entity row, just an easy
1441
- // place to put it
1442
- return (vecs) => {
1439
+ // Take the embedding, and lookup entities using graph
1440
+ // embeddings, add embedding to each entity row
1441
+ return (vec) => {
1443
1442
  const act = "Graph embedding search";
1444
1443
  add(act);
1445
1444
  return socket
1446
- .graphEmbeddingsQuery(vecs, limit , collection)
1447
- .then((ents) => {
1445
+ .graphEmbeddingsQuery(vec, limit , collection)
1446
+ .then((matches) => {
1448
1447
  remove(act);
1449
- return ents
1450
- .filter((ent) => ent.t === "i")
1451
- .map((ent) => {
1452
- return { uri: ent.i, target: vecs[0] };
1448
+ return matches
1449
+ .filter((m) => m.entity !== null && m.entity.t === "i")
1450
+ .map((m) => {
1451
+ return { uri: m.entity.i, target: vec };
1453
1452
  });
1454
1453
  })
1455
1454
  .catch((err) => {
@@ -1532,11 +1531,11 @@ const addRowEmbeddings = (socket, add, remove) => (entities) => {
1532
1531
  return socket
1533
1532
  .embeddings([text])
1534
1533
  .then((x) => {
1535
- if (x && x.length > 0 && x[0].length > 0) {
1534
+ if (x && x.length > 0) {
1536
1535
  remove(act);
1537
1536
  return {
1538
1537
  ...ent,
1539
- embeddings: x[0][0],
1538
+ embeddings: x[0],
1540
1539
  };
1541
1540
  }
1542
1541
  else {
@@ -1896,7 +1895,10 @@ const useChatSession = ({ flow } = {}) => {
1896
1895
  // Start embeddings activity
1897
1896
  addActivity(embActivity);
1898
1897
  // Get labels for each entity
1899
- const labelPromises = result.entities.map(async (entity) => {
1898
+ const labelPromises = result.entities
1899
+ .filter((match) => match.entity !== null)
1900
+ .map(async (match) => {
1901
+ const entity = match.entity;
1900
1902
  const labelActivity = "Label " + getTermValue$2(entity);
1901
1903
  addActivity(labelActivity);
1902
1904
  try {
@@ -4639,5 +4641,551 @@ const useNodeDetails = (nodeId, flowId) => {
4639
4641
  };
4640
4642
  };
4641
4643
 
4642
- export { DEFAULT_SETTINGS, NotificationProvider, RDFS_LABEL, SETTINGS_STORAGE_KEY, createDocId, fileToBase64, generateFlowBlueprintId, getTermValue$2 as getTermValue, getTriples, prepareMetadata, textToBase64, useActivity, useAgentTools, useChat, useChatSession, useCollections, useConversation, useDocumentEmbeddingsQuery, useEmbeddings, useEntityDetail, useFlowBlueprints, useFlowParameters, useFlows, useGraphEmbeddings, useGraphSubgraph, useInference, useKnowledgeCores, useLLMModels, useLibrary, useLoadStateStore, useMcpTools, useNlpQuery, useNodeDetails, useNotification, useOntologies, useParameterValidation, useProcessing, useProgressStateStore, usePrompts, useRowEmbeddingsQuery, useRowsQuery, useSchemas, useSearchStateStore, useSessionStore, useSettings, useStructuredQuery, useTokenCosts, useTriples, useVectorSearch, useWorkbenchStateStore, vectorSearch };
4644
+ // Default chunk size: 5MB (matches backend default)
4645
+ const DEFAULT_CHUNK_SIZE$1 = 5 * 1024 * 1024;
4646
+ // Maximum parallel chunk uploads
4647
+ const DEFAULT_PARALLEL_UPLOADS = 3;
4648
+ /**
4649
+ * Hook for managing chunked document uploads with progress tracking
4650
+ *
4651
+ * Features:
4652
+ * - Automatic chunking of large files
4653
+ * - Parallel chunk uploads for performance
4654
+ * - Progress tracking (bytes, percentage, chunks)
4655
+ * - Pause/resume support
4656
+ * - Cancel support
4657
+ * - Resumability after interruption
4658
+ *
4659
+ * @param options - Configuration options for the upload
4660
+ * @returns Upload state and control methods
4661
+ */
4662
+ const useChunkedUpload = (options = {}) => {
4663
+ const { chunkSize = DEFAULT_CHUNK_SIZE$1, parallelUploads = DEFAULT_PARALLEL_UPLOADS, onProgress, onComplete, onError, } = options;
4664
+ const socket = useSocket();
4665
+ const connectionState = useConnectionState();
4666
+ const queryClient = useQueryClient();
4667
+ const notify = useNotification();
4668
+ // Upload state
4669
+ const [progress, setProgress] = useState({
4670
+ totalBytes: 0,
4671
+ bytesUploaded: 0,
4672
+ percentage: 0,
4673
+ totalChunks: 0,
4674
+ chunksUploaded: 0,
4675
+ pendingChunks: [],
4676
+ status: "idle",
4677
+ });
4678
+ // Refs for managing upload lifecycle
4679
+ const abortControllerRef = useRef(null);
4680
+ const isPausedRef = useRef(false);
4681
+ const currentFileRef = useRef(null);
4682
+ const uploadIdRef = useRef(null);
4683
+ // Update progress and notify callback
4684
+ const updateProgress = useCallback((updates) => {
4685
+ setProgress((prev) => {
4686
+ const next = { ...prev, ...updates };
4687
+ onProgress?.(next);
4688
+ return next;
4689
+ });
4690
+ }, [onProgress]);
4691
+ // Read a chunk from the file as base64
4692
+ const readChunkAsBase64 = useCallback(async (file, chunkIndex, chunkSz) => {
4693
+ const start = chunkIndex * chunkSz;
4694
+ const end = Math.min(start + chunkSz, file.size);
4695
+ const blob = file.slice(start, end);
4696
+ return new Promise((resolve, reject) => {
4697
+ const reader = new FileReader();
4698
+ reader.onloadend = () => {
4699
+ const dataUrl = reader.result;
4700
+ // Extract base64 from data URL
4701
+ const base64 = dataUrl.replace(/^data:[^;]+;base64,/, "");
4702
+ resolve(base64);
4703
+ };
4704
+ reader.onerror = () => reject(new Error("Failed to read file chunk"));
4705
+ reader.readAsDataURL(blob);
4706
+ });
4707
+ }, []);
4708
+ // Upload chunks in parallel with concurrency limit
4709
+ const uploadChunks = useCallback(async (file, uploadId, pendingChunks, chunkSz, totalChunks) => {
4710
+ const remaining = [...pendingChunks];
4711
+ let completedCount = totalChunks - remaining.length;
4712
+ let bytesUploaded = completedCount * chunkSz;
4713
+ // Process chunks with limited parallelism
4714
+ const uploadNextBatch = async () => {
4715
+ while (remaining.length > 0 && !abortControllerRef.current?.signal.aborted) {
4716
+ // Wait if paused
4717
+ if (isPausedRef.current) {
4718
+ await new Promise((resolve) => setTimeout(resolve, 100));
4719
+ continue;
4720
+ }
4721
+ // Take up to parallelUploads chunks
4722
+ const batch = remaining.splice(0, parallelUploads);
4723
+ // Upload batch in parallel
4724
+ const results = await Promise.allSettled(batch.map(async (chunkIndex) => {
4725
+ const content = await readChunkAsBase64(file, chunkIndex, chunkSz);
4726
+ await socket.librarian().uploadChunk(uploadId, chunkIndex, content);
4727
+ return chunkIndex;
4728
+ }));
4729
+ // Process results
4730
+ for (const result of results) {
4731
+ if (result.status === "fulfilled") {
4732
+ completedCount++;
4733
+ // Calculate actual bytes for this chunk
4734
+ const chunkIdx = result.value;
4735
+ const chunkStart = chunkIdx * chunkSz;
4736
+ const chunkEnd = Math.min(chunkStart + chunkSz, file.size);
4737
+ bytesUploaded += chunkEnd - chunkStart;
4738
+ updateProgress({
4739
+ chunksUploaded: completedCount,
4740
+ bytesUploaded,
4741
+ percentage: Math.round((bytesUploaded / file.size) * 100),
4742
+ pendingChunks: [...remaining],
4743
+ });
4744
+ }
4745
+ else {
4746
+ // Re-add failed chunk to retry
4747
+ const failedIndex = batch[results.indexOf(result)];
4748
+ remaining.push(failedIndex);
4749
+ console.warn(`Chunk ${failedIndex} failed, will retry:`, result.reason);
4750
+ }
4751
+ }
4752
+ }
4753
+ };
4754
+ await uploadNextBatch();
4755
+ }, [socket, parallelUploads, readChunkAsBase64, updateProgress]);
4756
+ /**
4757
+ * Start a new chunked upload
4758
+ */
4759
+ const upload = useCallback(async (params) => {
4760
+ const { file, title, comments = "", tags = [], collection, documentId } = params;
4761
+ // Validate connection
4762
+ if (connectionState?.status !== "authenticated" &&
4763
+ connectionState?.status !== "unauthenticated") {
4764
+ const error = "Not connected to server";
4765
+ updateProgress({ status: "error", error });
4766
+ onError?.(error);
4767
+ return null;
4768
+ }
4769
+ // Reset state
4770
+ abortControllerRef.current = new AbortController();
4771
+ isPausedRef.current = false;
4772
+ currentFileRef.current = file;
4773
+ const docId = documentId || createDocId();
4774
+ const totalChunks = Math.ceil(file.size / chunkSize);
4775
+ const pendingChunks = Array.from({ length: totalChunks }, (_, i) => i);
4776
+ updateProgress({
4777
+ totalBytes: file.size,
4778
+ bytesUploaded: 0,
4779
+ percentage: 0,
4780
+ totalChunks,
4781
+ chunksUploaded: 0,
4782
+ pendingChunks,
4783
+ status: "preparing",
4784
+ error: undefined,
4785
+ uploadId: undefined,
4786
+ documentId: undefined,
4787
+ });
4788
+ try {
4789
+ // Initialize upload session
4790
+ const metadata = {
4791
+ id: docId,
4792
+ time: Math.floor(Date.now() / 1000),
4793
+ kind: file.type || "application/octet-stream",
4794
+ title,
4795
+ comments,
4796
+ user: "trustgraph", // Will be set by server based on auth
4797
+ collection: collection || "default",
4798
+ tags,
4799
+ };
4800
+ const beginResponse = await socket
4801
+ .librarian()
4802
+ .beginUpload(metadata, file.size, chunkSize);
4803
+ const uploadId = beginResponse["upload-id"];
4804
+ uploadIdRef.current = uploadId;
4805
+ updateProgress({
4806
+ status: "uploading",
4807
+ uploadId,
4808
+ });
4809
+ // Upload all chunks
4810
+ await uploadChunks(file, uploadId, pendingChunks, chunkSize, totalChunks);
4811
+ // Check if cancelled
4812
+ if (abortControllerRef.current?.signal.aborted) {
4813
+ return null;
4814
+ }
4815
+ // Complete the upload
4816
+ updateProgress({ status: "completing" });
4817
+ const completeResponse = await socket.librarian().completeUpload(uploadId);
4818
+ const finalDocId = completeResponse["document-id"];
4819
+ updateProgress({
4820
+ status: "completed",
4821
+ documentId: finalDocId,
4822
+ percentage: 100,
4823
+ });
4824
+ // Invalidate documents cache
4825
+ queryClient.invalidateQueries({ queryKey: ["documents"] });
4826
+ notify.success(`Upload complete: ${title}`);
4827
+ onComplete?.(finalDocId);
4828
+ return finalDocId;
4829
+ }
4830
+ catch (err) {
4831
+ const errorMsg = err instanceof Error ? err.message : String(err);
4832
+ updateProgress({ status: "error", error: errorMsg });
4833
+ notify.error(`Upload failed: ${errorMsg}`);
4834
+ onError?.(errorMsg);
4835
+ return null;
4836
+ }
4837
+ }, [
4838
+ socket,
4839
+ connectionState,
4840
+ chunkSize,
4841
+ queryClient,
4842
+ notify,
4843
+ updateProgress,
4844
+ uploadChunks,
4845
+ onComplete,
4846
+ onError,
4847
+ ]);
4848
+ /**
4849
+ * Resume an interrupted upload
4850
+ */
4851
+ const resume = useCallback(async (params) => {
4852
+ const { uploadId, file } = params;
4853
+ // Validate connection
4854
+ if (connectionState?.status !== "authenticated" &&
4855
+ connectionState?.status !== "unauthenticated") {
4856
+ const error = "Not connected to server";
4857
+ updateProgress({ status: "error", error });
4858
+ onError?.(error);
4859
+ return null;
4860
+ }
4861
+ abortControllerRef.current = new AbortController();
4862
+ isPausedRef.current = false;
4863
+ currentFileRef.current = file;
4864
+ uploadIdRef.current = uploadId;
4865
+ updateProgress({
4866
+ status: "preparing",
4867
+ uploadId,
4868
+ });
4869
+ try {
4870
+ // Get current upload status
4871
+ const status = await socket.librarian().getUploadStatus(uploadId);
4872
+ if (status["upload-state"] === "completed") {
4873
+ updateProgress({ status: "completed" });
4874
+ return null;
4875
+ }
4876
+ if (status["upload-state"] === "expired") {
4877
+ throw new Error("Upload session has expired");
4878
+ }
4879
+ const totalChunks = status["total-chunks"];
4880
+ const missingChunks = status["missing-chunks"];
4881
+ const bytesReceived = status["bytes-received"];
4882
+ const totalBytes = status["total-bytes"];
4883
+ updateProgress({
4884
+ totalBytes,
4885
+ bytesUploaded: bytesReceived,
4886
+ percentage: Math.round((bytesReceived / totalBytes) * 100),
4887
+ totalChunks,
4888
+ chunksUploaded: totalChunks - missingChunks.length,
4889
+ pendingChunks: missingChunks,
4890
+ status: "uploading",
4891
+ });
4892
+ // Upload missing chunks
4893
+ const effectiveChunkSize = status["chunk-size"] || chunkSize;
4894
+ await uploadChunks(file, uploadId, missingChunks, effectiveChunkSize, totalChunks);
4895
+ // Check if cancelled
4896
+ if (abortControllerRef.current?.signal.aborted) {
4897
+ return null;
4898
+ }
4899
+ // Complete the upload
4900
+ updateProgress({ status: "completing" });
4901
+ const completeResponse = await socket.librarian().completeUpload(uploadId);
4902
+ const finalDocId = completeResponse["document-id"];
4903
+ updateProgress({
4904
+ status: "completed",
4905
+ documentId: finalDocId,
4906
+ percentage: 100,
4907
+ });
4908
+ // Invalidate documents cache
4909
+ queryClient.invalidateQueries({ queryKey: ["documents"] });
4910
+ notify.success("Upload resumed and completed");
4911
+ onComplete?.(finalDocId);
4912
+ return finalDocId;
4913
+ }
4914
+ catch (err) {
4915
+ const errorMsg = err instanceof Error ? err.message : String(err);
4916
+ updateProgress({ status: "error", error: errorMsg });
4917
+ notify.error(`Resume failed: ${errorMsg}`);
4918
+ onError?.(errorMsg);
4919
+ return null;
4920
+ }
4921
+ }, [
4922
+ socket,
4923
+ connectionState,
4924
+ chunkSize,
4925
+ queryClient,
4926
+ notify,
4927
+ updateProgress,
4928
+ uploadChunks,
4929
+ onComplete,
4930
+ onError,
4931
+ ]);
4932
+ /**
4933
+ * Pause the current upload
4934
+ */
4935
+ const pause = useCallback(() => {
4936
+ if (progress.status === "uploading") {
4937
+ isPausedRef.current = true;
4938
+ updateProgress({ status: "paused" });
4939
+ }
4940
+ }, [progress.status, updateProgress]);
4941
+ /**
4942
+ * Resume a paused upload (not to be confused with resuming an interrupted upload)
4943
+ */
4944
+ const unpause = useCallback(() => {
4945
+ if (progress.status === "paused") {
4946
+ isPausedRef.current = false;
4947
+ updateProgress({ status: "uploading" });
4948
+ }
4949
+ }, [progress.status, updateProgress]);
4950
+ /**
4951
+ * Cancel the current upload
4952
+ */
4953
+ const cancel = useCallback(async () => {
4954
+ abortControllerRef.current?.abort();
4955
+ if (uploadIdRef.current) {
4956
+ try {
4957
+ await socket.librarian().abortUpload(uploadIdRef.current);
4958
+ }
4959
+ catch (err) {
4960
+ console.warn("Failed to abort upload on server:", err);
4961
+ }
4962
+ }
4963
+ updateProgress({
4964
+ status: "cancelled",
4965
+ pendingChunks: [],
4966
+ });
4967
+ uploadIdRef.current = null;
4968
+ currentFileRef.current = null;
4969
+ }, [socket, updateProgress]);
4970
+ /**
4971
+ * Reset the upload state to idle
4972
+ */
4973
+ const reset = useCallback(() => {
4974
+ abortControllerRef.current?.abort();
4975
+ uploadIdRef.current = null;
4976
+ currentFileRef.current = null;
4977
+ isPausedRef.current = false;
4978
+ setProgress({
4979
+ totalBytes: 0,
4980
+ bytesUploaded: 0,
4981
+ percentage: 0,
4982
+ totalChunks: 0,
4983
+ chunksUploaded: 0,
4984
+ pendingChunks: [],
4985
+ status: "idle",
4986
+ });
4987
+ }, []);
4988
+ return {
4989
+ // Current progress state
4990
+ progress,
4991
+ // Control methods
4992
+ upload,
4993
+ resume,
4994
+ pause,
4995
+ unpause,
4996
+ cancel,
4997
+ reset,
4998
+ // Convenience flags
4999
+ isIdle: progress.status === "idle",
5000
+ isUploading: progress.status === "uploading",
5001
+ isPaused: progress.status === "paused",
5002
+ isCompleted: progress.status === "completed",
5003
+ isError: progress.status === "error",
5004
+ };
5005
+ };
5006
+
5007
+ // Default chunk size for downloads: 1MB
5008
+ const DEFAULT_CHUNK_SIZE = 1024 * 1024;
5009
+ /**
5010
+ * Decode base64 string to Uint8Array
5011
+ */
5012
+ const base64ToUint8Array = (base64) => {
5013
+ const binaryString = atob(base64);
5014
+ const bytes = new Uint8Array(binaryString.length);
5015
+ for (let i = 0; i < binaryString.length; i++) {
5016
+ bytes[i] = binaryString.charCodeAt(i);
5017
+ }
5018
+ return bytes;
5019
+ };
5020
+ /**
5021
+ * Trigger browser download of a Blob
5022
+ */
5023
+ const triggerBrowserDownload = (blob, filename) => {
5024
+ const url = URL.createObjectURL(blob);
5025
+ const link = document.createElement("a");
5026
+ link.href = url;
5027
+ link.download = filename;
5028
+ document.body.appendChild(link);
5029
+ link.click();
5030
+ document.body.removeChild(link);
5031
+ URL.revokeObjectURL(url);
5032
+ };
5033
+ /**
5034
+ * Hook for managing streamed document downloads with progress tracking
5035
+ *
5036
+ * Features:
5037
+ * - Streams large documents via WebSocket streaming response
5038
+ * - Progress tracking (chunks received, percentage)
5039
+ * - Cancel support
5040
+ * - Returns Blob or triggers browser download
5041
+ *
5042
+ * @param options - Configuration options for the download
5043
+ * @returns Download state and control methods
5044
+ */
5045
+ const useChunkedDownload = (options = {}) => {
5046
+ const { chunkSize = DEFAULT_CHUNK_SIZE, onProgress, onComplete, onError, } = options;
5047
+ const socket = useSocket();
5048
+ const connectionState = useConnectionState();
5049
+ const notify = useNotification();
5050
+ // Download state
5051
+ const [progress, setProgress] = useState({
5052
+ totalChunks: 0,
5053
+ chunksReceived: 0,
5054
+ percentage: 0,
5055
+ status: "idle",
5056
+ });
5057
+ // Refs for managing download lifecycle
5058
+ const cancelledRef = useRef(false);
5059
+ const chunksRef = useRef(new Map());
5060
+ // Update progress and notify callback
5061
+ const updateProgress = useCallback((updates) => {
5062
+ setProgress((prev) => {
5063
+ const next = { ...prev, ...updates };
5064
+ onProgress?.(next);
5065
+ return next;
5066
+ });
5067
+ }, [onProgress]);
5068
+ /**
5069
+ * Download a document via streaming and return as Blob
5070
+ */
5071
+ const download = useCallback((params) => {
5072
+ const { documentId, mimeType = "application/octet-stream", filename } = params;
5073
+ // Validate connection
5074
+ if (connectionState?.status !== "authenticated" &&
5075
+ connectionState?.status !== "unauthenticated") {
5076
+ const error = "Not connected to server";
5077
+ updateProgress({ status: "error", error });
5078
+ onError?.(error);
5079
+ return Promise.resolve(null);
5080
+ }
5081
+ // Reset state
5082
+ cancelledRef.current = false;
5083
+ chunksRef.current = new Map();
5084
+ updateProgress({
5085
+ totalChunks: 0,
5086
+ chunksReceived: 0,
5087
+ percentage: 0,
5088
+ status: "downloading",
5089
+ error: undefined,
5090
+ documentId,
5091
+ });
5092
+ return new Promise((resolve) => {
5093
+ const onChunk = (content, chunkIndex, totalChunks, complete) => {
5094
+ // Check for cancellation
5095
+ if (cancelledRef.current) {
5096
+ return;
5097
+ }
5098
+ // Store chunk
5099
+ const chunkData = base64ToUint8Array(content);
5100
+ chunksRef.current.set(chunkIndex, chunkData);
5101
+ const chunksReceived = chunksRef.current.size;
5102
+ const percentage = totalChunks > 0
5103
+ ? Math.round((chunksReceived / totalChunks) * 100)
5104
+ : 0;
5105
+ updateProgress({
5106
+ totalChunks,
5107
+ chunksReceived,
5108
+ percentage,
5109
+ });
5110
+ // If complete, reassemble and return
5111
+ if (complete) {
5112
+ if (cancelledRef.current) {
5113
+ resolve(null);
5114
+ return;
5115
+ }
5116
+ // Reassemble chunks in order
5117
+ const orderedChunks = [];
5118
+ for (let i = 0; i < totalChunks; i++) {
5119
+ const chunk = chunksRef.current.get(i);
5120
+ if (chunk) {
5121
+ orderedChunks.push(chunk);
5122
+ }
5123
+ }
5124
+ const blob = new Blob(orderedChunks, { type: mimeType });
5125
+ updateProgress({
5126
+ status: "completed",
5127
+ percentage: 100,
5128
+ chunksReceived: totalChunks,
5129
+ });
5130
+ // Trigger browser download if filename provided
5131
+ if (filename) {
5132
+ triggerBrowserDownload(blob, filename);
5133
+ }
5134
+ notify.success("Download complete");
5135
+ onComplete?.(blob, documentId);
5136
+ resolve(blob);
5137
+ }
5138
+ };
5139
+ const onStreamError = (error) => {
5140
+ if (cancelledRef.current) {
5141
+ return;
5142
+ }
5143
+ updateProgress({ status: "error", error });
5144
+ notify.error(`Download failed: ${error}`);
5145
+ onError?.(error);
5146
+ resolve(null);
5147
+ };
5148
+ // Start streaming download
5149
+ socket.librarian().streamDocument(documentId, onChunk, onStreamError, chunkSize);
5150
+ });
5151
+ }, [socket, connectionState, chunkSize, notify, updateProgress, onComplete, onError]);
5152
+ /**
5153
+ * Cancel the current download
5154
+ */
5155
+ const cancel = useCallback(() => {
5156
+ cancelledRef.current = true;
5157
+ chunksRef.current = new Map();
5158
+ updateProgress({
5159
+ status: "cancelled",
5160
+ });
5161
+ }, [updateProgress]);
5162
+ /**
5163
+ * Reset the download state to idle
5164
+ */
5165
+ const reset = useCallback(() => {
5166
+ cancelledRef.current = true;
5167
+ chunksRef.current = new Map();
5168
+ setProgress({
5169
+ totalChunks: 0,
5170
+ chunksReceived: 0,
5171
+ percentage: 0,
5172
+ status: "idle",
5173
+ });
5174
+ }, []);
5175
+ return {
5176
+ // Current progress state
5177
+ progress,
5178
+ // Control methods
5179
+ download,
5180
+ cancel,
5181
+ reset,
5182
+ // Convenience flags
5183
+ isIdle: progress.status === "idle",
5184
+ isDownloading: progress.status === "downloading",
5185
+ isCompleted: progress.status === "completed",
5186
+ isError: progress.status === "error",
5187
+ };
5188
+ };
5189
+
5190
+ export { DEFAULT_SETTINGS, NotificationProvider, RDFS_LABEL, SETTINGS_STORAGE_KEY, createDocId, fileToBase64, generateFlowBlueprintId, getTermValue$2 as getTermValue, getTriples, prepareMetadata, textToBase64, useActivity, useAgentTools, useChat, useChatSession, useChunkedDownload, useChunkedUpload, useCollections, useConversation, useDocumentEmbeddingsQuery, useEmbeddings, useEntityDetail, useFlowBlueprints, useFlowParameters, useFlows, useGraphEmbeddings, useGraphSubgraph, useInference, useKnowledgeCores, useLLMModels, useLibrary, useLoadStateStore, useMcpTools, useNlpQuery, useNodeDetails, useNotification, useOntologies, useParameterValidation, useProcessing, useProgressStateStore, usePrompts, useRowEmbeddingsQuery, useRowsQuery, useSchemas, useSearchStateStore, useSessionStore, useSettings, useStructuredQuery, useTokenCosts, useTriples, useVectorSearch, useWorkbenchStateStore, vectorSearch };
4643
5191
  //# sourceMappingURL=index.esm.js.map