@nebula-ai/sdk 0.0.27 → 0.0.29

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.js CHANGED
@@ -41,10 +41,16 @@ var NebulaValidationException = class extends NebulaException {
41
41
  this.name = "NebulaValidationException";
42
42
  }
43
43
  };
44
- var NebulaClusterNotFoundException = class extends NebulaException {
45
- constructor(message = "Cluster not found") {
44
+ var NebulaCollectionNotFoundException = class extends NebulaException {
45
+ constructor(message = "Collection not found") {
46
46
  super(message, 404);
47
- this.name = "NebulaClusterNotFoundException";
47
+ this.name = "NebulaCollectionNotFoundException";
48
+ }
49
+ };
50
+ var NebulaNotFoundException = class extends NebulaException {
51
+ constructor(resourceId, resourceType = "Resource") {
52
+ super(`${resourceType} not found: ${resourceId}`, 404);
53
+ this.name = "NebulaNotFoundException";
48
54
  }
49
55
  };
50
56
 
@@ -137,6 +143,17 @@ var NebulaClient = class {
137
143
  } else if (response.status === 400) {
138
144
  const errorData = await response.json().catch(() => ({}));
139
145
  throw new NebulaValidationException(errorData.message || "Validation error", errorData.details);
146
+ } else if (response.status === 422) {
147
+ const errorData = await response.json().catch(() => ({}));
148
+ console.error("[SDK] 422 Validation error - Full details:");
149
+ console.error(" Status:", response.status);
150
+ console.error(" Error data:", JSON.stringify(errorData, null, 2));
151
+ console.error(" Message:", errorData.message);
152
+ console.error(" Detail:", errorData.detail);
153
+ throw new NebulaValidationException(
154
+ errorData.message || (typeof errorData.detail === "string" ? errorData.detail : JSON.stringify(errorData.detail)) || "Validation error",
155
+ errorData
156
+ );
140
157
  } else {
141
158
  const errorData = await response.json().catch(() => ({}));
142
159
  throw new NebulaException(errorData.message || `API error: ${response.status}`, response.status, errorData);
@@ -155,54 +172,85 @@ var NebulaClient = class {
155
172
  throw new NebulaClientException(`Request failed: ${String(error)}`);
156
173
  }
157
174
  }
158
- // Cluster Management Methods
159
- /** Create a new cluster */
160
- async createCluster(options) {
175
+ // Collection Management Methods
176
+ /** Create a new collection */
177
+ async createCollection(options) {
161
178
  const data = { name: options.name };
162
179
  if (options.description) data.description = options.description;
163
180
  if (options.metadata) data.metadata = options.metadata;
164
181
  const response = await this._makeRequest("POST", "/v1/collections", data);
165
182
  const result = response.results || response;
166
- return this._clusterFromDict(result);
183
+ return this._collectionFromDict(result);
167
184
  }
168
- /** Get a specific cluster by ID */
169
- async getCluster(clusterId) {
170
- const response = await this._makeRequest("GET", `/v1/collections/${clusterId}`);
185
+ /** Get a specific collection by ID */
186
+ async getCollection(collectionId) {
187
+ const response = await this._makeRequest("GET", `/v1/collections/${collectionId}`);
171
188
  const result = response.results || response;
172
- return this._clusterFromDict(result);
189
+ return this._collectionFromDict(result);
173
190
  }
174
- /** Get a specific cluster by name */
175
- async getClusterByName(name) {
191
+ /** Get a specific collection by name */
192
+ async getCollectionByName(name) {
176
193
  const response = await this._makeRequest("GET", `/v1/collections/name/${name}`);
177
194
  const result = response.results || response;
178
- return this._clusterFromDict(result);
195
+ return this._collectionFromDict(result);
179
196
  }
180
- /** Get all clusters */
181
- async listClusters(options) {
197
+ /** Get all collections */
198
+ async listCollections(options) {
182
199
  const params = {
183
200
  limit: options?.limit ?? 100,
184
201
  offset: options?.offset ?? 0
185
202
  };
186
203
  const response = await this._makeRequest("GET", "/v1/collections", void 0, params);
187
- let clusters;
204
+ let collections;
188
205
  if (response.results) {
189
- clusters = response.results;
206
+ collections = response.results;
190
207
  } else if (Array.isArray(response)) {
191
- clusters = response;
208
+ collections = response;
192
209
  } else {
193
- clusters = [response];
210
+ collections = [response];
194
211
  }
195
- return clusters.map((cluster) => this._clusterFromDict(cluster));
212
+ return collections.map((collection) => this._collectionFromDict(collection));
196
213
  }
197
214
  // Conversations Methods
198
- /** List conversations for the authenticated user */
215
+ /**
216
+ * List conversations for the authenticated user with optional metadata filtering
217
+ *
218
+ * @param options - Configuration for listing conversations
219
+ * @param options.limit - Maximum number of conversations to return (default: 100)
220
+ * @param options.offset - Number of conversations to skip for pagination (default: 0)
221
+ * @param options.collection_ids - Optional list of collection IDs to filter conversations by
222
+ * @param options.metadata_filters - Optional metadata filters using MongoDB-like operators.
223
+ * Supported operators: $eq, $ne, $in, $nin, $exists, $and, $or
224
+ *
225
+ * @returns Promise resolving to array of conversation objects with fields: id, created_at, user_id, name, collection_ids
226
+ *
227
+ * @example
228
+ * // Get all playground conversations
229
+ * const conversations = await client.listConversations({
230
+ * collection_ids: ['collection-id'],
231
+ * metadata_filters: {
232
+ * 'metadata.playground': { $eq: true }
233
+ * }
234
+ * });
235
+ *
236
+ * @example
237
+ * // Filter by session ID
238
+ * const conversations = await client.listConversations({
239
+ * metadata_filters: {
240
+ * 'metadata.session_id': { $eq: 'session-123' }
241
+ * }
242
+ * });
243
+ */
199
244
  async listConversations(options) {
200
245
  const params = {
201
246
  limit: options?.limit ?? 100,
202
247
  offset: options?.offset ?? 0
203
248
  };
204
- if (options?.cluster_ids && options.cluster_ids.length > 0) {
205
- params.collection_ids = options.cluster_ids;
249
+ if (options?.collection_ids && options.collection_ids.length > 0) {
250
+ params.collection_ids = options.collection_ids;
251
+ }
252
+ if (options?.metadata_filters) {
253
+ params.metadata_filters = JSON.stringify(options.metadata_filters);
206
254
  }
207
255
  const response = await this._makeRequest("GET", "/v1/conversations", void 0, params);
208
256
  let conversations;
@@ -283,30 +331,30 @@ var NebulaClient = class {
283
331
  content: text,
284
332
  metadata: combinedMetadata,
285
333
  created_at: msgResp.created_at,
286
- cluster_ids: msgResp.collection_ids || []
334
+ collection_ids: msgResp.collection_ids || []
287
335
  };
288
336
  });
289
337
  }
290
- /** Update a cluster */
291
- async updateCluster(options) {
338
+ /** Update a collection */
339
+ async updateCollection(options) {
292
340
  const data = {};
293
341
  if (options.name !== void 0) data.name = options.name;
294
342
  if (options.description !== void 0) data.description = options.description;
295
343
  if (options.metadata !== void 0) data.metadata = options.metadata;
296
- const response = await this._makeRequest("POST", `/v1/collections/${options.clusterId}`, data);
344
+ const response = await this._makeRequest("POST", `/v1/collections/${options.collectionId}`, data);
297
345
  const result = response.results || response;
298
- return this._clusterFromDict(result);
346
+ return this._collectionFromDict(result);
299
347
  }
300
- /** Delete a cluster */
301
- async deleteCluster(clusterId) {
302
- await this._makeRequest("DELETE", `/v1/collections/${clusterId}`);
348
+ /** Delete a collection */
349
+ async deleteCollection(collectionId) {
350
+ await this._makeRequest("DELETE", `/v1/collections/${collectionId}`);
303
351
  return true;
304
352
  }
305
353
  // Memory Management Methods
306
354
  /**
307
- * Legacy convenience: store raw text content into a cluster as a document
355
+ * Legacy convenience: store raw text content into a collection as a document
308
356
  */
309
- async store(content, clusterId, metadata = {}) {
357
+ async store(content, collectionId, metadata = {}) {
310
358
  const docMetadata = {
311
359
  ...metadata,
312
360
  memory_type: "memory",
@@ -315,10 +363,10 @@ var NebulaClient = class {
315
363
  const data = {
316
364
  metadata: JSON.stringify(docMetadata),
317
365
  ingestion_mode: "fast",
318
- collection_ids: JSON.stringify([clusterId]),
366
+ collection_ids: JSON.stringify([collectionId]),
319
367
  raw_text: String(content || "")
320
368
  };
321
- const url = `${this.baseUrl}/v1/documents`;
369
+ const url = `${this.baseUrl}/v1/memories`;
322
370
  const headers = this._buildAuthHeaders(false);
323
371
  const response = await fetch(url, {
324
372
  method: "POST",
@@ -328,72 +376,117 @@ var NebulaClient = class {
328
376
  if (!response.ok) {
329
377
  const errorData = await response.json().catch(() => ({}));
330
378
  throw new NebulaException(
331
- errorData.message || `Failed to create document: ${response.status}`,
379
+ errorData.message || `Failed to create engram: ${response.status}`,
332
380
  response.status,
333
381
  errorData
334
382
  );
335
383
  }
336
384
  const respData = await response.json();
337
- const id = respData?.results?.document_id || respData?.results?.id || respData?.id || "";
385
+ const id = respData?.results?.engram_id || respData?.results?.id || respData?.id || "";
338
386
  const result = {
339
387
  id: String(id),
340
388
  content: String(content || ""),
341
389
  metadata: docMetadata,
342
- cluster_ids: [clusterId],
390
+ collection_ids: [collectionId],
343
391
  created_at: docMetadata.timestamp,
344
392
  updated_at: docMetadata.timestamp
345
393
  };
346
394
  return result;
347
395
  }
348
- /** Store a single memory */
349
- async storeMemory(memory) {
396
+ /**
397
+ * Store a single memory using the unified engrams API.
398
+ *
399
+ * Automatically infers memory type:
400
+ * - If role is present, creates a conversation
401
+ * - Otherwise, creates a document
402
+ */
403
+ async storeMemory(memory, name) {
350
404
  let mem;
351
- if ("cluster_id" in memory) {
405
+ if ("collection_id" in memory) {
352
406
  mem = memory;
353
407
  } else {
354
408
  mem = {
355
- cluster_id: memory.cluster_id,
356
- content: memory.content,
409
+ collection_id: memory.collection_id,
410
+ content: memory.content || "",
357
411
  role: memory.role,
358
- parent_id: memory.parent_id,
412
+ memory_id: memory.memory_id,
359
413
  metadata: memory.metadata || {}
360
414
  };
361
415
  }
362
- if (mem.role) {
363
- let convId = mem.parent_id;
364
- if (!convId) {
365
- const created = await this._makeRequest("POST", "/v1/conversations", {});
366
- const conv = created.results || created;
367
- convId = conv.id;
416
+ if (mem.memory_id) {
417
+ return await this._appendToMemory(mem.memory_id, mem);
418
+ }
419
+ const memoryType = mem.role ? "conversation" : "document";
420
+ if (memoryType === "conversation") {
421
+ const docMetadata2 = { ...mem.metadata };
422
+ const data2 = {
423
+ engram_type: "conversation",
424
+ name: name || "Conversation",
425
+ metadata: JSON.stringify(docMetadata2),
426
+ collection_ids: JSON.stringify([mem.collection_id])
427
+ };
428
+ const url2 = `${this.baseUrl}/v1/memories`;
429
+ const headers2 = this._buildAuthHeaders(false);
430
+ const response2 = await fetch(url2, {
431
+ method: "POST",
432
+ headers: headers2,
433
+ body: this._formDataFromObject(data2)
434
+ });
435
+ if (!response2.ok) {
436
+ const errorData = await response2.json().catch(() => ({}));
437
+ throw new NebulaException(
438
+ errorData.message || `Failed to create conversation: ${response2.status}`,
439
+ response2.status,
440
+ errorData
441
+ );
442
+ }
443
+ const respData2 = await response2.json();
444
+ if (respData2.results) {
445
+ const convId = respData2.results.engram_id || respData2.results.id;
368
446
  if (!convId) {
369
447
  throw new NebulaClientException("Failed to create conversation: no id returned");
370
448
  }
449
+ if (mem.content && mem.role) {
450
+ const appendMem = {
451
+ collection_id: mem.collection_id,
452
+ content: [
453
+ {
454
+ content: String(mem.content),
455
+ role: mem.role,
456
+ metadata: mem.metadata,
457
+ ...typeof mem.authority === "number" ? { authority: Number(mem.authority) } : {}
458
+ }
459
+ ],
460
+ memory_id: convId,
461
+ metadata: {}
462
+ };
463
+ await this._appendToMemory(convId, appendMem);
464
+ }
465
+ return String(convId);
371
466
  }
372
- const payload = {
373
- messages: [
374
- {
375
- content: String(mem.content),
376
- role: mem.role,
377
- metadata: mem.metadata
378
- }
379
- ],
380
- collection_id: mem.cluster_id
381
- };
382
- await this._makeRequest("POST", `/v1/conversations/${convId}/messages`, payload);
383
- return String(convId);
467
+ throw new NebulaClientException("Failed to create conversation: invalid response format");
384
468
  }
385
469
  const contentText = String(mem.content || "");
470
+ if (!contentText) {
471
+ throw new NebulaClientException("Content is required for document memories");
472
+ }
386
473
  const contentHash = await this._sha256(contentText);
387
474
  const docMetadata = { ...mem.metadata };
388
475
  docMetadata.memory_type = "memory";
389
476
  docMetadata.content_hash = contentHash;
477
+ if (typeof mem.authority === "number") {
478
+ const v = Number(mem.authority);
479
+ if (!Number.isNaN(v) && v >= 0 && v <= 1) {
480
+ docMetadata.authority = v;
481
+ }
482
+ }
390
483
  const data = {
391
484
  metadata: JSON.stringify(docMetadata),
392
485
  ingestion_mode: "fast",
393
- collection_ids: JSON.stringify([mem.cluster_id]),
486
+ collection_ids: JSON.stringify([mem.collection_id]),
394
487
  raw_text: contentText
395
488
  };
396
- const url = `${this.baseUrl}/v1/documents`;
489
+ const url = `${this.baseUrl}/v1/memories`;
397
490
  const headers = this._buildAuthHeaders(false);
398
491
  const response = await fetch(url, {
399
492
  method: "POST",
@@ -403,26 +496,67 @@ var NebulaClient = class {
403
496
  if (!response.ok) {
404
497
  const errorData = await response.json().catch(() => ({}));
405
498
  throw new NebulaException(
406
- errorData.message || `Failed to create document: ${response.status}`,
499
+ errorData.message || `Failed to create engram: ${response.status}`,
407
500
  response.status,
408
501
  errorData
409
502
  );
410
503
  }
411
504
  const respData = await response.json();
412
505
  if (respData.results) {
413
- if (respData.results.document_id) return String(respData.results.document_id);
506
+ if (respData.results.engram_id) return String(respData.results.engram_id);
414
507
  if (respData.results.id) return String(respData.results.id);
415
508
  }
416
509
  return "";
417
510
  }
418
- /** Store multiple memories */
511
+ /**
512
+ * Internal method to append content to an existing engram
513
+ *
514
+ * @throws NebulaNotFoundException if engram_id doesn't exist
515
+ */
516
+ async _appendToMemory(memoryId, memory) {
517
+ const collectionId = memory.collection_id;
518
+ const content = memory.content;
519
+ const metadata = memory.metadata;
520
+ if (!collectionId) {
521
+ throw new NebulaClientException("collection_id is required");
522
+ }
523
+ const payload = {
524
+ collection_id: collectionId
525
+ };
526
+ if (Array.isArray(content)) {
527
+ if (content.length > 0 && typeof content[0] === "object" && "content" in content[0]) {
528
+ payload.messages = content;
529
+ } else {
530
+ payload.chunks = content;
531
+ }
532
+ } else if (typeof content === "string") {
533
+ payload.raw_text = content;
534
+ } else {
535
+ throw new NebulaClientException(
536
+ "content must be a string, array of strings, or array of message objects"
537
+ );
538
+ }
539
+ if (metadata) {
540
+ payload.metadata = metadata;
541
+ }
542
+ try {
543
+ await this._makeRequest("POST", `/v1/memories/${memoryId}/append`, payload);
544
+ return memoryId;
545
+ } catch (error) {
546
+ if (error instanceof NebulaException && error.statusCode === 404) {
547
+ throw new NebulaNotFoundException(memoryId, "Memory");
548
+ }
549
+ throw error;
550
+ }
551
+ }
552
+ /** Store multiple memories using the unified engrams API */
419
553
  async storeMemories(memories) {
420
554
  const results = [];
421
555
  const convGroups = {};
422
556
  const others = [];
423
557
  for (const m of memories) {
424
558
  if (m.role) {
425
- const key = m.parent_id || `__new__::${m.cluster_id}`;
559
+ const key = m.memory_id || `__new__::${m.collection_id}`;
426
560
  if (!convGroups[key]) convGroups[key] = [];
427
561
  convGroups[key].push(m);
428
562
  } else {
@@ -430,15 +564,19 @@ var NebulaClient = class {
430
564
  }
431
565
  }
432
566
  for (const [key, group] of Object.entries(convGroups)) {
433
- const clusterId = group[0].cluster_id;
567
+ const collectionId = group[0].collection_id;
434
568
  let convId;
435
569
  if (key.startsWith("__new__::")) {
436
- const created = await this._makeRequest("POST", "/v1/conversations", {});
437
- const conv = created.results || created;
438
- convId = conv.id;
439
- if (!convId) {
440
- throw new NebulaClientException("Failed to create conversation: no id returned");
441
- }
570
+ convId = await this.storeMemory(
571
+ {
572
+ collection_id: collectionId,
573
+ content: "",
574
+ role: "assistant",
575
+ // Placeholder role to infer conversation type
576
+ metadata: {}
577
+ },
578
+ "Conversation"
579
+ );
442
580
  } else {
443
581
  convId = key;
444
582
  }
@@ -447,8 +585,13 @@ var NebulaClient = class {
447
585
  role: m.role,
448
586
  metadata: m.metadata || {}
449
587
  }));
450
- const payload = { messages, collection_id: clusterId };
451
- await this._makeRequest("POST", `/v1/conversations/${convId}/messages`, payload);
588
+ const appendMem = {
589
+ collection_id: collectionId,
590
+ content: messages,
591
+ memory_id: convId,
592
+ metadata: {}
593
+ };
594
+ await this._appendToMemory(convId, appendMem);
452
595
  results.push(...Array(group.length).fill(String(convId)));
453
596
  }
454
597
  for (const m of others) {
@@ -459,33 +602,113 @@ var NebulaClient = class {
459
602
  /** Delete one or more memories */
460
603
  async delete(memoryIds) {
461
604
  try {
605
+ console.log("[SDK] delete() called with:", { memoryIds, type: typeof memoryIds, isArray: Array.isArray(memoryIds) });
462
606
  if (typeof memoryIds === "string") {
607
+ console.log("[SDK] Single deletion path for ID:", memoryIds);
463
608
  try {
464
- await this._makeRequest("DELETE", `/v1/documents/${memoryIds}`);
609
+ await this._makeRequest("DELETE", `/v1/memories/${memoryIds}`);
465
610
  return true;
466
611
  } catch {
467
612
  try {
468
- const response = await this._makeRequest("POST", "/v1/documents/delete", {
469
- ids: memoryIds
470
- });
613
+ console.log("[SDK] Falling back to POST /v1/memories/delete with single ID");
614
+ const response = await this._makeRequest("POST", "/v1/memories/delete", memoryIds);
471
615
  return typeof response === "object" && response.success !== void 0 ? response.success : true;
472
616
  } catch (error) {
473
617
  throw error;
474
618
  }
475
619
  }
476
620
  } else {
477
- const response = await this._makeRequest("POST", "/v1/documents/delete", {
478
- ids: memoryIds
479
- });
621
+ console.log("[SDK] Batch deletion path for IDs:", memoryIds);
622
+ console.log("[SDK] Sending POST request with body:", memoryIds);
623
+ const response = await this._makeRequest("POST", "/v1/memories/delete", memoryIds);
624
+ console.log("[SDK] Batch deletion response:", response);
480
625
  return response;
481
626
  }
482
627
  } catch (error) {
628
+ console.error("[SDK] Delete error:", error);
483
629
  if (error instanceof Error) {
484
630
  throw error;
485
631
  }
486
632
  throw new NebulaClientException(`Unknown error: ${String(error)}`);
487
633
  }
488
634
  }
635
+ /** Delete a specific chunk or message within a memory */
636
+ async deleteChunk(chunkId) {
637
+ try {
638
+ await this._makeRequest("DELETE", `/v1/chunks/${chunkId}`);
639
+ return true;
640
+ } catch (error) {
641
+ if (error instanceof NebulaException && error.statusCode === 404) {
642
+ throw new NebulaNotFoundException(chunkId, "Chunk");
643
+ }
644
+ throw error;
645
+ }
646
+ }
647
+ /** Update a specific chunk or message within a memory */
648
+ async updateChunk(chunkId, content, metadata) {
649
+ const payload = { content };
650
+ if (metadata !== void 0) {
651
+ payload.metadata = metadata;
652
+ }
653
+ try {
654
+ await this._makeRequest("PATCH", `/v1/chunks/${chunkId}`, payload);
655
+ return true;
656
+ } catch (error) {
657
+ if (error instanceof NebulaException && error.statusCode === 404) {
658
+ throw new NebulaNotFoundException(chunkId, "Chunk");
659
+ }
660
+ throw error;
661
+ }
662
+ }
663
+ /**
664
+ * Update memory-level properties including name, metadata, and collection associations.
665
+ *
666
+ * This method allows updating properties of an entire memory (document or conversation)
667
+ * without modifying its content. For updating individual chunks or messages within a memory,
668
+ * use updateChunk(). For updating content, use storeMemory() to append.
669
+ *
670
+ * @param options - Update configuration
671
+ * @param options.memoryId - The ID of the memory to update
672
+ * @param options.name - New name for the memory (useful for conversations and documents)
673
+ * @param options.metadata - Metadata to set. By default, replaces existing metadata.
674
+ * Set mergeMetadata=true to merge with existing metadata instead.
675
+ * @param options.collectionIds - New collection associations. Must specify at least one valid collection.
676
+ * @param options.mergeMetadata - If true, merges provided metadata with existing metadata.
677
+ * If false (default), replaces existing metadata entirely.
678
+ *
679
+ * @returns Promise resolving to true if successful
680
+ *
681
+ * @throws NebulaNotFoundException if memory_id doesn't exist
682
+ * @throws NebulaValidationException if validation fails (e.g., no fields provided)
683
+ * @throws NebulaAuthenticationException if user doesn't have permission to update this memory
684
+ */
685
+ async updateMemory(options) {
686
+ const payload = {};
687
+ if (options.name !== void 0) {
688
+ payload.name = options.name;
689
+ }
690
+ if (options.metadata !== void 0) {
691
+ payload.metadata = options.metadata;
692
+ payload.merge_metadata = options.mergeMetadata ?? false;
693
+ }
694
+ if (options.collectionIds !== void 0) {
695
+ payload.collection_ids = options.collectionIds;
696
+ }
697
+ if (Object.keys(payload).length === 0) {
698
+ throw new NebulaValidationException(
699
+ "At least one field (name, metadata, or collectionIds) must be provided to update"
700
+ );
701
+ }
702
+ try {
703
+ await this._makeRequest("PATCH", `/v1/memories/${options.memoryId}`, payload);
704
+ return true;
705
+ } catch (error) {
706
+ if (error instanceof NebulaException && error.statusCode === 404) {
707
+ throw new NebulaNotFoundException(options.memoryId, "Memory");
708
+ }
709
+ throw error;
710
+ }
711
+ }
489
712
  /** Delete a conversation and all its messages */
490
713
  async deleteConversation(conversationId) {
491
714
  try {
@@ -498,18 +721,53 @@ var NebulaClient = class {
498
721
  throw new NebulaClientException(`Unknown error: ${String(error)}`);
499
722
  }
500
723
  }
501
- /** Get all memories from specific clusters */
724
+ /**
725
+ * Get all memories from specific collections with optional metadata filtering
726
+ *
727
+ * @param options - Configuration for listing memories
728
+ * @param options.collection_ids - One or more collection IDs to retrieve memories from
729
+ * @param options.limit - Maximum number of memories to return (default: 100)
730
+ * @param options.offset - Number of memories to skip for pagination (default: 0)
731
+ * @param options.metadata_filters - Optional metadata filters using MongoDB-like operators.
732
+ * Supported operators: $eq, $ne, $in, $nin, $exists, $and, $or
733
+ *
734
+ * @returns Promise resolving to array of MemoryResponse objects
735
+ *
736
+ * @example
737
+ * // Get all playground memories excluding conversations
738
+ * const memories = await client.listMemories({
739
+ * collection_ids: ['collection-id'],
740
+ * metadata_filters: {
741
+ * 'metadata.content_type': { $ne: 'conversation' }
742
+ * }
743
+ * });
744
+ *
745
+ * @example
746
+ * // Complex filter with multiple conditions
747
+ * const memories = await client.listMemories({
748
+ * collection_ids: ['collection-id'],
749
+ * metadata_filters: {
750
+ * $and: [
751
+ * { 'metadata.playground': { $eq: true } },
752
+ * { 'metadata.session_id': { $exists: true } }
753
+ * ]
754
+ * }
755
+ * });
756
+ */
502
757
  async listMemories(options) {
503
- const ids = Array.isArray(options.cluster_ids) ? options.cluster_ids : [options.cluster_ids];
758
+ const ids = Array.isArray(options.collection_ids) ? options.collection_ids : [options.collection_ids];
504
759
  if (!ids.length) {
505
- throw new NebulaClientException("cluster_ids must be provided to list_memories().");
760
+ throw new NebulaClientException("collection_ids must be provided to list_memories().");
506
761
  }
507
762
  const params = {
508
763
  limit: options.limit ?? 100,
509
764
  offset: options.offset ?? 0,
510
765
  collection_ids: ids
511
766
  };
512
- const response = await this._makeRequest("GET", "/v1/documents", void 0, params);
767
+ if (options.metadata_filters) {
768
+ params.metadata_filters = JSON.stringify(options.metadata_filters);
769
+ }
770
+ const response = await this._makeRequest("GET", "/v1/memories", void 0, params);
513
771
  let documents;
514
772
  if (response.results) {
515
773
  documents = response.results;
@@ -520,9 +778,9 @@ var NebulaClient = class {
520
778
  }
521
779
  return documents.map((doc) => this._memoryResponseFromDict(doc, ids));
522
780
  }
523
- /** Get a specific memory by ID */
781
+ /** Get a specific memory by engram ID */
524
782
  async getMemory(memoryId) {
525
- const response = await this._makeRequest("GET", `/v1/documents/${memoryId}`);
783
+ const response = await this._makeRequest("GET", `/v1/memories/${memoryId}`);
526
784
  const content = response.text || response.content;
527
785
  const chunks = Array.isArray(response.chunks) ? response.chunks : void 0;
528
786
  const memoryData = {
@@ -536,11 +794,11 @@ var NebulaClient = class {
536
794
  }
537
795
  // Search Methods
538
796
  /**
539
- * Search within specific clusters with optional metadata filtering.
797
+ * Search within specific collections with optional metadata filtering.
540
798
  *
541
799
  * @param options - Search configuration
542
800
  * @param options.query - Search query string
543
- * @param options.cluster_ids - One or more cluster IDs to search within
801
+ * @param options.collection_ids - One or more collection IDs to search within
544
802
  * @param options.limit - Maximum number of results to return (default: 10)
545
803
  * @param options.retrieval_type - Retrieval strategy (default: ADVANCED)
546
804
  * @param options.filters - Optional filters to apply to the search. Supports comprehensive metadata filtering
@@ -553,7 +811,7 @@ var NebulaClient = class {
553
811
  * // Basic equality filter
554
812
  * await client.search({
555
813
  * query: "machine learning",
556
- * cluster_ids: ["research-cluster"],
814
+ * collection_ids: ["research-collection"],
557
815
  * filters: {
558
816
  * "metadata.category": { $eq: "research" },
559
817
  * "metadata.verified": true // Shorthand for $eq
@@ -564,7 +822,7 @@ var NebulaClient = class {
564
822
  * // Numeric comparisons
565
823
  * await client.search({
566
824
  * query: "high priority",
567
- * cluster_ids: ["tasks"],
825
+ * collection_ids: ["tasks"],
568
826
  * filters: {
569
827
  * "metadata.priority": { $gte: 8 },
570
828
  * "metadata.score": { $lt: 100 }
@@ -575,7 +833,7 @@ var NebulaClient = class {
575
833
  * // String matching
576
834
  * await client.search({
577
835
  * query: "employees",
578
- * cluster_ids: ["team"],
836
+ * collection_ids: ["team"],
579
837
  * filters: {
580
838
  * "metadata.email": { $ilike: "%@company.com" } // Case-insensitive
581
839
  * }
@@ -585,7 +843,7 @@ var NebulaClient = class {
585
843
  * // Array operations
586
844
  * await client.search({
587
845
  * query: "developers",
588
- * cluster_ids: ["team"],
846
+ * collection_ids: ["team"],
589
847
  * filters: {
590
848
  * "metadata.skills": { $overlap: ["python", "typescript"] } // Has any
591
849
  * }
@@ -595,7 +853,7 @@ var NebulaClient = class {
595
853
  * // Nested paths
596
854
  * await client.search({
597
855
  * query: "users",
598
- * cluster_ids: ["profiles"],
856
+ * collection_ids: ["profiles"],
599
857
  * filters: {
600
858
  * "metadata.user.preferences.theme": { $eq: "dark" }
601
859
  * }
@@ -605,7 +863,7 @@ var NebulaClient = class {
605
863
  * // Complex logical combinations
606
864
  * await client.search({
607
865
  * query: "candidates",
608
- * cluster_ids: ["hiring"],
866
+ * collection_ids: ["hiring"],
609
867
  * filters: {
610
868
  * $and: [
611
869
  * { "metadata.verified": true },
@@ -632,9 +890,10 @@ var NebulaClient = class {
632
890
  * https://docs.nebulacloud.app/guides/metadata-filtering
633
891
  */
634
892
  async search(options) {
635
- const clusterIds = Array.isArray(options.cluster_ids) ? options.cluster_ids : [options.cluster_ids];
636
- if (!clusterIds.length) {
637
- throw new NebulaClientException("cluster_ids must be provided to search().");
893
+ const collectionIds = Array.isArray(options.collection_ids) ? options.collection_ids : [options.collection_ids];
894
+ const validCollectionIds = collectionIds.filter((id) => id && id.trim() !== "");
895
+ if (!validCollectionIds.length) {
896
+ throw new NebulaClientException("collection_ids must be provided to search().");
638
897
  }
639
898
  const limit = options.limit ?? 10;
640
899
  const searchMode = options.search_mode ?? "super";
@@ -646,7 +905,7 @@ var NebulaClient = class {
646
905
  if (options.filters) {
647
906
  Object.assign(userFilters, options.filters);
648
907
  }
649
- userFilters.collection_ids = { $overlap: clusterIds };
908
+ userFilters.collection_ids = { $overlap: validCollectionIds };
650
909
  effectiveSettings.filters = userFilters;
651
910
  const data = {
652
911
  query: options.query,
@@ -670,23 +929,23 @@ var NebulaClient = class {
670
929
  /**
671
930
  * Legacy wrapper: store a two-message conversation turn as a document
672
931
  */
673
- async storeConversation(userMessage, assistantMessage, clusterId, sessionId) {
932
+ async storeConversation(userMessage, assistantMessage, collectionId, sessionId) {
674
933
  const content = `User: ${String(userMessage || "")}
675
934
  Assistant: ${String(assistantMessage || "")}`;
676
935
  const metadata = { session_id: sessionId, content_type: "conversation" };
677
- return this.store(content, clusterId, metadata);
936
+ return this.store(content, collectionId, metadata);
678
937
  }
679
938
  /**
680
939
  * Legacy wrapper: search conversations optionally scoped by session
681
940
  */
682
- async searchConversations(query, clusterId, sessionId, includeAllSessions = true) {
941
+ async searchConversations(query, collectionId, sessionId, includeAllSessions = true) {
683
942
  const filters = { "metadata.content_type": "conversation" };
684
943
  if (sessionId && !includeAllSessions) {
685
944
  filters["metadata.session_id"] = sessionId;
686
945
  }
687
946
  return this.search({
688
947
  query,
689
- cluster_ids: [clusterId],
948
+ collection_ids: [collectionId],
690
949
  limit: 10,
691
950
  filters
692
951
  });
@@ -696,7 +955,7 @@ Assistant: ${String(assistantMessage || "")}`;
696
955
  return this._makeRequest("GET", "/health");
697
956
  }
698
957
  // Helpers
699
- _clusterFromDict(data) {
958
+ _collectionFromDict(data) {
700
959
  let createdAt;
701
960
  if (data.created_at) {
702
961
  createdAt = typeof data.created_at === "string" ? data.created_at : data.created_at.toISOString();
@@ -705,29 +964,29 @@ Assistant: ${String(assistantMessage || "")}`;
705
964
  if (data.updated_at) {
706
965
  updatedAt = typeof data.updated_at === "string" ? data.updated_at : data.updated_at.toISOString();
707
966
  }
708
- const clusterId = String(data.id || "");
709
- const clusterName = data.name || "";
710
- const clusterDescription = data.description;
711
- const clusterOwnerId = data.owner_id ? String(data.owner_id) : void 0;
967
+ const collectionId = String(data.id || "");
968
+ const collectionName = data.name || "";
969
+ const collectionDescription = data.description;
970
+ const collectionOwnerId = data.owner_id ? String(data.owner_id) : void 0;
712
971
  const memoryCount = data.document_count || 0;
713
972
  const metadata = {
714
- graph_cluster_status: data.graph_cluster_status || "",
973
+ graph_collection_status: data.graph_collection_status || "",
715
974
  graph_sync_status: data.graph_sync_status || "",
716
975
  user_count: data.user_count || 0,
717
976
  document_count: data.document_count || 0
718
977
  };
719
978
  return {
720
- id: clusterId,
721
- name: clusterName,
722
- description: clusterDescription,
979
+ id: collectionId,
980
+ name: collectionName,
981
+ description: collectionDescription,
723
982
  metadata,
724
983
  created_at: createdAt,
725
984
  updated_at: updatedAt,
726
985
  memory_count: memoryCount,
727
- owner_id: clusterOwnerId
986
+ owner_id: collectionOwnerId
728
987
  };
729
988
  }
730
- _memoryResponseFromDict(data, clusterIds) {
989
+ _memoryResponseFromDict(data, collectionIds) {
731
990
  let createdAt;
732
991
  if (data.created_at) {
733
992
  createdAt = typeof data.created_at === "string" ? data.created_at : data.created_at.toISOString();
@@ -736,7 +995,7 @@ Assistant: ${String(assistantMessage || "")}`;
736
995
  if (data.updated_at) {
737
996
  updatedAt = typeof data.updated_at === "string" ? data.updated_at : data.updated_at.toISOString();
738
997
  }
739
- const memoryId = String(data.id || "");
998
+ const engramId = String(data.id || "");
740
999
  const content = data.content || data.text;
741
1000
  let chunks;
742
1001
  if (data.chunks && Array.isArray(data.chunks)) {
@@ -747,12 +1006,12 @@ Assistant: ${String(assistantMessage || "")}`;
747
1006
  }
748
1007
  }
749
1008
  const metadata = { ...data.metadata };
750
- if (data.document_id) {
751
- metadata.document_id = data.document_id;
1009
+ if (data.engram_id) {
1010
+ metadata.engram_id = data.engram_id;
752
1011
  }
753
- let finalId = memoryId;
754
- if (data.document_id && !memoryId) {
755
- finalId = data.document_id;
1012
+ let finalId = engramId;
1013
+ if (data.engram_id && !engramId) {
1014
+ finalId = data.engram_id;
756
1015
  }
757
1016
  if (data.document_metadata) {
758
1017
  Object.assign(metadata, data.document_metadata);
@@ -762,7 +1021,7 @@ Assistant: ${String(assistantMessage || "")}`;
762
1021
  content,
763
1022
  chunks,
764
1023
  metadata,
765
- cluster_ids: data.collection_ids || clusterIds,
1024
+ collection_ids: data.collection_ids || collectionIds,
766
1025
  created_at: createdAt,
767
1026
  updated_at: updatedAt
768
1027
  };
@@ -800,7 +1059,7 @@ Assistant: ${String(assistantMessage || "")}`;
800
1059
  }
801
1060
  const displayName = typeof data.display_name === "string" ? data.display_name : void 0;
802
1061
  const sourceRole = typeof data.source_role === "string" ? data.source_role : void 0;
803
- const documentId = data.document_id ? String(data.document_id) : void 0;
1062
+ const engramId = data.engram_id ? String(data.engram_id) : void 0;
804
1063
  const ownerId = data.owner_id ? String(data.owner_id) : void 0;
805
1064
  let entity;
806
1065
  let rel;
@@ -845,7 +1104,7 @@ Assistant: ${String(assistantMessage || "")}`;
845
1104
  timestamp,
846
1105
  display_name: displayName,
847
1106
  source_role: sourceRole,
848
- document_id: documentId,
1107
+ engram_id: engramId,
849
1108
  owner_id: ownerId
850
1109
  };
851
1110
  }
@@ -869,8 +1128,9 @@ exports.GraphSearchResultType = GraphSearchResultType;
869
1128
  exports.NebulaAuthenticationException = NebulaAuthenticationException;
870
1129
  exports.NebulaClient = NebulaClient;
871
1130
  exports.NebulaClientException = NebulaClientException;
872
- exports.NebulaClusterNotFoundException = NebulaClusterNotFoundException;
1131
+ exports.NebulaCollectionNotFoundException = NebulaCollectionNotFoundException;
873
1132
  exports.NebulaException = NebulaException;
1133
+ exports.NebulaNotFoundException = NebulaNotFoundException;
874
1134
  exports.NebulaRateLimitException = NebulaRateLimitException;
875
1135
  exports.NebulaValidationException = NebulaValidationException;
876
1136
  //# sourceMappingURL=index.js.map