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