@nebula-ai/sdk 0.0.31 → 0.0.34
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 +97 -463
- package/dist/index.d.mts +21 -4
- package/dist/index.d.ts +21 -4
- package/dist/index.js +83 -120
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +83 -120
- package/dist/index.mjs.map +1 -1
- package/package.json +17 -16
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,14 @@ interface Chunk {
|
|
|
9
9
|
metadata: Record<string, any>;
|
|
10
10
|
role?: string;
|
|
11
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* Structured chunk format returned by backend for conversation messages.
|
|
14
|
+
* Contains message text and role metadata inline.
|
|
15
|
+
*/
|
|
16
|
+
interface StructuredChunk {
|
|
17
|
+
text: string;
|
|
18
|
+
role: 'user' | 'assistant' | 'system';
|
|
19
|
+
}
|
|
12
20
|
interface MemoryResponse {
|
|
13
21
|
id: string;
|
|
14
22
|
content?: string;
|
|
@@ -193,11 +201,20 @@ declare class NebulaClient {
|
|
|
193
201
|
collection_ids?: string[];
|
|
194
202
|
metadata_filters?: Record<string, any>;
|
|
195
203
|
}): Promise<any[]>;
|
|
196
|
-
/**
|
|
204
|
+
/**
|
|
205
|
+
* Get conversation messages from the engrams API.
|
|
206
|
+
*
|
|
207
|
+
* This method retrieves conversation engrams and parses their chunks into structured messages.
|
|
208
|
+
* Expects conversation engrams to contain structured chunks with role metadata:
|
|
209
|
+
* `{text: string, role: 'user'|'assistant'|'system'}`.
|
|
210
|
+
* Converts chunks to `MemoryResponse` objects with proper role metadata.
|
|
211
|
+
*
|
|
212
|
+
* @param conversationId - Single conversation ID (returns array of messages)
|
|
213
|
+
* @param conversationIds - Multiple conversation IDs (returns map of conversation_id -> messages)
|
|
214
|
+
* @returns Messages for the requested conversation(s)
|
|
215
|
+
*/
|
|
197
216
|
getConversationMessages(conversationId: string): Promise<MemoryResponse[]>;
|
|
198
217
|
getConversationMessages(conversationIds: string[]): Promise<Record<string, MemoryResponse[]>>;
|
|
199
|
-
/** Helper method to transform conversation messages to MemoryResponse format */
|
|
200
|
-
private _transformConversationMessages;
|
|
201
218
|
/** Update a collection */
|
|
202
219
|
updateCollection(options: {
|
|
203
220
|
collectionId: string;
|
|
@@ -440,4 +457,4 @@ declare class NebulaClient {
|
|
|
440
457
|
private _formDataFromObject;
|
|
441
458
|
}
|
|
442
459
|
|
|
443
|
-
export { type AgentResponse, type Chunk, type Collection, type GraphCommunityResult, type GraphEntityResult, type GraphRelationshipResult, GraphSearchResultType, type Memory, type MemoryResponse, NebulaAuthenticationException, NebulaClient, type NebulaClientConfig, NebulaClientException, NebulaCollectionNotFoundException, NebulaException, NebulaNotFoundException, NebulaRateLimitException, NebulaValidationException, type SearchOptions, type SearchResult };
|
|
460
|
+
export { type AgentResponse, type Chunk, type Collection, type GraphCommunityResult, type GraphEntityResult, type GraphRelationshipResult, GraphSearchResultType, type Memory, type MemoryResponse, NebulaAuthenticationException, NebulaClient, type NebulaClientConfig, NebulaClientException, NebulaCollectionNotFoundException, NebulaException, NebulaNotFoundException, NebulaRateLimitException, NebulaValidationException, type SearchOptions, type SearchResult, type StructuredChunk };
|
package/dist/index.js
CHANGED
|
@@ -106,23 +106,18 @@ var NebulaClient = class {
|
|
|
106
106
|
async _makeRequest(method, endpoint, jsonData, params) {
|
|
107
107
|
const url = new URL(endpoint, this.baseUrl);
|
|
108
108
|
if (params) {
|
|
109
|
-
console.log("SDK: _makeRequest params before processing:", params);
|
|
110
109
|
Object.entries(params).forEach(([key, value]) => {
|
|
111
110
|
if (value !== void 0 && value !== null) {
|
|
112
111
|
if (Array.isArray(value)) {
|
|
113
|
-
console.log(`SDK: Adding array param ${key}:`, value);
|
|
114
112
|
value.forEach((item) => {
|
|
115
113
|
url.searchParams.append(key, String(item));
|
|
116
|
-
console.log(`SDK: Appended ${key}=${item} to URL`);
|
|
117
114
|
});
|
|
118
115
|
} else {
|
|
119
|
-
console.log(`SDK: Adding single param ${key}:`, value);
|
|
120
116
|
url.searchParams.append(key, String(value));
|
|
121
117
|
}
|
|
122
118
|
}
|
|
123
119
|
});
|
|
124
120
|
}
|
|
125
|
-
console.log("SDK: Final URL being requested:", url.toString());
|
|
126
121
|
const headers = this._buildAuthHeaders(true);
|
|
127
122
|
const controller = new AbortController();
|
|
128
123
|
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
@@ -134,7 +129,7 @@ var NebulaClient = class {
|
|
|
134
129
|
signal: controller.signal
|
|
135
130
|
});
|
|
136
131
|
clearTimeout(timeoutId);
|
|
137
|
-
if (response.status === 200) {
|
|
132
|
+
if (response.status === 200 || response.status === 202) {
|
|
138
133
|
return await response.json();
|
|
139
134
|
} else if (response.status === 401) {
|
|
140
135
|
throw new NebulaAuthenticationException("Invalid API key");
|
|
@@ -252,7 +247,7 @@ var NebulaClient = class {
|
|
|
252
247
|
if (options?.metadata_filters) {
|
|
253
248
|
params.metadata_filters = JSON.stringify(options.metadata_filters);
|
|
254
249
|
}
|
|
255
|
-
const response = await this._makeRequest("GET", "/v1/
|
|
250
|
+
const response = await this._makeRequest("GET", "/v1/memories", void 0, params);
|
|
256
251
|
let conversations;
|
|
257
252
|
if (response && response.results) {
|
|
258
253
|
conversations = response.results;
|
|
@@ -265,36 +260,46 @@ var NebulaClient = class {
|
|
|
265
260
|
}
|
|
266
261
|
async getConversationMessages(conversationIdOrIds) {
|
|
267
262
|
if (typeof conversationIdOrIds === "string") {
|
|
268
|
-
const
|
|
269
|
-
|
|
270
|
-
return [];
|
|
271
|
-
}
|
|
272
|
-
return this._transformConversationMessages(response2.results);
|
|
263
|
+
const batchResults = await this.getConversationMessages([conversationIdOrIds]);
|
|
264
|
+
return batchResults[conversationIdOrIds] || [];
|
|
273
265
|
}
|
|
274
266
|
if (!Array.isArray(conversationIdOrIds) || conversationIdOrIds.length === 0) {
|
|
275
267
|
return {};
|
|
276
268
|
}
|
|
277
|
-
const
|
|
278
|
-
|
|
279
|
-
});
|
|
280
|
-
console.log("\u{1F50D} SDK: Raw batch response:", response);
|
|
281
|
-
console.log("\u{1F50D} SDK: Response has results?", !!response?.results);
|
|
282
|
-
if (response?.results) {
|
|
283
|
-
console.log("\u{1F50D} SDK: Results keys:", Object.keys(response.results));
|
|
284
|
-
console.log("\u{1F50D} SDK: Sample result:", Object.keys(response.results)[0], ":", response.results[Object.keys(response.results)[0]]);
|
|
285
|
-
}
|
|
269
|
+
const params = { ids: conversationIdOrIds };
|
|
270
|
+
const response = await this._makeRequest("GET", "/v1/memories", void 0, params);
|
|
286
271
|
const results = {};
|
|
287
|
-
if (response && response.results) {
|
|
288
|
-
const
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
272
|
+
if (response && response.results && Array.isArray(response.results)) {
|
|
273
|
+
for (const doc of response.results) {
|
|
274
|
+
const conversationId = doc.id;
|
|
275
|
+
if (!conversationId) {
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
if (Array.isArray(doc.chunks) && doc.chunks.length > 0) {
|
|
279
|
+
const messages = [];
|
|
280
|
+
for (let i = 0; i < doc.chunks.length; i++) {
|
|
281
|
+
const structuredChunk = doc.chunks[i];
|
|
282
|
+
if (!structuredChunk || typeof structuredChunk.text !== "string" || structuredChunk.text.length === 0) {
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
const text = structuredChunk.text;
|
|
286
|
+
const role = structuredChunk.role ?? "user";
|
|
287
|
+
messages.push({
|
|
288
|
+
id: `${doc.id}-${i}`,
|
|
289
|
+
content: text,
|
|
290
|
+
metadata: {
|
|
291
|
+
...doc.metadata,
|
|
292
|
+
// Copy engram metadata (playground, session_id, etc.)
|
|
293
|
+
role
|
|
294
|
+
// Add/override role for this specific message
|
|
295
|
+
},
|
|
296
|
+
created_at: doc.created_at,
|
|
297
|
+
collection_ids: doc.collection_ids || []
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
results[conversationId] = messages;
|
|
295
301
|
} else {
|
|
296
302
|
results[conversationId] = [];
|
|
297
|
-
console.log(`\u{1F50D} SDK: Conversation ${conversationId.slice(-8)}: not array, setting empty`);
|
|
298
303
|
}
|
|
299
304
|
}
|
|
300
305
|
}
|
|
@@ -305,36 +310,6 @@ var NebulaClient = class {
|
|
|
305
310
|
}
|
|
306
311
|
return results;
|
|
307
312
|
}
|
|
308
|
-
/** Helper method to transform conversation messages to MemoryResponse format */
|
|
309
|
-
_transformConversationMessages(messageResponses) {
|
|
310
|
-
return messageResponses.map((msgResp) => {
|
|
311
|
-
const msgId = String(msgResp.id || "");
|
|
312
|
-
const msg = msgResp.message || {};
|
|
313
|
-
const metadata = msgResp.metadata || {};
|
|
314
|
-
let text = "";
|
|
315
|
-
const rawContent = msg.content;
|
|
316
|
-
if (typeof rawContent === "string") {
|
|
317
|
-
text = rawContent;
|
|
318
|
-
} else if (rawContent && typeof rawContent === "object") {
|
|
319
|
-
text = String(rawContent.content || rawContent.text || JSON.stringify(rawContent));
|
|
320
|
-
} else if (rawContent != null) {
|
|
321
|
-
text = String(rawContent);
|
|
322
|
-
}
|
|
323
|
-
const role = msg.role || metadata.role || "user";
|
|
324
|
-
const combinedMetadata = {
|
|
325
|
-
...metadata,
|
|
326
|
-
role
|
|
327
|
-
// Ensure role is in metadata for UI compatibility
|
|
328
|
-
};
|
|
329
|
-
return {
|
|
330
|
-
id: msgId,
|
|
331
|
-
content: text,
|
|
332
|
-
metadata: combinedMetadata,
|
|
333
|
-
created_at: msgResp.created_at,
|
|
334
|
-
collection_ids: msgResp.collection_ids || []
|
|
335
|
-
};
|
|
336
|
-
});
|
|
337
|
-
}
|
|
338
313
|
/** Update a collection */
|
|
339
314
|
async updateCollection(options) {
|
|
340
315
|
const data = {};
|
|
@@ -418,50 +393,31 @@ var NebulaClient = class {
|
|
|
418
393
|
}
|
|
419
394
|
const memoryType = mem.role ? "conversation" : "document";
|
|
420
395
|
if (memoryType === "conversation") {
|
|
421
|
-
const
|
|
396
|
+
const messages = [];
|
|
397
|
+
if (mem.content && mem.role) {
|
|
398
|
+
messages.push({
|
|
399
|
+
content: String(mem.content),
|
|
400
|
+
role: mem.role,
|
|
401
|
+
metadata: mem.metadata || {},
|
|
402
|
+
...typeof mem.authority === "number" ? { authority: Number(mem.authority) } : {}
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
if (messages.length === 0) {
|
|
406
|
+
throw new NebulaClientException("Cannot create conversation without messages. Provide content and role.");
|
|
407
|
+
}
|
|
422
408
|
const data2 = {
|
|
423
409
|
engram_type: "conversation",
|
|
410
|
+
collection_ref: mem.collection_id,
|
|
424
411
|
name: name || "Conversation",
|
|
425
|
-
|
|
426
|
-
|
|
412
|
+
messages,
|
|
413
|
+
metadata: mem.metadata || {}
|
|
427
414
|
};
|
|
428
|
-
const
|
|
429
|
-
|
|
430
|
-
|
|
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;
|
|
415
|
+
const response2 = await this._makeRequest("POST", "/v1/memories", data2);
|
|
416
|
+
if (response2.results) {
|
|
417
|
+
const convId = response2.results.memory_id || response2.results.id;
|
|
446
418
|
if (!convId) {
|
|
447
419
|
throw new NebulaClientException("Failed to create conversation: no id returned");
|
|
448
420
|
}
|
|
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
421
|
return String(convId);
|
|
466
422
|
}
|
|
467
423
|
throw new NebulaClientException("Failed to create conversation: invalid response format");
|
|
@@ -566,32 +522,39 @@ var NebulaClient = class {
|
|
|
566
522
|
for (const [key, group] of Object.entries(convGroups)) {
|
|
567
523
|
const collectionId = group[0].collection_id;
|
|
568
524
|
let convId;
|
|
569
|
-
if (key.startsWith("__new__::")) {
|
|
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
|
-
);
|
|
580
|
-
} else {
|
|
581
|
-
convId = key;
|
|
582
|
-
}
|
|
583
525
|
const messages = group.map((m) => ({
|
|
584
526
|
content: String(m.content || ""),
|
|
585
527
|
role: m.role,
|
|
586
|
-
metadata: m.metadata || {}
|
|
528
|
+
metadata: m.metadata || {},
|
|
529
|
+
...typeof m.authority === "number" ? { authority: Number(m.authority) } : {}
|
|
587
530
|
}));
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
531
|
+
if (key.startsWith("__new__::")) {
|
|
532
|
+
const data = {
|
|
533
|
+
engram_type: "conversation",
|
|
534
|
+
collection_ref: collectionId,
|
|
535
|
+
name: "Conversation",
|
|
536
|
+
messages,
|
|
537
|
+
metadata: {}
|
|
538
|
+
};
|
|
539
|
+
const response = await this._makeRequest("POST", "/v1/memories", data);
|
|
540
|
+
if (response.results) {
|
|
541
|
+
convId = response.results.memory_id || response.results.id;
|
|
542
|
+
if (!convId) {
|
|
543
|
+
throw new NebulaClientException("Failed to create conversation: no id returned");
|
|
544
|
+
}
|
|
545
|
+
} else {
|
|
546
|
+
throw new NebulaClientException("Failed to create conversation: invalid response format");
|
|
547
|
+
}
|
|
548
|
+
} else {
|
|
549
|
+
convId = key;
|
|
550
|
+
const appendMem = {
|
|
551
|
+
collection_id: collectionId,
|
|
552
|
+
content: messages,
|
|
553
|
+
memory_id: convId,
|
|
554
|
+
metadata: {}
|
|
555
|
+
};
|
|
556
|
+
await this._appendToMemory(convId, appendMem);
|
|
557
|
+
}
|
|
595
558
|
results.push(...Array(group.length).fill(String(convId)));
|
|
596
559
|
}
|
|
597
560
|
for (const m of others) {
|
|
@@ -712,7 +675,7 @@ var NebulaClient = class {
|
|
|
712
675
|
/** Delete a conversation and all its messages */
|
|
713
676
|
async deleteConversation(conversationId) {
|
|
714
677
|
try {
|
|
715
|
-
await this._makeRequest("DELETE", `/v1/
|
|
678
|
+
await this._makeRequest("DELETE", `/v1/memories/${conversationId}`);
|
|
716
679
|
return true;
|
|
717
680
|
} catch (error) {
|
|
718
681
|
if (error instanceof Error) {
|