@nebula-ai/sdk 0.0.27 → 0.0.31
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/README.md +56 -19
- package/dist/index.d.mts +169 -47
- package/dist/index.d.ts +169 -47
- package/dist/index.js +388 -128
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +387 -128
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
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
|
|
45
|
-
constructor(message = "
|
|
44
|
+
var NebulaCollectionNotFoundException = class extends NebulaException {
|
|
45
|
+
constructor(message = "Collection not found") {
|
|
46
46
|
super(message, 404);
|
|
47
|
-
this.name = "
|
|
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
|
-
//
|
|
159
|
-
/** Create a new
|
|
160
|
-
async
|
|
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.
|
|
183
|
+
return this._collectionFromDict(result);
|
|
167
184
|
}
|
|
168
|
-
/** Get a specific
|
|
169
|
-
async
|
|
170
|
-
const response = await this._makeRequest("GET", `/v1/collections/${
|
|
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.
|
|
189
|
+
return this._collectionFromDict(result);
|
|
173
190
|
}
|
|
174
|
-
/** Get a specific
|
|
175
|
-
async
|
|
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.
|
|
195
|
+
return this._collectionFromDict(result);
|
|
179
196
|
}
|
|
180
|
-
/** Get all
|
|
181
|
-
async
|
|
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
|
|
204
|
+
let collections;
|
|
188
205
|
if (response.results) {
|
|
189
|
-
|
|
206
|
+
collections = response.results;
|
|
190
207
|
} else if (Array.isArray(response)) {
|
|
191
|
-
|
|
208
|
+
collections = response;
|
|
192
209
|
} else {
|
|
193
|
-
|
|
210
|
+
collections = [response];
|
|
194
211
|
}
|
|
195
|
-
return
|
|
212
|
+
return collections.map((collection) => this._collectionFromDict(collection));
|
|
196
213
|
}
|
|
197
214
|
// Conversations Methods
|
|
198
|
-
/**
|
|
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?.
|
|
205
|
-
params.collection_ids = options.
|
|
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
|
-
|
|
334
|
+
collection_ids: msgResp.collection_ids || []
|
|
287
335
|
};
|
|
288
336
|
});
|
|
289
337
|
}
|
|
290
|
-
/** Update a
|
|
291
|
-
async
|
|
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.
|
|
344
|
+
const response = await this._makeRequest("POST", `/v1/collections/${options.collectionId}`, data);
|
|
297
345
|
const result = response.results || response;
|
|
298
|
-
return this.
|
|
346
|
+
return this._collectionFromDict(result);
|
|
299
347
|
}
|
|
300
|
-
/** Delete a
|
|
301
|
-
async
|
|
302
|
-
await this._makeRequest("DELETE", `/v1/collections/${
|
|
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
|
|
355
|
+
* Legacy convenience: store raw text content into a collection as a document
|
|
308
356
|
*/
|
|
309
|
-
async store(content,
|
|
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([
|
|
366
|
+
collection_ids: JSON.stringify([collectionId]),
|
|
319
367
|
raw_text: String(content || "")
|
|
320
368
|
};
|
|
321
|
-
const url = `${this.baseUrl}/v1/
|
|
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
|
|
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?.
|
|
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
|
-
|
|
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
|
-
/**
|
|
349
|
-
|
|
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 ("
|
|
405
|
+
if ("collection_id" in memory) {
|
|
352
406
|
mem = memory;
|
|
353
407
|
} else {
|
|
354
408
|
mem = {
|
|
355
|
-
|
|
356
|
-
content: memory.content,
|
|
409
|
+
collection_id: memory.collection_id,
|
|
410
|
+
content: memory.content || "",
|
|
357
411
|
role: memory.role,
|
|
358
|
-
|
|
412
|
+
memory_id: memory.memory_id,
|
|
359
413
|
metadata: memory.metadata || {}
|
|
360
414
|
};
|
|
361
415
|
}
|
|
362
|
-
if (mem.
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
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
|
-
|
|
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.
|
|
486
|
+
collection_ids: JSON.stringify([mem.collection_id]),
|
|
394
487
|
raw_text: contentText
|
|
395
488
|
};
|
|
396
|
-
const url = `${this.baseUrl}/v1/
|
|
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
|
|
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.
|
|
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
|
-
/**
|
|
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.
|
|
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
|
|
567
|
+
const collectionId = group[0].collection_id;
|
|
434
568
|
let convId;
|
|
435
569
|
if (key.startsWith("__new__::")) {
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
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
|
|
451
|
-
|
|
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/
|
|
609
|
+
await this._makeRequest("DELETE", `/v1/memories/${memoryIds}`);
|
|
465
610
|
return true;
|
|
466
611
|
} catch {
|
|
467
612
|
try {
|
|
468
|
-
|
|
469
|
-
|
|
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
|
-
|
|
478
|
-
|
|
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
|
-
/**
|
|
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.
|
|
758
|
+
const ids = Array.isArray(options.collection_ids) ? options.collection_ids : [options.collection_ids];
|
|
504
759
|
if (!ids.length) {
|
|
505
|
-
throw new NebulaClientException("
|
|
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
|
-
|
|
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/
|
|
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
|
|
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.
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
|
636
|
-
|
|
637
|
-
|
|
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:
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
709
|
-
const
|
|
710
|
-
const
|
|
711
|
-
const
|
|
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
|
-
|
|
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:
|
|
721
|
-
name:
|
|
722
|
-
description:
|
|
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:
|
|
986
|
+
owner_id: collectionOwnerId
|
|
728
987
|
};
|
|
729
988
|
}
|
|
730
|
-
_memoryResponseFromDict(data,
|
|
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
|
|
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.
|
|
751
|
-
metadata.
|
|
1009
|
+
if (data.engram_id) {
|
|
1010
|
+
metadata.engram_id = data.engram_id;
|
|
752
1011
|
}
|
|
753
|
-
let finalId =
|
|
754
|
-
if (data.
|
|
755
|
-
finalId = data.
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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.
|
|
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
|