@elqnt/kg 3.0.0 → 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/dist/api/index.d.mts +94 -5
  2. package/dist/api/index.d.ts +94 -5
  3. package/dist/api/index.js +16 -2
  4. package/dist/api/index.js.map +1 -1
  5. package/dist/api/index.mjs +15 -1
  6. package/dist/api/server.d.mts +4 -3
  7. package/dist/api/server.d.ts +4 -3
  8. package/dist/api/server.js.map +1 -1
  9. package/dist/{chunk-HCDFJCQL.mjs → chunk-5D7RJC7D.mjs} +105 -5
  10. package/dist/chunk-5D7RJC7D.mjs.map +1 -0
  11. package/dist/chunk-67SUELDR.js.map +1 -1
  12. package/dist/chunk-ADIKUMMI.js.map +1 -1
  13. package/dist/chunk-B33SF6DB.js +2 -0
  14. package/dist/chunk-B33SF6DB.js.map +1 -0
  15. package/dist/chunk-BP2I7KWY.js +1031 -0
  16. package/dist/chunk-BP2I7KWY.js.map +1 -0
  17. package/dist/{chunk-2TJCYLTP.js → chunk-CNWOI7LX.js} +104 -4
  18. package/dist/chunk-CNWOI7LX.js.map +1 -0
  19. package/dist/chunk-MAEB7UOW.mjs +257 -0
  20. package/dist/chunk-MAEB7UOW.mjs.map +1 -0
  21. package/dist/chunk-SUDQ45LY.mjs +2 -0
  22. package/dist/chunk-UCKE66GB.js.map +1 -1
  23. package/dist/chunk-WYRCAPY4.js +257 -0
  24. package/dist/chunk-WYRCAPY4.js.map +1 -0
  25. package/dist/chunk-ZEPJC46Z.mjs +1031 -0
  26. package/dist/chunk-ZEPJC46Z.mjs.map +1 -0
  27. package/dist/hooks/index.d.mts +446 -79
  28. package/dist/hooks/index.d.ts +446 -79
  29. package/dist/hooks/index.js +8 -3
  30. package/dist/hooks/index.js.map +1 -1
  31. package/dist/hooks/index.mjs +9 -4
  32. package/dist/index.d.mts +4 -2
  33. package/dist/index.d.ts +4 -2
  34. package/dist/index.js +24 -5
  35. package/dist/index.js.map +1 -1
  36. package/dist/index.mjs +31 -12
  37. package/dist/index.mjs.map +1 -1
  38. package/dist/models/index.d.mts +213 -0
  39. package/dist/models/index.d.ts +213 -0
  40. package/dist/models/index.js +1 -1
  41. package/dist/models/index.js.map +1 -1
  42. package/dist/models/index.mjs +1 -1
  43. package/dist/models/kg-designer.js.map +1 -1
  44. package/dist/models/kg.js.map +1 -1
  45. package/dist/transport/index.d.mts +365 -0
  46. package/dist/transport/index.d.ts +365 -0
  47. package/dist/transport/index.js +10 -0
  48. package/dist/transport/index.js.map +1 -0
  49. package/dist/transport/index.mjs +10 -0
  50. package/dist/transport/index.mjs.map +1 -0
  51. package/dist/utils/index.js +1 -1
  52. package/dist/utils/index.js.map +1 -1
  53. package/dist/utils/index.mjs +1 -1
  54. package/package.json +15 -13
  55. package/dist/chunk-2TJCYLTP.js.map +0 -1
  56. package/dist/chunk-7RW5MHP5.js +0 -497
  57. package/dist/chunk-7RW5MHP5.js.map +0 -1
  58. package/dist/chunk-HCDFJCQL.mjs.map +0 -1
  59. package/dist/chunk-JZ7UXVRW.mjs +0 -497
  60. package/dist/chunk-JZ7UXVRW.mjs.map +0 -1
  61. package/dist/chunk-NJNBEGDB.mjs +0 -2
  62. package/dist/chunk-W4XVBGE7.js +0 -2
  63. package/dist/chunk-W4XVBGE7.js.map +0 -1
  64. /package/dist/{chunk-NJNBEGDB.mjs.map → chunk-SUDQ45LY.mjs.map} +0 -0
@@ -0,0 +1,1031 @@
1
+ "use client";
2
+ import {
3
+ cancelCrawlJobApi,
4
+ cancelFullIngestExtractionApi,
5
+ createDesignerEdgeApi,
6
+ createDesignerNodeApi,
7
+ createGraphApi,
8
+ deleteDesignerEdgeApi,
9
+ deleteDesignerNodeApi,
10
+ deleteGraphApi,
11
+ getCrawlJobStatusApi,
12
+ getCrawledPagesApi,
13
+ getDesignerNodeApi,
14
+ getGraphApi,
15
+ getGraphLabelsApi,
16
+ getKGNodeApi,
17
+ ingestFullIngestNodesApi,
18
+ ingestKGNodeApi,
19
+ listCrawlJobsApi,
20
+ listDesignerEdgesApi,
21
+ listDesignerNodesApi,
22
+ listGraphsApi,
23
+ queryGraphApi,
24
+ startCrawlJobApi,
25
+ startFullIngestExtractionApi,
26
+ startQuickIngestApi,
27
+ updateDesignerEdgeApi,
28
+ updateDesignerNodeApi,
29
+ updateGraphApi,
30
+ updateKGNodeApi
31
+ } from "./chunk-5D7RJC7D.mjs";
32
+ import {
33
+ createFullIngestTransport
34
+ } from "./chunk-MAEB7UOW.mjs";
35
+
36
+ // hooks/use-graphs.ts
37
+ import { useCallback, useMemo } from "react";
38
+ import { useApiAsync } from "@elqnt/api-client/hooks";
39
+
40
+ // hooks/use-options-ref.ts
41
+ import { useRef, useEffect } from "react";
42
+ function useOptionsRef(options) {
43
+ const ref = useRef(options);
44
+ useEffect(() => {
45
+ ref.current = options;
46
+ }, [options]);
47
+ return ref;
48
+ }
49
+
50
+ // hooks/use-graphs.ts
51
+ function useGraphs(options) {
52
+ const optionsRef = useOptionsRef(options);
53
+ const {
54
+ execute: listGraphs,
55
+ loading: listLoading,
56
+ error: listError
57
+ } = useApiAsync(
58
+ () => listGraphsApi(optionsRef.current),
59
+ (data) => data.graphs || [],
60
+ []
61
+ );
62
+ const {
63
+ execute: getGraphInternal,
64
+ loading: getLoading,
65
+ error: getError
66
+ } = useApiAsync(
67
+ (graphId) => getGraphApi(graphId, optionsRef.current),
68
+ (data) => data.graph || null,
69
+ null
70
+ );
71
+ const getGraph = useCallback((graphId) => getGraphInternal(graphId), [getGraphInternal]);
72
+ const {
73
+ execute: createGraphInternal,
74
+ loading: createLoading,
75
+ error: createError
76
+ } = useApiAsync(
77
+ (graph) => createGraphApi(graph, optionsRef.current),
78
+ (data) => data.graph || null,
79
+ null
80
+ );
81
+ const createGraph = useCallback(
82
+ (graph) => createGraphInternal(graph),
83
+ [createGraphInternal]
84
+ );
85
+ const {
86
+ execute: updateGraphInternal,
87
+ loading: updateLoading,
88
+ error: updateError
89
+ } = useApiAsync(
90
+ (graphId, updates) => updateGraphApi(graphId, updates, optionsRef.current),
91
+ (data) => data.graph || null,
92
+ null
93
+ );
94
+ const updateGraph = useCallback(
95
+ (graphId, updates) => updateGraphInternal(graphId, updates),
96
+ [updateGraphInternal]
97
+ );
98
+ const {
99
+ execute: deleteGraphInternal,
100
+ loading: deleteLoading,
101
+ error: deleteError
102
+ } = useApiAsync(
103
+ (graphId) => deleteGraphApi(graphId, optionsRef.current),
104
+ (data) => data.success ?? true,
105
+ false
106
+ );
107
+ const deleteGraph = useCallback(
108
+ (graphId) => deleteGraphInternal(graphId),
109
+ [deleteGraphInternal]
110
+ );
111
+ const loading = listLoading || getLoading || createLoading || updateLoading || deleteLoading;
112
+ const error = listError || getError || createError || updateError || deleteError;
113
+ return useMemo(
114
+ () => ({
115
+ loading,
116
+ error,
117
+ listGraphs,
118
+ getGraph,
119
+ createGraph,
120
+ updateGraph,
121
+ deleteGraph
122
+ }),
123
+ [loading, error, listGraphs, getGraph, createGraph, updateGraph, deleteGraph]
124
+ );
125
+ }
126
+
127
+ // hooks/use-kg-query.ts
128
+ import { useCallback as useCallback2, useMemo as useMemo2 } from "react";
129
+ import { useApiAsync as useApiAsync2 } from "@elqnt/api-client/hooks";
130
+ function useKGQuery(options) {
131
+ const optionsRef = useOptionsRef(options);
132
+ const {
133
+ execute: queryInternal,
134
+ loading: queryLoading,
135
+ error: queryError
136
+ } = useApiAsync2(
137
+ (queryParams) => queryGraphApi(queryParams, optionsRef.current),
138
+ (data) => data,
139
+ null
140
+ );
141
+ const query = useCallback2(
142
+ (queryParams) => queryInternal(queryParams),
143
+ [queryInternal]
144
+ );
145
+ const {
146
+ execute: getLabels,
147
+ loading: labelsLoading,
148
+ error: labelsError
149
+ } = useApiAsync2(
150
+ () => getGraphLabelsApi(optionsRef.current),
151
+ (data) => data.labels || [],
152
+ []
153
+ );
154
+ const {
155
+ execute: getNodeInternal,
156
+ loading: nodeLoading,
157
+ error: nodeError
158
+ } = useApiAsync2(
159
+ (nodeId) => getKGNodeApi(nodeId, optionsRef.current),
160
+ (data) => data.node || null,
161
+ null
162
+ );
163
+ const getNode = useCallback2((nodeId) => getNodeInternal(nodeId), [getNodeInternal]);
164
+ const {
165
+ execute: ingestNodeInternal,
166
+ loading: ingestLoading,
167
+ error: ingestError
168
+ } = useApiAsync2(
169
+ (node) => ingestKGNodeApi(node, optionsRef.current),
170
+ (data) => data.nodeId || null,
171
+ null
172
+ );
173
+ const ingestNode = useCallback2(
174
+ (node) => ingestNodeInternal(node),
175
+ [ingestNodeInternal]
176
+ );
177
+ const {
178
+ execute: updateNodeInternal,
179
+ loading: updateLoading,
180
+ error: updateError
181
+ } = useApiAsync2(
182
+ (nodeId, updates) => updateKGNodeApi(nodeId, updates, optionsRef.current),
183
+ (data) => data.success ?? true,
184
+ false
185
+ );
186
+ const updateNode = useCallback2(
187
+ (nodeId, updates) => updateNodeInternal(nodeId, updates),
188
+ [updateNodeInternal]
189
+ );
190
+ const loading = queryLoading || labelsLoading || nodeLoading || ingestLoading || updateLoading;
191
+ const error = queryError || labelsError || nodeError || ingestError || updateError;
192
+ return useMemo2(
193
+ () => ({
194
+ loading,
195
+ error,
196
+ query,
197
+ getLabels,
198
+ getNode,
199
+ ingestNode,
200
+ updateNode
201
+ }),
202
+ [loading, error, query, getLabels, getNode, ingestNode, updateNode]
203
+ );
204
+ }
205
+
206
+ // hooks/use-kg-designer.ts
207
+ import { useCallback as useCallback3, useMemo as useMemo3 } from "react";
208
+ import { useApiAsync as useApiAsync3 } from "@elqnt/api-client/hooks";
209
+ function useKGDesigner(options) {
210
+ const optionsRef = useOptionsRef(options);
211
+ const {
212
+ execute: listNodes,
213
+ loading: listNodesLoading,
214
+ error: listNodesError
215
+ } = useApiAsync3(
216
+ () => listDesignerNodesApi(optionsRef.current),
217
+ (data) => data.nodes || [],
218
+ []
219
+ );
220
+ const {
221
+ execute: getNodeInternal,
222
+ loading: getNodeLoading,
223
+ error: getNodeError
224
+ } = useApiAsync3(
225
+ (label) => getDesignerNodeApi(label, optionsRef.current),
226
+ (data) => data.node || null,
227
+ null
228
+ );
229
+ const getNode = useCallback3((label) => getNodeInternal(label), [getNodeInternal]);
230
+ const {
231
+ execute: createNodeInternal,
232
+ loading: createNodeLoading,
233
+ error: createNodeError
234
+ } = useApiAsync3(
235
+ (node) => createDesignerNodeApi(node, optionsRef.current),
236
+ (data) => data.node || null,
237
+ null
238
+ );
239
+ const createNode = useCallback3(
240
+ (node) => createNodeInternal(node),
241
+ [createNodeInternal]
242
+ );
243
+ const {
244
+ execute: updateNodeInternal,
245
+ loading: updateNodeLoading,
246
+ error: updateNodeError
247
+ } = useApiAsync3(
248
+ (label, updates) => updateDesignerNodeApi(label, updates, optionsRef.current),
249
+ (data) => data.node || null,
250
+ null
251
+ );
252
+ const updateNode = useCallback3(
253
+ (label, updates) => updateNodeInternal(label, updates),
254
+ [updateNodeInternal]
255
+ );
256
+ const {
257
+ execute: deleteNodeInternal,
258
+ loading: deleteNodeLoading,
259
+ error: deleteNodeError
260
+ } = useApiAsync3(
261
+ (label) => deleteDesignerNodeApi(label, optionsRef.current),
262
+ (data) => data.success ?? true,
263
+ false
264
+ );
265
+ const deleteNode = useCallback3((label) => deleteNodeInternal(label), [deleteNodeInternal]);
266
+ const {
267
+ execute: listEdges,
268
+ loading: listEdgesLoading,
269
+ error: listEdgesError
270
+ } = useApiAsync3(
271
+ () => listDesignerEdgesApi(optionsRef.current),
272
+ (data) => data.edges || [],
273
+ []
274
+ );
275
+ const {
276
+ execute: createEdgeInternal,
277
+ loading: createEdgeLoading,
278
+ error: createEdgeError
279
+ } = useApiAsync3(
280
+ (edge) => createDesignerEdgeApi(edge, optionsRef.current),
281
+ (data) => data.edge || null,
282
+ null
283
+ );
284
+ const createEdge = useCallback3(
285
+ (edge) => createEdgeInternal(edge),
286
+ [createEdgeInternal]
287
+ );
288
+ const {
289
+ execute: updateEdgeInternal,
290
+ loading: updateEdgeLoading,
291
+ error: updateEdgeError
292
+ } = useApiAsync3(
293
+ (label, updates) => updateDesignerEdgeApi(label, updates, optionsRef.current),
294
+ (data) => data.edge || null,
295
+ null
296
+ );
297
+ const updateEdge = useCallback3(
298
+ (label, updates) => updateEdgeInternal(label, updates),
299
+ [updateEdgeInternal]
300
+ );
301
+ const {
302
+ execute: deleteEdgeInternal,
303
+ loading: deleteEdgeLoading,
304
+ error: deleteEdgeError
305
+ } = useApiAsync3(
306
+ (label) => deleteDesignerEdgeApi(label, optionsRef.current),
307
+ (data) => data.success ?? true,
308
+ false
309
+ );
310
+ const deleteEdge = useCallback3((label) => deleteEdgeInternal(label), [deleteEdgeInternal]);
311
+ const loading = listNodesLoading || getNodeLoading || createNodeLoading || updateNodeLoading || deleteNodeLoading || listEdgesLoading || createEdgeLoading || updateEdgeLoading || deleteEdgeLoading;
312
+ const error = listNodesError || getNodeError || createNodeError || updateNodeError || deleteNodeError || listEdgesError || createEdgeError || updateEdgeError || deleteEdgeError;
313
+ return useMemo3(
314
+ () => ({
315
+ loading,
316
+ error,
317
+ // Nodes
318
+ listNodes,
319
+ getNode,
320
+ createNode,
321
+ updateNode,
322
+ deleteNode,
323
+ // Edges
324
+ listEdges,
325
+ createEdge,
326
+ updateEdge,
327
+ deleteEdge
328
+ }),
329
+ [
330
+ loading,
331
+ error,
332
+ listNodes,
333
+ getNode,
334
+ createNode,
335
+ updateNode,
336
+ deleteNode,
337
+ listEdges,
338
+ createEdge,
339
+ updateEdge,
340
+ deleteEdge
341
+ ]
342
+ );
343
+ }
344
+
345
+ // hooks/use-crawl-jobs.ts
346
+ import { useCallback as useCallback4, useMemo as useMemo4 } from "react";
347
+ import { useApiAsync as useApiAsync4 } from "@elqnt/api-client/hooks";
348
+ function useCrawlJobs(options) {
349
+ const optionsRef = useOptionsRef(options);
350
+ const {
351
+ execute: listJobsInternal,
352
+ loading: listLoading,
353
+ error: listError
354
+ } = useApiAsync4(
355
+ (params) => listCrawlJobsApi({ ...optionsRef.current, ...params }),
356
+ (data) => ({ jobs: data.jobs || [], total: data.total || 0 }),
357
+ { jobs: [], total: 0 }
358
+ );
359
+ const listJobs = useCallback4(
360
+ (params) => listJobsInternal(params),
361
+ [listJobsInternal]
362
+ );
363
+ const {
364
+ execute: startJobInternal,
365
+ loading: startLoading,
366
+ error: startError
367
+ } = useApiAsync4(
368
+ (params) => startCrawlJobApi(params, optionsRef.current),
369
+ (data) => data.jobId || null,
370
+ null
371
+ );
372
+ const startJob = useCallback4(
373
+ (params) => startJobInternal(params),
374
+ [startJobInternal]
375
+ );
376
+ const {
377
+ execute: getJobStatusInternal,
378
+ loading: statusLoading,
379
+ error: statusError
380
+ } = useApiAsync4(
381
+ (jobId) => getCrawlJobStatusApi(jobId, optionsRef.current),
382
+ (data) => data.job || null,
383
+ null
384
+ );
385
+ const getJobStatus = useCallback4(
386
+ (jobId) => getJobStatusInternal(jobId),
387
+ [getJobStatusInternal]
388
+ );
389
+ const {
390
+ execute: cancelJobInternal,
391
+ loading: cancelLoading,
392
+ error: cancelError
393
+ } = useApiAsync4(
394
+ (jobId) => cancelCrawlJobApi(jobId, optionsRef.current),
395
+ (data) => data.success ?? true,
396
+ false
397
+ );
398
+ const cancelJob = useCallback4((jobId) => cancelJobInternal(jobId), [cancelJobInternal]);
399
+ const {
400
+ execute: getCrawledPagesInternal,
401
+ loading: pagesLoading,
402
+ error: pagesError
403
+ } = useApiAsync4(
404
+ (jobId) => getCrawledPagesApi(jobId, optionsRef.current),
405
+ (data) => data.pages || [],
406
+ []
407
+ );
408
+ const getCrawledPages = useCallback4(
409
+ (jobId) => getCrawledPagesInternal(jobId),
410
+ [getCrawledPagesInternal]
411
+ );
412
+ const loading = listLoading || startLoading || statusLoading || cancelLoading || pagesLoading;
413
+ const error = listError || startError || statusError || cancelError || pagesError;
414
+ return useMemo4(
415
+ () => ({
416
+ loading,
417
+ error,
418
+ listJobs,
419
+ startJob,
420
+ getJobStatus,
421
+ cancelJob,
422
+ getCrawledPages
423
+ }),
424
+ [loading, error, listJobs, startJob, getJobStatus, cancelJob, getCrawledPages]
425
+ );
426
+ }
427
+
428
+ // hooks/use-quick-ingest.ts
429
+ import { useCallback as useCallback5, useMemo as useMemo5, useState, useRef as useRef2 } from "react";
430
+ function useQuickIngest(options) {
431
+ const optionsRef = useOptionsRef(options);
432
+ const [items, setItems] = useState([]);
433
+ const [isProcessing, setIsProcessing] = useState(false);
434
+ const [error, setError] = useState(null);
435
+ const abortControllerRef = useRef2(null);
436
+ const uploadFile = useCallback5(async (file) => {
437
+ const tempId = `temp_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
438
+ const placeholderItem = {
439
+ id: tempId,
440
+ type: "document",
441
+ name: file.name,
442
+ sizeBytes: file.size,
443
+ status: "uploading",
444
+ progress: 0
445
+ };
446
+ setItems((prev) => [...prev, placeholderItem]);
447
+ try {
448
+ const result = await optionsRef.current.onUploadFile(file);
449
+ if (result.error) {
450
+ throw new Error(result.error);
451
+ }
452
+ const uploadedItem = {
453
+ id: tempId,
454
+ type: "document",
455
+ name: file.name,
456
+ url: result.url,
457
+ sizeBytes: file.size,
458
+ pageCount: result.pageCount,
459
+ status: "ready",
460
+ progress: 100
461
+ };
462
+ setItems(
463
+ (prev) => prev.map((item) => item.id === tempId ? uploadedItem : item)
464
+ );
465
+ return uploadedItem;
466
+ } catch (err) {
467
+ setItems(
468
+ (prev) => prev.map(
469
+ (item) => item.id === tempId ? { ...item, status: "error", error: String(err) } : item
470
+ )
471
+ );
472
+ throw err;
473
+ }
474
+ }, []);
475
+ const addUrl = useCallback5((url) => {
476
+ const id = `url_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
477
+ const item = {
478
+ id,
479
+ type: "url",
480
+ name: url,
481
+ url,
482
+ status: "ready",
483
+ progress: 0
484
+ };
485
+ setItems((prev) => [...prev, item]);
486
+ }, []);
487
+ const removeItem = useCallback5((id) => {
488
+ setItems((prev) => prev.filter((item) => item.id !== id));
489
+ }, []);
490
+ const clearQueue = useCallback5(() => {
491
+ setItems([]);
492
+ setError(null);
493
+ }, []);
494
+ const startIngestion = useCallback5(
495
+ async (ingestionOptions) => {
496
+ const readyItems = items.filter((item) => item.status === "ready" && item.url);
497
+ if (readyItems.length === 0) {
498
+ setError("No items ready for ingestion");
499
+ return;
500
+ }
501
+ setError(null);
502
+ setIsProcessing(true);
503
+ abortControllerRef.current = new AbortController();
504
+ setItems(
505
+ (prev) => prev.map(
506
+ (item) => item.status === "ready" ? { ...item, status: "processing" } : item
507
+ )
508
+ );
509
+ try {
510
+ const request = {
511
+ items: readyItems.map((item) => ({
512
+ id: item.id,
513
+ type: item.type,
514
+ name: item.name,
515
+ url: item.url
516
+ })),
517
+ options: ingestionOptions,
518
+ graphId: optionsRef.current.graphId || "default"
519
+ };
520
+ await startQuickIngestApi(request, optionsRef.current, (event) => {
521
+ switch (event.type) {
522
+ case "item_start":
523
+ setItems(
524
+ (prev) => prev.map(
525
+ (item) => item.id === event.itemId ? { ...item, status: "processing", progress: 0 } : item
526
+ )
527
+ );
528
+ break;
529
+ case "item_progress":
530
+ setItems(
531
+ (prev) => prev.map(
532
+ (item) => item.id === event.itemId ? { ...item, progress: event.progress || 0, progressText: event.text } : item
533
+ )
534
+ );
535
+ break;
536
+ case "item_complete":
537
+ setItems(
538
+ (prev) => prev.map(
539
+ (item) => item.id === event.itemId ? {
540
+ ...item,
541
+ status: "complete",
542
+ progress: 100,
543
+ result: {
544
+ articlesCreated: event.articles,
545
+ topicsCreated: event.topics,
546
+ nodesCreated: event.nodesCreated,
547
+ nodesByLabel: event.nodesByLabel
548
+ }
549
+ } : item
550
+ )
551
+ );
552
+ break;
553
+ case "item_error":
554
+ setItems(
555
+ (prev) => prev.map(
556
+ (item) => item.id === event.itemId ? { ...item, status: "error", error: event.error } : item
557
+ )
558
+ );
559
+ break;
560
+ case "job_complete":
561
+ setIsProcessing(false);
562
+ break;
563
+ case "error":
564
+ setError(event.message || event.error || "Unknown error");
565
+ setIsProcessing(false);
566
+ break;
567
+ case "cancelled":
568
+ setIsProcessing(false);
569
+ setItems(
570
+ (prev) => prev.map(
571
+ (item) => item.status === "processing" ? { ...item, status: "ready" } : item
572
+ )
573
+ );
574
+ break;
575
+ }
576
+ });
577
+ setIsProcessing(false);
578
+ } catch (err) {
579
+ setError(String(err));
580
+ setIsProcessing(false);
581
+ setItems(
582
+ (prev) => prev.map(
583
+ (item) => item.status === "processing" ? { ...item, status: "ready" } : item
584
+ )
585
+ );
586
+ }
587
+ },
588
+ [items]
589
+ );
590
+ const cancelIngestion = useCallback5(() => {
591
+ if (abortControllerRef.current) {
592
+ abortControllerRef.current.abort();
593
+ abortControllerRef.current = null;
594
+ }
595
+ setIsProcessing(false);
596
+ setItems(
597
+ (prev) => prev.map(
598
+ (item) => item.status === "processing" ? { ...item, status: "ready" } : item
599
+ )
600
+ );
601
+ }, []);
602
+ return useMemo5(
603
+ () => ({
604
+ items,
605
+ isProcessing,
606
+ error,
607
+ uploadFile,
608
+ addUrl,
609
+ removeItem,
610
+ startIngestion,
611
+ cancelIngestion,
612
+ clearQueue
613
+ }),
614
+ [
615
+ items,
616
+ isProcessing,
617
+ error,
618
+ uploadFile,
619
+ addUrl,
620
+ removeItem,
621
+ startIngestion,
622
+ cancelIngestion,
623
+ clearQueue
624
+ ]
625
+ );
626
+ }
627
+
628
+ // hooks/use-full-ingest.ts
629
+ import { useCallback as useCallback6, useMemo as useMemo6, useState as useState2, useEffect as useEffect2, useRef as useRef3 } from "react";
630
+ function useFullIngest(options) {
631
+ const optionsRef = useOptionsRef(options);
632
+ const [sourceType, setSourceType] = useState2(null);
633
+ const [document, setDocument] = useState2(null);
634
+ const [crawlJob, setCrawlJob] = useState2(null);
635
+ const [selectedLabels, setSelectedLabels] = useState2([]);
636
+ const [extractedNodes, setExtractedNodes] = useState2([]);
637
+ const [extractedEdges, setExtractedEdges] = useState2([]);
638
+ const [isExtracting, setIsExtracting] = useState2(false);
639
+ const [extractionProgress, setExtractionProgress] = useState2(null);
640
+ const [isIngesting, setIsIngesting] = useState2(false);
641
+ const [ingestProgress, setIngestProgress] = useState2(null);
642
+ const [jobId, setJobId] = useState2(null);
643
+ const [error, setError] = useState2(null);
644
+ const transportRef = useRef3(null);
645
+ useEffect2(() => {
646
+ return () => {
647
+ if (transportRef.current) {
648
+ transportRef.current.disconnect();
649
+ transportRef.current = null;
650
+ }
651
+ };
652
+ }, []);
653
+ const uploadDocument = useCallback6(async (file) => {
654
+ setError(null);
655
+ try {
656
+ const { onUploadFile } = optionsRef.current;
657
+ if (onUploadFile) {
658
+ const result = await onUploadFile(file);
659
+ if (result.error) {
660
+ throw new Error(result.error);
661
+ }
662
+ setDocument({
663
+ url: result.url,
664
+ pageCount: result.pageCount || 0,
665
+ sizeBytes: file.size
666
+ });
667
+ } else {
668
+ const url = URL.createObjectURL(file);
669
+ setDocument({
670
+ url,
671
+ pageCount: 0,
672
+ sizeBytes: file.size
673
+ });
674
+ }
675
+ setSourceType("document");
676
+ } catch (err) {
677
+ setError(String(err));
678
+ throw err;
679
+ }
680
+ }, []);
681
+ const setDocumentUrl = useCallback6(
682
+ (url, pageCount, sizeBytes) => {
683
+ setDocument({ url, pageCount, sizeBytes });
684
+ setSourceType("document");
685
+ setError(null);
686
+ },
687
+ []
688
+ );
689
+ const startCrawl = useCallback6(
690
+ async (url, depth, maxPages) => {
691
+ setError(null);
692
+ try {
693
+ const response = await startCrawlJobApi(
694
+ { baseUrl: url, depth, maxPages },
695
+ optionsRef.current
696
+ );
697
+ if (!response.data?.jobId) {
698
+ throw new Error(response.error || "Failed to start crawl");
699
+ }
700
+ const pollInterval = setInterval(async () => {
701
+ const statusResponse = await getCrawlJobStatusApi(
702
+ response.data.jobId,
703
+ optionsRef.current
704
+ );
705
+ if (statusResponse.data?.job) {
706
+ setCrawlJob(statusResponse.data.job);
707
+ if (statusResponse.data.job.status === "completed" || statusResponse.data.job.status === "failed") {
708
+ clearInterval(pollInterval);
709
+ if (statusResponse.data.job.status === "failed") {
710
+ setError("Crawl job failed");
711
+ }
712
+ }
713
+ }
714
+ }, 2e3);
715
+ setSourceType("website");
716
+ setCrawlJob({
717
+ id: response.data.jobId,
718
+ baseUrl: url,
719
+ depth,
720
+ maxPages,
721
+ status: "pending",
722
+ pagesProcessed: 0,
723
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
724
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
725
+ });
726
+ } catch (err) {
727
+ setError(String(err));
728
+ throw err;
729
+ }
730
+ },
731
+ []
732
+ );
733
+ const startExtraction = useCallback6(async () => {
734
+ if (!sourceType) {
735
+ setError("No source selected");
736
+ return;
737
+ }
738
+ if (selectedLabels.length === 0) {
739
+ setError("No labels selected");
740
+ return;
741
+ }
742
+ let sourceId;
743
+ if (sourceType === "document") {
744
+ if (!document) {
745
+ setError("No document uploaded");
746
+ return;
747
+ }
748
+ sourceId = document.url;
749
+ } else {
750
+ if (!crawlJob) {
751
+ setError("No crawl job");
752
+ return;
753
+ }
754
+ sourceId = crawlJob.id;
755
+ }
756
+ setError(null);
757
+ setIsExtracting(true);
758
+ setExtractedNodes([]);
759
+ setExtractedEdges([]);
760
+ setExtractionProgress(null);
761
+ try {
762
+ const request = {
763
+ sourceType,
764
+ sourceId,
765
+ labels: selectedLabels,
766
+ graphId: optionsRef.current.graphId || "default"
767
+ };
768
+ const response = await startFullIngestExtractionApi(request, optionsRef.current);
769
+ if (!response.data) {
770
+ throw new Error(response.error || "Failed to start extraction");
771
+ }
772
+ const newJobId = response.data.jobId;
773
+ setJobId(newJobId);
774
+ const transport = createFullIngestTransport({ debug: options.debug });
775
+ await transport.connect(optionsRef.current);
776
+ transportRef.current = transport;
777
+ transport.on("progress", (event) => {
778
+ setExtractionProgress({
779
+ current: event.currentPage,
780
+ total: event.totalPages,
781
+ phase: "extracting"
782
+ });
783
+ });
784
+ transport.on("node", (event) => {
785
+ const node = {
786
+ id: event.id,
787
+ label: event.label,
788
+ fields: event.fields
789
+ };
790
+ setExtractedNodes((prev) => [...prev, node]);
791
+ });
792
+ transport.on("consolidating", (event) => {
793
+ setExtractionProgress((prev) => ({
794
+ current: prev?.current || 0,
795
+ total: prev?.total || 0,
796
+ phase: "consolidating",
797
+ message: event.message
798
+ }));
799
+ });
800
+ transport.on("consolidated", (event) => {
801
+ setExtractionProgress((prev) => ({
802
+ current: prev?.current || 0,
803
+ total: prev?.total || 0,
804
+ phase: "consolidating",
805
+ message: event.message
806
+ }));
807
+ });
808
+ transport.on("linking", (event) => {
809
+ setExtractionProgress((prev) => ({
810
+ current: prev?.current || 0,
811
+ total: prev?.total || 0,
812
+ phase: "linking",
813
+ message: event.message
814
+ }));
815
+ });
816
+ transport.on("edge", (event) => {
817
+ const edge = {
818
+ id: event.id,
819
+ fromLabel: event.fromLabel,
820
+ fromName: event.fromName,
821
+ toLabel: event.toLabel,
822
+ toName: event.toName,
823
+ edgeLabel: event.edgeLabel,
824
+ confidence: event.confidence
825
+ };
826
+ setExtractedEdges((prev) => [...prev, edge]);
827
+ });
828
+ transport.on("linked", (event) => {
829
+ setExtractionProgress((prev) => ({
830
+ current: prev?.current || 0,
831
+ total: prev?.total || 0,
832
+ phase: "linking",
833
+ message: event.message
834
+ }));
835
+ });
836
+ transport.on("complete", (event) => {
837
+ setExtractionProgress((prev) => ({
838
+ current: prev?.current || 0,
839
+ total: prev?.total || 0,
840
+ phase: "complete",
841
+ message: event.message
842
+ }));
843
+ setIsExtracting(false);
844
+ setJobId(null);
845
+ transport.disconnect();
846
+ transportRef.current = null;
847
+ });
848
+ transport.on("error", (event) => {
849
+ setError(event.message);
850
+ setIsExtracting(false);
851
+ setJobId(null);
852
+ transport.disconnect();
853
+ transportRef.current = null;
854
+ });
855
+ transport.subscribeToJob(newJobId);
856
+ } catch (err) {
857
+ setError(String(err));
858
+ setIsExtracting(false);
859
+ setJobId(null);
860
+ }
861
+ }, [sourceType, document, crawlJob, selectedLabels, options.debug]);
862
+ const cancelExtraction = useCallback6(async () => {
863
+ if (!jobId) return;
864
+ try {
865
+ await cancelFullIngestExtractionApi(jobId, optionsRef.current);
866
+ if (transportRef.current) {
867
+ transportRef.current.disconnect();
868
+ transportRef.current = null;
869
+ }
870
+ setIsExtracting(false);
871
+ setJobId(null);
872
+ } catch (err) {
873
+ setError(String(err));
874
+ }
875
+ }, [jobId]);
876
+ const removeNode = useCallback6((id) => {
877
+ setExtractedNodes((prev) => prev.filter((node) => node.id !== id));
878
+ }, []);
879
+ const updateNode = useCallback6((id, fields) => {
880
+ setExtractedNodes(
881
+ (prev) => prev.map((node) => node.id === id ? { ...node, fields } : node)
882
+ );
883
+ }, []);
884
+ const removeEdge = useCallback6((id) => {
885
+ setExtractedEdges((prev) => prev.filter((edge) => edge.id !== id));
886
+ }, []);
887
+ const ingestNodes = useCallback6(async () => {
888
+ if (!jobId) {
889
+ setError("No job ID - extraction must be started first");
890
+ return;
891
+ }
892
+ if (extractedNodes.length === 0) {
893
+ setError("No nodes to ingest");
894
+ return;
895
+ }
896
+ setError(null);
897
+ setIsIngesting(true);
898
+ setIngestProgress(null);
899
+ try {
900
+ const request = {
901
+ jobId
902
+ };
903
+ const response = await ingestFullIngestNodesApi(request, optionsRef.current);
904
+ if (!response.data) {
905
+ throw new Error(response.error || "Failed to start ingestion");
906
+ }
907
+ const transport = createFullIngestTransport({ debug: options.debug });
908
+ await transport.connect(optionsRef.current);
909
+ transportRef.current = transport;
910
+ transport.on("ingest_progress", (event) => {
911
+ setIngestProgress({
912
+ currentNode: event.currentNode,
913
+ totalNodes: event.totalNodes,
914
+ currentEdge: event.currentEdge,
915
+ totalEdges: event.totalEdges,
916
+ message: event.message
917
+ });
918
+ });
919
+ transport.on("ingest_complete", (event) => {
920
+ setIngestProgress({
921
+ currentNode: event.nodesIngested,
922
+ totalNodes: event.nodesIngested,
923
+ currentEdge: event.edgesIngested,
924
+ totalEdges: event.edgesIngested,
925
+ message: event.message
926
+ });
927
+ setIsIngesting(false);
928
+ setExtractedNodes([]);
929
+ setExtractedEdges([]);
930
+ transport.disconnect();
931
+ transportRef.current = null;
932
+ });
933
+ transport.on("error", (event) => {
934
+ setError(event.message);
935
+ setIsIngesting(false);
936
+ transport.disconnect();
937
+ transportRef.current = null;
938
+ });
939
+ transport.subscribeToJob(jobId);
940
+ } catch (err) {
941
+ setError(String(err));
942
+ setIsIngesting(false);
943
+ throw err;
944
+ }
945
+ }, [jobId, extractedNodes, options.debug]);
946
+ const reset = useCallback6(() => {
947
+ if (transportRef.current) {
948
+ transportRef.current.disconnect();
949
+ transportRef.current = null;
950
+ }
951
+ setSourceType(null);
952
+ setDocument(null);
953
+ setCrawlJob(null);
954
+ setSelectedLabels([]);
955
+ setExtractedNodes([]);
956
+ setExtractedEdges([]);
957
+ setIsExtracting(false);
958
+ setExtractionProgress(null);
959
+ setIsIngesting(false);
960
+ setIngestProgress(null);
961
+ setJobId(null);
962
+ setError(null);
963
+ }, []);
964
+ return useMemo6(
965
+ () => ({
966
+ sourceType,
967
+ document,
968
+ crawlJob,
969
+ selectedLabels,
970
+ extractedNodes,
971
+ extractedEdges,
972
+ isExtracting,
973
+ extractionProgress,
974
+ isIngesting,
975
+ ingestProgress,
976
+ jobId,
977
+ error,
978
+ uploadDocument,
979
+ setDocumentUrl,
980
+ startCrawl,
981
+ setSelectedLabels,
982
+ startExtraction,
983
+ cancelExtraction,
984
+ removeNode,
985
+ updateNode,
986
+ removeEdge,
987
+ ingestNodes,
988
+ reset
989
+ }),
990
+ [
991
+ sourceType,
992
+ document,
993
+ crawlJob,
994
+ selectedLabels,
995
+ extractedNodes,
996
+ extractedEdges,
997
+ isExtracting,
998
+ extractionProgress,
999
+ isIngesting,
1000
+ ingestProgress,
1001
+ jobId,
1002
+ error,
1003
+ uploadDocument,
1004
+ setDocumentUrl,
1005
+ startCrawl,
1006
+ startExtraction,
1007
+ cancelExtraction,
1008
+ removeNode,
1009
+ updateNode,
1010
+ removeEdge,
1011
+ ingestNodes,
1012
+ reset
1013
+ ]
1014
+ );
1015
+ }
1016
+
1017
+ // hooks/index.ts
1018
+ import { useApiAsync as useApiAsync5, useAsync } from "@elqnt/api-client/hooks";
1019
+
1020
+ export {
1021
+ useOptionsRef,
1022
+ useGraphs,
1023
+ useKGQuery,
1024
+ useKGDesigner,
1025
+ useCrawlJobs,
1026
+ useQuickIngest,
1027
+ useFullIngest,
1028
+ useApiAsync5 as useApiAsync,
1029
+ useAsync
1030
+ };
1031
+ //# sourceMappingURL=chunk-ZEPJC46Z.mjs.map