@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/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
- /** Get conversation messages directly from the conversations API */
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/conversations", void 0, params);
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 response2 = await this._makeRequest("GET", `/v1/conversations/${conversationIdOrIds}`);
269
- if (!response2 || !response2.results) {
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 response = await this._makeRequest("POST", "/v1/conversations/batch", {
278
- conversation_ids: conversationIdOrIds
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 batchResults = response.results.results || response.results;
289
- console.log("\u{1F50D} SDK: Processing", Object.keys(batchResults).length, "conversations");
290
- for (const [conversationId, messages] of Object.entries(batchResults)) {
291
- if (Array.isArray(messages)) {
292
- const transformed = this._transformConversationMessages(messages);
293
- results[conversationId] = transformed;
294
- console.log(`\u{1F50D} SDK: Conversation ${conversationId.slice(-8)}: ${messages.length} raw -> ${transformed.length} transformed`);
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 docMetadata2 = { ...mem.metadata };
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
- metadata: JSON.stringify(docMetadata2),
426
- collection_ids: JSON.stringify([mem.collection_id])
412
+ messages,
413
+ metadata: mem.metadata || {}
427
414
  };
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;
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
- const appendMem = {
589
- collection_id: collectionId,
590
- content: messages,
591
- memory_id: convId,
592
- metadata: {}
593
- };
594
- await this._appendToMemory(convId, appendMem);
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/conversations/${conversationId}`);
678
+ await this._makeRequest("DELETE", `/v1/memories/${conversationId}`);
716
679
  return true;
717
680
  } catch (error) {
718
681
  if (error instanceof Error) {