@trustgraph/client 0.2.0

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 (49) hide show
  1. package/LICENSE +176 -0
  2. package/README.md +319 -0
  3. package/dist/__tests__/flows-api.test.d.ts +2 -0
  4. package/dist/__tests__/flows-api.test.d.ts.map +1 -0
  5. package/dist/__tests__/messages.test.d.ts +2 -0
  6. package/dist/__tests__/messages.test.d.ts.map +1 -0
  7. package/dist/__tests__/service-call-multi.test.d.ts +2 -0
  8. package/dist/__tests__/service-call-multi.test.d.ts.map +1 -0
  9. package/dist/__tests__/service-call.test.d.ts +2 -0
  10. package/dist/__tests__/service-call.test.d.ts.map +1 -0
  11. package/dist/api/authenticated-fetch.d.ts +18 -0
  12. package/dist/api/authenticated-fetch.d.ts.map +1 -0
  13. package/dist/api/trustgraph/SocketContext.d.ts +2 -0
  14. package/dist/api/trustgraph/SocketContext.d.ts.map +1 -0
  15. package/dist/api/trustgraph/SocketProvider.d.ts +21 -0
  16. package/dist/api/trustgraph/SocketProvider.d.ts.map +1 -0
  17. package/dist/api/trustgraph/Triple.d.ts +17 -0
  18. package/dist/api/trustgraph/Triple.d.ts.map +1 -0
  19. package/dist/api/trustgraph/messages.d.ts +205 -0
  20. package/dist/api/trustgraph/messages.d.ts.map +1 -0
  21. package/dist/api/trustgraph/service-call-multi.d.ts +17 -0
  22. package/dist/api/trustgraph/service-call-multi.d.ts.map +1 -0
  23. package/dist/api/trustgraph/service-call.d.ts +57 -0
  24. package/dist/api/trustgraph/service-call.d.ts.map +1 -0
  25. package/dist/api/trustgraph/socket.d.ts +2 -0
  26. package/dist/api/trustgraph/socket.d.ts.map +1 -0
  27. package/dist/api/trustgraph/trustgraph-socket.d.ts +429 -0
  28. package/dist/api/trustgraph/trustgraph-socket.d.ts.map +1 -0
  29. package/dist/index.cjs +1370 -0
  30. package/dist/index.cjs.map +1 -0
  31. package/dist/index.d.ts +4 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.esm.js +1361 -0
  34. package/dist/index.esm.js.map +1 -0
  35. package/dist/index.js +1375 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/models/Triple.d.ts +17 -0
  38. package/dist/models/Triple.d.ts.map +1 -0
  39. package/dist/models/messages.d.ts +215 -0
  40. package/dist/models/messages.d.ts.map +1 -0
  41. package/dist/socket/service-call-multi.d.ts +30 -0
  42. package/dist/socket/service-call-multi.d.ts.map +1 -0
  43. package/dist/socket/service-call.d.ts +69 -0
  44. package/dist/socket/service-call.d.ts.map +1 -0
  45. package/dist/socket/trustgraph-socket.d.ts +433 -0
  46. package/dist/socket/trustgraph-socket.d.ts.map +1 -0
  47. package/dist/types.d.ts +2 -0
  48. package/dist/types.d.ts.map +1 -0
  49. package/package.json +68 -0
package/dist/index.cjs ADDED
@@ -0,0 +1,1370 @@
1
+ 'use strict';
2
+
3
+ // Constant defining the delay before attempting to reconnect a WebSocket
4
+ // (2 seconds)
5
+ const SOCKET_RECONNECTION_TIMEOUT$2 = 2000;
6
+ class ServiceCallMulti {
7
+ constructor(mid, msg, success, error, timeout, retries, socket, receiver) {
8
+ this.mid = mid;
9
+ this.msg = msg;
10
+ this.success = success;
11
+ this.error = error;
12
+ this.timeout = timeout;
13
+ this.retries = retries;
14
+ this.socket = socket;
15
+ this.complete = false;
16
+ this.receiver = receiver;
17
+ }
18
+ start() {
19
+ this.socket.inflight[this.mid] = this;
20
+ this.attempt();
21
+ }
22
+ onReceived(resp) {
23
+ if (this.complete == true)
24
+ console.log(this.mid, "should not happen, request is already complete");
25
+ const fin = this.receiver(resp);
26
+ if (fin) {
27
+ this.complete = true;
28
+ // console.log("Received for", this.mid);
29
+ clearTimeout(this.timeoutId);
30
+ this.timeoutId = undefined;
31
+ delete this.socket.inflight[this.mid];
32
+ this.success(resp);
33
+ }
34
+ }
35
+ onTimeout() {
36
+ if (this.complete == true)
37
+ console.log(this.mid, "timeout should not happen, request is already complete");
38
+ console.log("Request", this.mid, "timed out");
39
+ clearTimeout(this.timeoutId);
40
+ this.attempt();
41
+ }
42
+ attempt() {
43
+ // console.log("attempt:", this.mid);
44
+ if (this.complete == true)
45
+ console.log(this.mid, "attempt should not be called, request is already complete");
46
+ this.retries--;
47
+ if (this.retries < 0) {
48
+ console.log("Request", this.mid, "ran out of retries");
49
+ clearTimeout(this.timeoutId);
50
+ delete this.socket.inflight[this.mid];
51
+ this.error("Ran out of retries");
52
+ return; // Exit early - no more attempts
53
+ }
54
+ // Check if WebSocket connection is available and ready
55
+ if (this.socket.ws && this.socket.ws.readyState === WebSocket.OPEN) {
56
+ try {
57
+ this.socket.ws.send(JSON.stringify(this.msg));
58
+ this.timeoutId = setTimeout(this.onTimeout.bind(this), this.timeout);
59
+ return;
60
+ }
61
+ catch (e) {
62
+ console.log("Error:", e);
63
+ console.log("Message send failure, retry...");
64
+ // Calculate backoff delay with jitter
65
+ const backoffDelay = Math.min(SOCKET_RECONNECTION_TIMEOUT$2 * Math.pow(2, 3 - this.retries) +
66
+ Math.random() * 1000, 30000);
67
+ this.timeoutId = setTimeout(this.attempt.bind(this), backoffDelay);
68
+ console.log("Reopen...");
69
+ // Attempt to reopen the WebSocket connection
70
+ this.socket.reopen();
71
+ }
72
+ }
73
+ else {
74
+ // No WebSocket connection available or not ready
75
+ // Check if socket is connecting
76
+ if (this.socket.ws &&
77
+ this.socket.ws.readyState === WebSocket.CONNECTING) {
78
+ // Wait a bit longer for connection to establish
79
+ setTimeout(this.attempt.bind(this), 500);
80
+ }
81
+ else {
82
+ // Socket is closed or closing, trigger reopen
83
+ console.log("Socket not ready, reopening...");
84
+ this.socket.reopen();
85
+ // Calculate backoff delay
86
+ const backoffDelay = Math.min(SOCKET_RECONNECTION_TIMEOUT$2 * Math.pow(2, 3 - this.retries) +
87
+ Math.random() * 1000, 30000);
88
+ setTimeout(this.attempt.bind(this), backoffDelay);
89
+ }
90
+ }
91
+ }
92
+ }
93
+
94
+ // Constant defining the delay before attempting to reconnect a WebSocket
95
+ // (2 seconds)
96
+ const SOCKET_RECONNECTION_TIMEOUT$1 = 2000;
97
+ /**
98
+ * ServiceCall represents a single request/response cycle over a WebSocket
99
+ * connection with built-in retry logic, timeout handling, and completion
100
+ * tracking.
101
+ *
102
+ * This class manages the lifecycle of a service call including:
103
+ * - Sending the initial request
104
+ * - Handling timeouts and retries
105
+ * - Managing completion state
106
+ * - Cleaning up resources
107
+ */
108
+ class ServiceCall {
109
+ constructor(mid, // Message ID - unique identifier for this request
110
+ msg, // The actual message/request to send
111
+ success, // Callback function called on
112
+ // successful response
113
+ error, // Callback function called on error/failure
114
+ timeout, // Timeout duration in milliseconds
115
+ retries, // Number of retry attempts allowed
116
+ socket) {
117
+ this.mid = mid;
118
+ this.msg = msg;
119
+ this.success = success;
120
+ this.error = error;
121
+ this.timeout = timeout;
122
+ this.retries = retries;
123
+ this.socket = socket;
124
+ this.complete = false; // Track if this request has completed
125
+ }
126
+ /**
127
+ * Initiates the service call by registering it with the socket's inflight
128
+ * requests and making the first attempt to send the message
129
+ */
130
+ start() {
131
+ // Register this request as "in-flight" so responses can be matched to it
132
+ this.socket.inflight[this.mid] = this;
133
+ // Make the first attempt to send the message
134
+ this.attempt();
135
+ }
136
+ /**
137
+ * Called when a response is received for this request
138
+ * Handles cleanup and calls the success or error callback based on response
139
+ *
140
+ * @param resp - The response object received from the server
141
+ */
142
+ onReceived(resp) {
143
+ // Defensive check - this shouldn't happen but log if it does
144
+ if (this.complete == true)
145
+ console.log(this.mid, "should not happen, request is already complete");
146
+ // Mark as complete to prevent duplicate processing
147
+ this.complete = true;
148
+ // Clean up timeout timer
149
+ clearTimeout(this.timeoutId);
150
+ this.timeoutId = undefined;
151
+ // Remove from inflight requests tracker
152
+ delete this.socket.inflight[this.mid];
153
+ // Check if the response contains an error (error can be directly in resp or nested under response)
154
+ let errorToHandle = null;
155
+ // Check for direct error in response
156
+ if (resp && typeof resp === "object" && "error" in resp) {
157
+ errorToHandle = resp.error;
158
+ }
159
+ // Check for nested error under response property
160
+ else if (resp && typeof resp === "object" && "response" in resp) {
161
+ const response = resp.response;
162
+ if (response && typeof response === "object" && "error" in response) {
163
+ errorToHandle = response.error;
164
+ }
165
+ }
166
+ if (errorToHandle) {
167
+ // Response contains an error - call error callback
168
+ const errorObj = errorToHandle;
169
+ const errorMessage = (typeof errorObj.message === "string" ? errorObj.message : null) ||
170
+ (typeof errorObj.type === "string" ? errorObj.type : null) ||
171
+ "Unknown error";
172
+ console.log("ServiceCall: API error detected in response:", errorMessage, "Full error:", errorToHandle);
173
+ this.error(new Error(errorMessage));
174
+ return;
175
+ }
176
+ // Call success callback with the response
177
+ this.success(resp);
178
+ }
179
+ /**
180
+ * Called when the request times out
181
+ * Triggers another attempt if retries are available
182
+ */
183
+ onTimeout() {
184
+ // Defensive check - this shouldn't happen but log if it does
185
+ if (this.complete == true)
186
+ console.log(this.mid, "timeout should not happen, request is already complete");
187
+ console.log("Request", this.mid, "timed out");
188
+ // Clear the current timeout
189
+ clearTimeout(this.timeoutId);
190
+ // Try again (this will check retry count)
191
+ this.attempt();
192
+ }
193
+ /**
194
+ * Calculates exponential backoff delay with jitter
195
+ * @returns backoff delay in milliseconds
196
+ */
197
+ calculateBackoff() {
198
+ return Math.min(SOCKET_RECONNECTION_TIMEOUT$1 * Math.pow(2, 3 - this.retries) +
199
+ Math.random() * 1000, 30000);
200
+ }
201
+ /**
202
+ * Core retry logic - attempts to send the message over the WebSocket
203
+ * Handles retries and waits for BaseApi to handle reconnection
204
+ */
205
+ attempt() {
206
+ // Defensive check - this shouldn't be called on completed requests
207
+ if (this.complete == true)
208
+ console.log(this.mid, "attempt should not be called, request is already complete");
209
+ // Decrement retry counter
210
+ this.retries--;
211
+ // Check if we've exhausted all retries
212
+ if (this.retries < 0) {
213
+ console.log("Request", this.mid, "ran out of retries");
214
+ // Clean up and call error callback
215
+ clearTimeout(this.timeoutId);
216
+ delete this.socket.inflight[this.mid];
217
+ this.error("Ran out of retries");
218
+ return; // Exit early - no more attempts
219
+ }
220
+ // Check if WebSocket connection is available and ready
221
+ if (this.socket.ws && this.socket.ws.readyState === WebSocket.OPEN) {
222
+ try {
223
+ // Attempt to send the message as JSON
224
+ this.socket.ws.send(JSON.stringify(this.msg));
225
+ // Set up timeout for this attempt
226
+ this.timeoutId = setTimeout(this.onTimeout.bind(this), this.timeout);
227
+ return; // Success - message sent, waiting for response or timeout
228
+ }
229
+ catch (e) {
230
+ // Handle send failure - wait for BaseApi to handle reconnection
231
+ console.log("Error:", e);
232
+ console.log("Message send failure, waiting for socket reconnection...");
233
+ // Schedule retry with backoff - let BaseApi handle the reconnection
234
+ this.timeoutId = setTimeout(this.attempt.bind(this), this.calculateBackoff());
235
+ }
236
+ }
237
+ else {
238
+ // No WebSocket connection available or not ready
239
+ // Let BaseApi handle reconnection, just wait and retry
240
+ console.log("Request", this.mid, "waiting for socket reconnection...");
241
+ // Use consistent backoff for all waiting scenarios
242
+ setTimeout(this.attempt.bind(this), this.calculateBackoff());
243
+ }
244
+ }
245
+ }
246
+
247
+ // Configuration constants
248
+ const SOCKET_RECONNECTION_TIMEOUT = 2000; // 2 seconds between reconnection
249
+ // attempts
250
+ const SOCKET_URL = "/api/socket"; // WebSocket endpoint path
251
+ /**
252
+ * Generates a random message ID using cryptographically secure random values
253
+ * @param length - Number of random characters to generate
254
+ * @returns Random string of specified length
255
+ */
256
+ function makeid(length) {
257
+ const array = new Uint32Array(length);
258
+ crypto.getRandomValues(array);
259
+ const characters = "abcdefghijklmnopqrstuvwxyz1234567890";
260
+ return array.reduce((acc, current) => acc + characters[current % characters.length], "");
261
+ }
262
+ class BaseApi {
263
+ constructor(user, token) {
264
+ this.inflight = {}; // Track active requests by
265
+ // message ID
266
+ this.reconnectAttempts = 0; // Track reconnection attempts
267
+ this.maxReconnectAttempts = 10; // Maximum reconnection attempts
268
+ this.reconnectionState = "idle"; // Connection state
269
+ // Connection state tracking for UI
270
+ this.connectionStateListeners = [];
271
+ this.tag = makeid(16); // Generate unique client tag
272
+ this.id = 1; // Start message ID counter
273
+ this.token = token; // Store authentication token
274
+ this.user = user; // Store user identifier
275
+ console.log("SOCKET: opening socket...", token ? "with auth" : "without auth", "user:", user);
276
+ this.openSocket(); // Establish WebSocket connection
277
+ console.log("SOCKET: socket opened");
278
+ }
279
+ /**
280
+ * Subscribe to connection state changes for UI updates
281
+ */
282
+ onConnectionStateChange(listener) {
283
+ this.connectionStateListeners.push(listener);
284
+ // Immediately send current state
285
+ listener(this.getConnectionState());
286
+ // Return unsubscribe function
287
+ return () => {
288
+ const index = this.connectionStateListeners.indexOf(listener);
289
+ if (index > -1) {
290
+ this.connectionStateListeners.splice(index, 1);
291
+ }
292
+ };
293
+ }
294
+ /**
295
+ * Get current connection state
296
+ */
297
+ getConnectionState() {
298
+ const hasApiKey = !!this.token;
299
+ // Determine status based on WebSocket state and reconnection state
300
+ let status;
301
+ if (!this.ws || this.ws.readyState === WebSocket.CLOSED) {
302
+ if (this.reconnectionState === "failed") {
303
+ status = "failed";
304
+ }
305
+ else if (this.reconnectionState === "reconnecting") {
306
+ status = "reconnecting";
307
+ }
308
+ else {
309
+ status = "connecting";
310
+ }
311
+ }
312
+ else if (this.ws.readyState === WebSocket.CONNECTING) {
313
+ status = "connecting";
314
+ }
315
+ else if (this.ws.readyState === WebSocket.OPEN) {
316
+ status = hasApiKey ? "authenticated" : "unauthenticated";
317
+ }
318
+ else {
319
+ status = "connecting";
320
+ }
321
+ const state = {
322
+ status,
323
+ hasApiKey,
324
+ lastError: this.lastError,
325
+ };
326
+ // Add reconnection details if applicable
327
+ if (status === "reconnecting") {
328
+ state.reconnectAttempt = this.reconnectAttempts;
329
+ state.maxAttempts = this.maxReconnectAttempts;
330
+ }
331
+ return state;
332
+ }
333
+ /**
334
+ * Notify all listeners of connection state changes
335
+ */
336
+ notifyStateChange() {
337
+ const state = this.getConnectionState();
338
+ this.connectionStateListeners.forEach((listener) => {
339
+ try {
340
+ listener(state);
341
+ }
342
+ catch (error) {
343
+ console.error("Error in connection state listener:", error);
344
+ }
345
+ });
346
+ }
347
+ /**
348
+ * Establishes WebSocket connection and sets up event handlers
349
+ */
350
+ openSocket() {
351
+ // Don't create multiple connections
352
+ if (this.ws &&
353
+ (this.ws.readyState === WebSocket.CONNECTING ||
354
+ this.ws.readyState === WebSocket.OPEN)) {
355
+ return;
356
+ }
357
+ // Clean up old socket if exists
358
+ if (this.ws) {
359
+ this.ws.removeEventListener("message", this.onMessage);
360
+ this.ws.removeEventListener("close", this.onClose);
361
+ this.ws.removeEventListener("open", this.onOpen);
362
+ this.ws.removeEventListener("error", this.onError);
363
+ this.ws = undefined;
364
+ }
365
+ try {
366
+ // Build WebSocket URL with optional token parameter
367
+ const wsUrl = this.token
368
+ ? `${SOCKET_URL}?token=${this.token}`
369
+ : SOCKET_URL;
370
+ console.log("SOCKET: connecting to", wsUrl.replace(/token=[^&]*/, "token=***"));
371
+ this.ws = new WebSocket(wsUrl);
372
+ }
373
+ catch (e) {
374
+ console.error("[socket creation error]", e);
375
+ this.scheduleReconnect();
376
+ return;
377
+ }
378
+ // Bind event handlers to maintain proper 'this' context
379
+ this.onMessage = this.onMessage.bind(this);
380
+ this.onClose = this.onClose.bind(this);
381
+ this.onOpen = this.onOpen.bind(this);
382
+ this.onError = this.onError.bind(this);
383
+ // Attach event listeners
384
+ this.ws.addEventListener("message", this.onMessage);
385
+ this.ws.addEventListener("close", this.onClose);
386
+ this.ws.addEventListener("open", this.onOpen);
387
+ this.ws.addEventListener("error", this.onError);
388
+ }
389
+ // Handle incoming messages from server
390
+ onMessage(message) {
391
+ if (!message.data)
392
+ return;
393
+ try {
394
+ const obj = JSON.parse(message.data);
395
+ // Skip messages without ID (can't route them)
396
+ if (!obj.id)
397
+ return;
398
+ // Route response to the corresponding inflight request
399
+ if (this.inflight[obj.id]) {
400
+ this.inflight[obj.id].onReceived(obj.response);
401
+ }
402
+ }
403
+ catch (e) {
404
+ console.error("[socket message parse error]", e);
405
+ }
406
+ }
407
+ // Handle connection closure - automatically attempt reconnection
408
+ onClose(event) {
409
+ console.log("[socket close]", event.code, event.reason);
410
+ this.lastError = `Connection closed: ${event.reason || "Unknown reason"}`;
411
+ this.ws = undefined;
412
+ this.notifyStateChange();
413
+ this.scheduleReconnect();
414
+ }
415
+ // Handle successful connection
416
+ onOpen() {
417
+ console.log("[socket open]");
418
+ this.reconnectAttempts = 0; // Reset reconnection attempts on success
419
+ this.reconnectionState = "idle"; // Reset connection state
420
+ this.lastError = undefined; // Clear any previous errors
421
+ // Clear any pending reconnect timer
422
+ if (this.reconnectTimer) {
423
+ clearTimeout(this.reconnectTimer);
424
+ this.reconnectTimer = undefined;
425
+ }
426
+ // Notify UI of successful connection
427
+ this.notifyStateChange();
428
+ }
429
+ // Handle socket errors
430
+ onError(event) {
431
+ console.error("[socket error]", event);
432
+ this.lastError = "Connection error occurred";
433
+ this.notifyStateChange();
434
+ }
435
+ /**
436
+ * Schedules a reconnection attempt with exponential backoff
437
+ */
438
+ scheduleReconnect() {
439
+ // Prevent concurrent reconnection attempts
440
+ if (this.reconnectionState === "reconnecting") {
441
+ console.log("[socket] Reconnection already in progress, skipping");
442
+ return;
443
+ }
444
+ // Don't schedule if already scheduled
445
+ if (this.reconnectTimer)
446
+ return;
447
+ this.reconnectionState = "reconnecting";
448
+ this.reconnectAttempts++;
449
+ this.notifyStateChange(); // Notify UI of reconnection attempt
450
+ if (this.reconnectAttempts > this.maxReconnectAttempts) {
451
+ console.error("[socket] Max reconnection attempts reached");
452
+ this.reconnectionState = "failed";
453
+ this.lastError = "Max reconnection attempts exceeded";
454
+ this.notifyStateChange();
455
+ // Notify all pending requests of the failure
456
+ for (const mid in this.inflight) {
457
+ this.inflight[mid].error(new Error("WebSocket connection failed"));
458
+ }
459
+ return;
460
+ }
461
+ // Calculate exponential backoff with jitter
462
+ const backoffDelay = Math.min(SOCKET_RECONNECTION_TIMEOUT * Math.pow(2, this.reconnectAttempts - 1) +
463
+ Math.random() * 1000, 30000);
464
+ console.log(`[socket] Reconnecting in ${backoffDelay}ms (attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts})`);
465
+ this.reconnectTimer = setTimeout(() => {
466
+ this.reconnectTimer = undefined;
467
+ this.reopen();
468
+ }, backoffDelay);
469
+ }
470
+ /**
471
+ * Reopens the WebSocket connection (used after connection failures)
472
+ */
473
+ reopen() {
474
+ console.log("[socket reopen]");
475
+ // Check if we're already connected or connecting
476
+ if (this.ws &&
477
+ (this.ws.readyState === WebSocket.OPEN ||
478
+ this.ws.readyState === WebSocket.CONNECTING)) {
479
+ return;
480
+ }
481
+ this.openSocket();
482
+ }
483
+ /**
484
+ * Closes the WebSocket connection and cleans up
485
+ */
486
+ close() {
487
+ // Clear reconnection timer
488
+ if (this.reconnectTimer) {
489
+ clearTimeout(this.reconnectTimer);
490
+ this.reconnectTimer = undefined;
491
+ }
492
+ // Clean up WebSocket
493
+ if (this.ws) {
494
+ // Remove event listeners to prevent memory leaks
495
+ this.ws.removeEventListener("message", this.onMessage);
496
+ this.ws.removeEventListener("close", this.onClose);
497
+ this.ws.removeEventListener("open", this.onOpen);
498
+ this.ws.removeEventListener("error", this.onError);
499
+ this.ws.close();
500
+ this.ws = undefined;
501
+ }
502
+ // Clear any remaining inflight requests
503
+ for (const mid in this.inflight) {
504
+ this.inflight[mid].error(new Error("Socket closed"));
505
+ }
506
+ this.inflight = {};
507
+ }
508
+ /**
509
+ * Generates the next unique message ID for requests
510
+ * Format: {clientTag}-{incrementingNumber}
511
+ */
512
+ getNextId() {
513
+ const mid = this.tag + "-" + this.id.toString();
514
+ this.id++;
515
+ return mid;
516
+ }
517
+ /**
518
+ * Core method for making service requests over WebSocket
519
+ * @param service - Name of the service to call
520
+ * @param request - Request payload
521
+ * @param timeout - Request timeout in milliseconds (default: 10000)
522
+ * @param retries - Number of retry attempts (default: 3)
523
+ * @param flow - Optional flow identifier
524
+ * @returns Promise resolving to the service response
525
+ */
526
+ makeRequest(service, request, timeout, retries, flow) {
527
+ const mid = this.getNextId();
528
+ // Set default values
529
+ if (timeout == undefined)
530
+ timeout = 10000;
531
+ if (retries == undefined)
532
+ retries = 3;
533
+ // Construct the request message
534
+ const msg = {
535
+ id: mid,
536
+ service: service,
537
+ request: request,
538
+ };
539
+ // Add flow identifier if provided
540
+ if (flow)
541
+ msg.flow = flow;
542
+ // Return a Promise that will be resolved/rejected by the ServiceCall
543
+ return new Promise((resolve, reject) => {
544
+ const call = new ServiceCall(mid, msg, resolve, reject, timeout, retries, this);
545
+ call.start();
546
+ // Commented out debug logging: console.log("-->", msg);
547
+ }).then((obj) => {
548
+ // Commented out success logging: console.log("Success for", mid);
549
+ return obj;
550
+ });
551
+ }
552
+ /**
553
+ * Makes a request that can receive multiple responses (streaming)
554
+ * Used for operations that return data in chunks
555
+ */
556
+ makeRequestMulti(service, request, receiver, // Callback to handle each response chunk
557
+ timeout, retries, flow) {
558
+ const mid = this.getNextId();
559
+ // Set defaults
560
+ if (timeout == undefined)
561
+ timeout = 10000;
562
+ if (retries == undefined)
563
+ retries = 3;
564
+ // Construct request message
565
+ const msg = {
566
+ id: mid,
567
+ service: service,
568
+ request: request,
569
+ };
570
+ if (flow)
571
+ msg.flow = flow;
572
+ return new Promise((resolve, reject) => {
573
+ const call = new ServiceCallMulti(mid, msg, resolve, reject, timeout, retries, this, // eslint-disable-line @typescript-eslint/no-explicit-any
574
+ receiver);
575
+ call.start();
576
+ }).then((obj) => {
577
+ return obj;
578
+ });
579
+ }
580
+ /**
581
+ * Convenience method for making flow-specific requests
582
+ * Defaults to "default" flow if none specified
583
+ */
584
+ makeFlowRequest(service, request, timeout, retries, flow) {
585
+ if (!flow)
586
+ flow = "default";
587
+ return this.makeRequest(service, request, timeout, retries, flow);
588
+ }
589
+ // Factory methods for creating specialized API instances
590
+ librarian() {
591
+ return new LibrarianApi(this);
592
+ }
593
+ flows() {
594
+ return new FlowsApi(this);
595
+ }
596
+ flow(id) {
597
+ return new FlowApi(this, id);
598
+ }
599
+ knowledge() {
600
+ return new KnowledgeApi(this);
601
+ }
602
+ config() {
603
+ return new ConfigApi(this);
604
+ }
605
+ collectionManagement() {
606
+ return new CollectionManagementApi(this);
607
+ }
608
+ }
609
+ /**
610
+ * LibrarianApi - Manages document storage and retrieval
611
+ * Handles document lifecycle including upload, processing, and removal
612
+ */
613
+ class LibrarianApi {
614
+ constructor(api) {
615
+ this.api = api;
616
+ }
617
+ /**
618
+ * Retrieves list of all documents in the system
619
+ */
620
+ getDocuments() {
621
+ return this.api
622
+ .makeRequest("librarian", {
623
+ operation: "list-documents",
624
+ user: this.api.user,
625
+ }, 60000)
626
+ .then((r) => r["document-metadatas"] || []);
627
+ }
628
+ /**
629
+ * Retrieves list of documents currently being processed
630
+ */
631
+ getProcessing() {
632
+ return this.api
633
+ .makeRequest("librarian", {
634
+ operation: "list-processing",
635
+ user: this.api.user,
636
+ }, 60000)
637
+ .then((r) => r["processing-metadata"] || []);
638
+ }
639
+ /**
640
+ * Uploads a document to the library with full metadata
641
+ * @param document - Base64-encoded document content
642
+ * @param id - Optional document identifier
643
+ * @param metadata - Optional metadata as triples
644
+ * @param mimeType - Document MIME type
645
+ * @param title - Document title
646
+ * @param comments - Additional comments
647
+ * @param tags - Document tags for categorization
648
+ */
649
+ loadDocument(document, // base64-encoded doc
650
+ mimeType, title, comments, tags, id, metadata) {
651
+ return this.api.makeRequest("librarian", {
652
+ operation: "add-document",
653
+ "document-metadata": {
654
+ id: id,
655
+ time: Math.floor(Date.now() / 1000), // Unix timestamp
656
+ kind: mimeType,
657
+ title: title,
658
+ comments: comments,
659
+ metadata: metadata,
660
+ user: this.api.user,
661
+ tags: tags,
662
+ },
663
+ content: document,
664
+ }, 30000);
665
+ }
666
+ /**
667
+ * Removes a document from the library
668
+ */
669
+ removeDocument(id, collection) {
670
+ return this.api.makeRequest("librarian", {
671
+ operation: "remove-document",
672
+ "document-id": id,
673
+ user: this.api.user,
674
+ collection: collection || "default",
675
+ }, 30000);
676
+ }
677
+ /**
678
+ * Adds a document to the processing queue
679
+ * @param id - Processing job identifier
680
+ * @param doc_id - Document to process
681
+ * @param flow - Processing flow to use
682
+ * @param collection - Collection to add processed data to
683
+ * @param tags - Tags for the processing job
684
+ */
685
+ addProcessing(id, doc_id, flow, collection, tags) {
686
+ return this.api.makeRequest("librarian", {
687
+ operation: "add-processing",
688
+ "processing-metadata": {
689
+ id: id,
690
+ "document-id": doc_id,
691
+ time: Math.floor(Date.now() / 1000),
692
+ flow: flow,
693
+ user: this.api.user,
694
+ collection: collection ? collection : "default",
695
+ tags: tags ? tags : [],
696
+ },
697
+ }, 30000);
698
+ }
699
+ }
700
+ /**
701
+ * FlowsApi - Manages processing flows and configuration
702
+ * Flows define how documents and data are processed through the system
703
+ */
704
+ class FlowsApi {
705
+ constructor(api) {
706
+ this.api = api;
707
+ }
708
+ /**
709
+ * Retrieves list of available flows
710
+ */
711
+ getFlows() {
712
+ return this.api
713
+ .makeRequest("flow", {
714
+ operation: "list-flows",
715
+ }, 60000)
716
+ .then((r) => r["flow-ids"] || []);
717
+ }
718
+ /**
719
+ * Retrieves definition of a specific flow
720
+ */
721
+ getFlow(id) {
722
+ return this.api
723
+ .makeRequest("flow", {
724
+ operation: "get-flow",
725
+ "flow-id": id,
726
+ }, 60000)
727
+ .then((r) => JSON.parse(r.flow || "{}")); // Parse JSON flow definition
728
+ }
729
+ // Configuration management methods
730
+ /**
731
+ * Retrieves all configuration settings
732
+ */
733
+ getConfigAll() {
734
+ return this.api.makeRequest("config", {
735
+ operation: "config",
736
+ }, 60000);
737
+ }
738
+ /**
739
+ * Retrieves specific configuration values by key
740
+ */
741
+ getConfig(keys) {
742
+ return this.api.makeRequest("config", {
743
+ operation: "get",
744
+ keys: keys,
745
+ }, 60000);
746
+ }
747
+ /**
748
+ * Updates configuration values
749
+ */
750
+ putConfig(values) {
751
+ return this.api.makeRequest("config", {
752
+ operation: "put",
753
+ values: values,
754
+ }, 60000);
755
+ }
756
+ /**
757
+ * Deletes configuration entries
758
+ */
759
+ deleteConfig(keys) {
760
+ return this.api.makeRequest("config", {
761
+ operation: "delete",
762
+ keys: keys,
763
+ }, 30000);
764
+ }
765
+ // Prompt management - specialized config operations for AI prompts
766
+ /**
767
+ * Retrieves list of available prompt templates
768
+ */
769
+ getPrompts() {
770
+ return this.getConfigAll().then((r) => {
771
+ const config = r;
772
+ return JSON.parse(config.config.prompt["template-index"]);
773
+ });
774
+ }
775
+ /**
776
+ * Retrieves a specific prompt template
777
+ */
778
+ getPrompt(id) {
779
+ return this.getConfigAll().then((r) => {
780
+ const config = r;
781
+ return JSON.parse(config.config.prompt[`template.${id}`]);
782
+ });
783
+ }
784
+ /**
785
+ * Retrieves the system prompt configuration
786
+ */
787
+ getSystemPrompt() {
788
+ return this.getConfigAll().then((r) => {
789
+ const config = r;
790
+ return JSON.parse(config.config.prompt.system);
791
+ });
792
+ }
793
+ // Flow class management - templates for creating flows
794
+ /**
795
+ * Retrieves list of available flow classes (templates)
796
+ */
797
+ getFlowClasses() {
798
+ return this.api
799
+ .makeRequest("flow", {
800
+ operation: "list-classes",
801
+ }, 60000)
802
+ .then((r) => r["class-names"]);
803
+ }
804
+ /**
805
+ * Retrieves definition of a specific flow class
806
+ */
807
+ getFlowClass(name) {
808
+ return this.api
809
+ .makeRequest("flow", {
810
+ operation: "get-class",
811
+ "class-name": name,
812
+ }, 60000)
813
+ .then((r) => JSON.parse(r["class-definition"] || "{}"));
814
+ }
815
+ /**
816
+ * Deletes a flow class
817
+ */
818
+ deleteFlowClass(name) {
819
+ return this.api.makeRequest("flow", {
820
+ operation: "delete-class",
821
+ "class-name": name,
822
+ }, 30000);
823
+ }
824
+ // Flow lifecycle management
825
+ /**
826
+ * Starts a new flow instance
827
+ */
828
+ startFlow(id, class_name, description, parameters) {
829
+ const request = {
830
+ operation: "start-flow",
831
+ "flow-id": id,
832
+ "class-name": class_name,
833
+ description: description,
834
+ };
835
+ // Only include parameters if provided and not empty
836
+ if (parameters && Object.keys(parameters).length > 0) {
837
+ request.parameters = parameters;
838
+ }
839
+ return this.api
840
+ .makeRequest("flow", request, 30000)
841
+ .then((response) => {
842
+ if (response.error) {
843
+ let errorMessage = "Flow start failed";
844
+ if (typeof response.error === "object" &&
845
+ response.error &&
846
+ "message" in response.error) {
847
+ errorMessage =
848
+ response.error.message || errorMessage;
849
+ }
850
+ else if (typeof response.error === "string") {
851
+ errorMessage = response.error;
852
+ }
853
+ throw new Error(errorMessage);
854
+ }
855
+ return response;
856
+ });
857
+ }
858
+ /**
859
+ * Stops a running flow instance
860
+ */
861
+ stopFlow(id) {
862
+ return this.api.makeRequest("flow", {
863
+ operation: "stop-flow",
864
+ "flow-id": id,
865
+ }, 30000);
866
+ }
867
+ }
868
+ /**
869
+ * FlowApi - Interface for interacting with a specific flow instance
870
+ * Provides flow-specific versions of core AI/ML operations
871
+ */
872
+ class FlowApi {
873
+ constructor(api, flowId) {
874
+ this.api = api;
875
+ this.flowId = flowId; // All requests will be routed through this flow
876
+ }
877
+ /**
878
+ * Performs text completion using AI models within this flow
879
+ */
880
+ textCompletion(system, text) {
881
+ return this.api
882
+ .makeRequest("text-completion", {
883
+ system: system, // System prompt/instructions
884
+ prompt: text, // User prompt
885
+ }, 30000, undefined, // Use default retries
886
+ this.flowId)
887
+ .then((r) => r.response);
888
+ }
889
+ /**
890
+ * Performs Graph RAG (Retrieval Augmented Generation) query
891
+ */
892
+ graphRag(text, options, collection) {
893
+ return this.api
894
+ .makeRequest("graph-rag", {
895
+ query: text,
896
+ user: this.api.user,
897
+ collection: collection || "default",
898
+ "entity-limit": options?.entityLimit,
899
+ "triple-limit": options?.tripleLimit,
900
+ "max-subgraph-size": options?.maxSubgraphSize,
901
+ "max-path-length": options?.pathLength,
902
+ }, 60000, // Longer timeout for complex graph operations
903
+ undefined, this.flowId)
904
+ .then((r) => r.response);
905
+ }
906
+ /**
907
+ * Performs Document RAG (Retrieval Augmented Generation) query
908
+ */
909
+ documentRag(text, docLimit, collection) {
910
+ return this.api
911
+ .makeRequest("document-rag", {
912
+ query: text,
913
+ user: this.api.user,
914
+ collection: collection || "default",
915
+ "doc-limit": docLimit || 20,
916
+ }, 60000, // Longer timeout for document operations
917
+ undefined, this.flowId)
918
+ .then((r) => r.response);
919
+ }
920
+ /**
921
+ * Interacts with an AI agent that provides streaming responses
922
+ */
923
+ agent(question, think, // Called when agent is thinking
924
+ observe, // Called when agent observes something
925
+ answer, // Called when agent provides answer
926
+ error) {
927
+ // Create a receiver function to handle streaming responses
928
+ const receiver = (response) => {
929
+ console.log("Agent response received:", response);
930
+ const resp = response;
931
+ // Check for backend errors
932
+ if (resp.error) {
933
+ const errorObj = resp.error;
934
+ const errorMessage = (typeof errorObj.message === "string" ? errorObj.message : null) ||
935
+ "Unknown agent error";
936
+ error(`Agent error: ${errorMessage}`);
937
+ return true; // End streaming on error
938
+ }
939
+ // Handle different response types
940
+ if (typeof resp.thought === "string")
941
+ think(resp.thought);
942
+ if (typeof resp.observation === "string")
943
+ observe(resp.observation);
944
+ if (typeof resp.answer === "string") {
945
+ answer(resp.answer);
946
+ return true; // End streaming when final answer is received
947
+ }
948
+ return false; // Continue streaming
949
+ };
950
+ // Use the existing makeRequestMulti infrastructure
951
+ return this.api
952
+ .makeRequestMulti("agent", {
953
+ question: question,
954
+ user: this.api.user,
955
+ }, receiver, 120000, // 120 second timeout
956
+ 2, // 2 retries
957
+ this.flowId)
958
+ .catch((err) => {
959
+ // Handle any errors from makeRequestMulti
960
+ const errorMessage = err instanceof Error
961
+ ? err.message
962
+ : err?.toString() || "Unknown error";
963
+ error(`Agent request failed: ${errorMessage}`);
964
+ });
965
+ }
966
+ /**
967
+ * Generates embeddings for text within this flow
968
+ */
969
+ embeddings(text) {
970
+ return this.api
971
+ .makeRequest("embeddings", {
972
+ text: text,
973
+ }, 30000, undefined, this.flowId)
974
+ .then((r) => r.vectors);
975
+ }
976
+ /**
977
+ * Queries the knowledge graph using embedding vectors
978
+ */
979
+ graphEmbeddingsQuery(vecs, limit, collection) {
980
+ return this.api
981
+ .makeRequest("graph-embeddings", {
982
+ vectors: vecs,
983
+ limit: limit ? limit : 20, // Default to 20 results
984
+ user: this.api.user,
985
+ collection: collection || "default",
986
+ }, 30000, undefined, this.flowId)
987
+ .then((r) => r.entities);
988
+ }
989
+ /**
990
+ * Queries knowledge graph triples (subject-predicate-object relationships)
991
+ * All parameters are optional - omitted parameters act as wildcards
992
+ */
993
+ triplesQuery(s, p, o, limit, collection) {
994
+ return this.api
995
+ .makeRequest("triples", {
996
+ s: s, // Subject
997
+ p: p, // Predicate
998
+ o: o, // Object
999
+ limit: limit ? limit : 20,
1000
+ user: this.api.user,
1001
+ collection: collection || "default",
1002
+ }, 30000, undefined, this.flowId)
1003
+ .then((r) => r.response);
1004
+ }
1005
+ /**
1006
+ * Loads a document into this flow for processing
1007
+ */
1008
+ loadDocument(document, // base64-encoded document
1009
+ id, metadata) {
1010
+ return this.api.makeRequest("document-load", {
1011
+ id: id,
1012
+ metadata: metadata,
1013
+ data: document,
1014
+ }, 30000, undefined, this.flowId);
1015
+ }
1016
+ /**
1017
+ * Loads plain text into this flow for processing
1018
+ */
1019
+ loadText(text, // Text content
1020
+ id, metadata, charset) {
1021
+ return this.api.makeRequest("text-load", {
1022
+ id: id,
1023
+ metadata: metadata,
1024
+ text: text,
1025
+ charset: charset,
1026
+ }, 30000, undefined, this.flowId);
1027
+ }
1028
+ /**
1029
+ * Executes a GraphQL query against structured data objects
1030
+ */
1031
+ objectsQuery(query, collection, variables, operationName) {
1032
+ return this.api
1033
+ .makeRequest("objects", {
1034
+ query: query,
1035
+ user: this.api.user,
1036
+ collection: collection || "default",
1037
+ variables: variables,
1038
+ operation_name: operationName,
1039
+ }, 30000, undefined, this.flowId)
1040
+ .then((r) => {
1041
+ // Return the GraphQL response structure directly
1042
+ const result = {};
1043
+ if (r.data !== undefined)
1044
+ result.data = r.data;
1045
+ if (r.errors)
1046
+ result.errors = r.errors;
1047
+ if (r.extensions)
1048
+ result.extensions = r.extensions;
1049
+ return result;
1050
+ });
1051
+ }
1052
+ /**
1053
+ * Converts a natural language question to a GraphQL query
1054
+ */
1055
+ nlpQuery(question, maxResults) {
1056
+ return this.api
1057
+ .makeRequest("nlp-query", {
1058
+ question: question,
1059
+ max_results: maxResults || 100,
1060
+ }, 30000, undefined, this.flowId)
1061
+ .then((r) => r);
1062
+ }
1063
+ /**
1064
+ * Executes a natural language question against structured data
1065
+ * Combines NLP query conversion and GraphQL execution
1066
+ */
1067
+ structuredQuery(question, collection) {
1068
+ return this.api
1069
+ .makeRequest("structured-query", {
1070
+ question: question,
1071
+ user: this.api.user,
1072
+ collection: collection || "default",
1073
+ }, 30000, undefined, this.flowId)
1074
+ .then((r) => {
1075
+ // Return the response structure directly
1076
+ const result = {};
1077
+ if (r.data !== undefined)
1078
+ result.data = r.data;
1079
+ if (r.errors)
1080
+ result.errors = r.errors;
1081
+ return result;
1082
+ });
1083
+ }
1084
+ }
1085
+ /**
1086
+ * ConfigApi - Dedicated configuration management interface
1087
+ * Handles system configuration, prompts, and token cost tracking
1088
+ */
1089
+ class ConfigApi {
1090
+ constructor(api) {
1091
+ this.api = api;
1092
+ }
1093
+ /**
1094
+ * Retrieves complete configuration
1095
+ */
1096
+ getConfigAll() {
1097
+ return this.api.makeRequest("config", {
1098
+ operation: "config",
1099
+ }, 60000);
1100
+ }
1101
+ /**
1102
+ * Retrieves specific configuration entries
1103
+ */
1104
+ getConfig(keys) {
1105
+ return this.api.makeRequest("config", {
1106
+ operation: "get",
1107
+ keys: keys,
1108
+ }, 60000);
1109
+ }
1110
+ /**
1111
+ * Updates configuration values
1112
+ */
1113
+ putConfig(values) {
1114
+ return this.api.makeRequest("config", {
1115
+ operation: "put",
1116
+ values: values,
1117
+ }, 60000);
1118
+ }
1119
+ /**
1120
+ * Deletes configuration entries
1121
+ */
1122
+ deleteConfig(keys) {
1123
+ return this.api.makeRequest("config", {
1124
+ operation: "delete",
1125
+ keys: keys,
1126
+ }, 30000);
1127
+ }
1128
+ // Specialized prompt management methods
1129
+ /**
1130
+ * Retrieves available prompt templates
1131
+ */
1132
+ getPrompts() {
1133
+ return this.getConfigAll().then((r) => {
1134
+ const config = r;
1135
+ return JSON.parse(config.config.prompt["template-index"]);
1136
+ });
1137
+ }
1138
+ /**
1139
+ * Retrieves a specific prompt template
1140
+ */
1141
+ getPrompt(id) {
1142
+ return this.getConfigAll().then((r) => {
1143
+ const config = r;
1144
+ return JSON.parse(config.config.prompt[`template.${id}`]);
1145
+ });
1146
+ }
1147
+ /**
1148
+ * Retrieves system prompt configuration
1149
+ */
1150
+ getSystemPrompt() {
1151
+ return this.getConfigAll().then((r) => {
1152
+ const config = r;
1153
+ return JSON.parse(config.config.prompt.system);
1154
+ });
1155
+ }
1156
+ /**
1157
+ * Lists available configuration types
1158
+ */
1159
+ list(type) {
1160
+ return this.api
1161
+ .makeRequest("config", {
1162
+ operation: "list",
1163
+ type: type,
1164
+ }, 60000)
1165
+ .then((r) => r);
1166
+ }
1167
+ /**
1168
+ * Retrieves all key/values for a specific type
1169
+ */
1170
+ getValues(type) {
1171
+ return this.api
1172
+ .makeRequest("config", {
1173
+ operation: "getvalues",
1174
+ type: type,
1175
+ }, 60000)
1176
+ .then((r) => r.values);
1177
+ }
1178
+ /**
1179
+ * Retrieves token cost information for different AI models
1180
+ * Useful for cost tracking and optimization
1181
+ */
1182
+ getTokenCosts() {
1183
+ return this.api
1184
+ .makeRequest("config", {
1185
+ operation: "getvalues",
1186
+ type: "token-costs",
1187
+ }, 60000)
1188
+ .then((r) => {
1189
+ // Parse JSON values and restructure data
1190
+ const response = r;
1191
+ return (response.values || []).map((x) => {
1192
+ const item = x;
1193
+ return { key: item.key, value: JSON.parse(item.value) };
1194
+ });
1195
+ })
1196
+ .then((r) =>
1197
+ // Transform to more usable format
1198
+ r.map((x) => {
1199
+ const item = x;
1200
+ const value = item.value;
1201
+ return {
1202
+ model: item.key,
1203
+ input_price: value.input_price, // Cost per input token
1204
+ output_price: value.output_price, // Cost per output token
1205
+ };
1206
+ }));
1207
+ }
1208
+ }
1209
+ /**
1210
+ * KnowledgeApi - Manages knowledge graph cores and data
1211
+ * Knowledge cores appear to be collections of processed knowledge graph data
1212
+ */
1213
+ class KnowledgeApi {
1214
+ constructor(api) {
1215
+ this.api = api;
1216
+ }
1217
+ /**
1218
+ * Retrieves list of available knowledge graph cores
1219
+ */
1220
+ getKnowledgeCores() {
1221
+ return this.api
1222
+ .makeRequest("knowledge", {
1223
+ operation: "list-kg-cores",
1224
+ user: this.api.user,
1225
+ }, 60000)
1226
+ .then((r) => r.ids || []);
1227
+ }
1228
+ /**
1229
+ * Deletes a knowledge graph core
1230
+ */
1231
+ deleteKgCore(id, collection) {
1232
+ return this.api.makeRequest("knowledge", {
1233
+ operation: "delete-kg-core",
1234
+ id: id,
1235
+ user: this.api.user,
1236
+ collection: collection || "default",
1237
+ }, 30000);
1238
+ }
1239
+ /**
1240
+ * Deletes a knowledge graph core
1241
+ */
1242
+ loadKgCore(id, flow, collection) {
1243
+ return this.api.makeRequest("knowledge", {
1244
+ operation: "load-kg-core",
1245
+ id: id,
1246
+ flow: flow,
1247
+ user: this.api.user,
1248
+ collection: collection || "default",
1249
+ }, 30000);
1250
+ }
1251
+ /**
1252
+ * Retrieves a knowledge graph core with streaming data
1253
+ * Uses multi-request pattern for large datasets
1254
+ * @param receiver - Callback function to handle streaming data chunks
1255
+ */
1256
+ getKgCore(id, collection, receiver) {
1257
+ // Wrapper to handle end-of-stream detection
1258
+ const recv = (msg) => {
1259
+ const response = msg;
1260
+ if (response.eos) {
1261
+ // End of stream - notify receiver and signal completion
1262
+ receiver(msg, true);
1263
+ return true;
1264
+ }
1265
+ else {
1266
+ // Regular message - continue streaming
1267
+ receiver(msg, false);
1268
+ return false;
1269
+ }
1270
+ };
1271
+ return this.api.makeRequestMulti("knowledge", {
1272
+ operation: "get-kg-core",
1273
+ id: id,
1274
+ user: this.api.user,
1275
+ collection: collection || "default",
1276
+ }, recv, // Stream handler
1277
+ 30000);
1278
+ }
1279
+ }
1280
+ /**
1281
+ * CollectionManagementApi - Manages collections for organizing documents
1282
+ * Provides operations for listing, creating, updating, and deleting collections
1283
+ */
1284
+ class CollectionManagementApi {
1285
+ constructor(api) {
1286
+ this.api = api;
1287
+ }
1288
+ /**
1289
+ * Lists all collections for the current user with optional tag filtering
1290
+ * @param tagFilter - Optional array of tags to filter collections
1291
+ * @returns Promise resolving to array of collection metadata
1292
+ */
1293
+ listCollections(tagFilter) {
1294
+ const request = {
1295
+ operation: "list-collections",
1296
+ user: this.api.user,
1297
+ };
1298
+ if (tagFilter && tagFilter.length > 0) {
1299
+ request.tag_filter = tagFilter;
1300
+ }
1301
+ return this.api
1302
+ .makeRequest("collection-management", request, 30000)
1303
+ .then((r) => r.collections || []);
1304
+ }
1305
+ /**
1306
+ * Creates or updates a collection for the current user
1307
+ * @param collection - Collection ID (unique identifier)
1308
+ * @param name - Display name for the collection
1309
+ * @param description - Description of the collection
1310
+ * @param tags - Array of tags for categorization
1311
+ * @returns Promise resolving to updated collection metadata
1312
+ */
1313
+ updateCollection(collection, name, description, tags) {
1314
+ const request = {
1315
+ operation: "update-collection",
1316
+ user: this.api.user,
1317
+ collection,
1318
+ };
1319
+ if (name !== undefined) {
1320
+ request.name = name;
1321
+ }
1322
+ if (description !== undefined) {
1323
+ request.description = description;
1324
+ }
1325
+ if (tags !== undefined) {
1326
+ request.tags = tags;
1327
+ }
1328
+ return this.api
1329
+ .makeRequest("collection-management", request, 30000)
1330
+ .then((r) => {
1331
+ if (r.collections &&
1332
+ Array.isArray(r.collections) &&
1333
+ r.collections.length > 0) {
1334
+ return r.collections[0];
1335
+ }
1336
+ throw new Error("Failed to update collection");
1337
+ });
1338
+ }
1339
+ /**
1340
+ * Deletes a collection and all its data for the current user
1341
+ * @param collection - Collection ID to delete
1342
+ * @returns Promise resolving when deletion is complete
1343
+ */
1344
+ deleteCollection(collection) {
1345
+ return this.api.makeRequest("collection-management", {
1346
+ operation: "delete-collection",
1347
+ user: this.api.user,
1348
+ collection,
1349
+ }, 30000);
1350
+ }
1351
+ }
1352
+ /**
1353
+ * Factory function to create a new TrustGraph WebSocket connection
1354
+ * This is the main entry point for using the TrustGraph API
1355
+ * @param user - User identifier for API requests
1356
+ * @param token - Optional authentication token for secure connections
1357
+ */
1358
+ const createTrustGraphSocket = (user, token) => {
1359
+ return new BaseApi(user, token);
1360
+ };
1361
+
1362
+ exports.BaseApi = BaseApi;
1363
+ exports.CollectionManagementApi = CollectionManagementApi;
1364
+ exports.ConfigApi = ConfigApi;
1365
+ exports.FlowApi = FlowApi;
1366
+ exports.FlowsApi = FlowsApi;
1367
+ exports.KnowledgeApi = KnowledgeApi;
1368
+ exports.LibrarianApi = LibrarianApi;
1369
+ exports.createTrustGraphSocket = createTrustGraphSocket;
1370
+ //# sourceMappingURL=index.cjs.map