@nebula-ai/sdk 0.0.19
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/LICENSE +26 -0
- package/README.md +448 -0
- package/dist/index.d.mts +218 -0
- package/dist/index.d.ts +218 -0
- package/dist/index.js +664 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +651 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +66 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,651 @@
|
|
|
1
|
+
// src/types.ts
|
|
2
|
+
var RetrievalType = /* @__PURE__ */ ((RetrievalType2) => {
|
|
3
|
+
RetrievalType2["BASIC"] = "basic";
|
|
4
|
+
RetrievalType2["ADVANCED"] = "advanced";
|
|
5
|
+
RetrievalType2["CUSTOM"] = "custom";
|
|
6
|
+
return RetrievalType2;
|
|
7
|
+
})(RetrievalType || {});
|
|
8
|
+
var GraphSearchResultType = /* @__PURE__ */ ((GraphSearchResultType2) => {
|
|
9
|
+
GraphSearchResultType2["ENTITY"] = "entity";
|
|
10
|
+
GraphSearchResultType2["RELATIONSHIP"] = "relationship";
|
|
11
|
+
GraphSearchResultType2["COMMUNITY"] = "community";
|
|
12
|
+
return GraphSearchResultType2;
|
|
13
|
+
})(GraphSearchResultType || {});
|
|
14
|
+
var NebulaException = class extends Error {
|
|
15
|
+
constructor(message, statusCode, details) {
|
|
16
|
+
super(message);
|
|
17
|
+
this.statusCode = statusCode;
|
|
18
|
+
this.details = details;
|
|
19
|
+
this.name = "NebulaException";
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
var NebulaClientException = class extends NebulaException {
|
|
23
|
+
constructor(message, cause) {
|
|
24
|
+
super(message);
|
|
25
|
+
this.cause = cause;
|
|
26
|
+
this.name = "NebulaClientException";
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
var NebulaAuthenticationException = class extends NebulaException {
|
|
30
|
+
constructor(message = "Invalid API key") {
|
|
31
|
+
super(message, 401);
|
|
32
|
+
this.name = "NebulaAuthenticationException";
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
var NebulaRateLimitException = class extends NebulaException {
|
|
36
|
+
constructor(message = "Rate limit exceeded") {
|
|
37
|
+
super(message, 429);
|
|
38
|
+
this.name = "NebulaRateLimitException";
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
var NebulaValidationException = class extends NebulaException {
|
|
42
|
+
constructor(message = "Validation error", details) {
|
|
43
|
+
super(message, 400);
|
|
44
|
+
this.details = details;
|
|
45
|
+
this.name = "NebulaValidationException";
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
var NebulaClusterNotFoundException = class extends NebulaException {
|
|
49
|
+
constructor(message = "Cluster not found") {
|
|
50
|
+
super(message, 404);
|
|
51
|
+
this.name = "NebulaClusterNotFoundException";
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// src/client.ts
|
|
56
|
+
var NebulaSDK = class {
|
|
57
|
+
constructor(config) {
|
|
58
|
+
this.apiKey = config.apiKey;
|
|
59
|
+
if (!this.apiKey) {
|
|
60
|
+
throw new NebulaClientException(
|
|
61
|
+
"API key is required. Pass it to the constructor or set NEBULA_API_KEY environment variable."
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
this.baseUrl = (config.baseUrl || "https://api.nebulacloud.app").replace(/\/$/, "");
|
|
65
|
+
this.timeout = config.timeout || 3e4;
|
|
66
|
+
}
|
|
67
|
+
// Public mutators used by tests
|
|
68
|
+
setApiKey(next) {
|
|
69
|
+
this.apiKey = next;
|
|
70
|
+
}
|
|
71
|
+
setBaseUrl(next) {
|
|
72
|
+
this.baseUrl = (next || this.baseUrl).replace(/\/$/, "");
|
|
73
|
+
}
|
|
74
|
+
// Kept for backwards-compat tests; no-op in current implementation
|
|
75
|
+
setCorsProxy(_next) {
|
|
76
|
+
}
|
|
77
|
+
/** Check if API key is set */
|
|
78
|
+
isApiKeySet() {
|
|
79
|
+
return !!(this.apiKey && this.apiKey.trim() !== "");
|
|
80
|
+
}
|
|
81
|
+
/** Detect if a token looks like a Nebula API key (public.raw) */
|
|
82
|
+
_isNebulaApiKey(token) {
|
|
83
|
+
const candidate = token || this.apiKey;
|
|
84
|
+
if (!candidate) return false;
|
|
85
|
+
const parts = candidate.split(".");
|
|
86
|
+
if (parts.length !== 2) return false;
|
|
87
|
+
const [publicPart, rawPart] = parts;
|
|
88
|
+
return publicPart.startsWith("key_") && !!rawPart && rawPart.length > 0;
|
|
89
|
+
}
|
|
90
|
+
/** Build authentication headers */
|
|
91
|
+
_buildAuthHeaders(includeContentType = true) {
|
|
92
|
+
const headers = {};
|
|
93
|
+
if (this._isNebulaApiKey()) {
|
|
94
|
+
headers["X-API-Key"] = this.apiKey;
|
|
95
|
+
} else {
|
|
96
|
+
headers["Authorization"] = `Bearer ${this.apiKey}`;
|
|
97
|
+
}
|
|
98
|
+
if (includeContentType) {
|
|
99
|
+
headers["Content-Type"] = "application/json";
|
|
100
|
+
}
|
|
101
|
+
return headers;
|
|
102
|
+
}
|
|
103
|
+
/** Make an HTTP request to the Nebula API */
|
|
104
|
+
async _makeRequest(method, endpoint, jsonData, params) {
|
|
105
|
+
const url = new URL(endpoint, this.baseUrl);
|
|
106
|
+
if (params) {
|
|
107
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
108
|
+
if (value !== void 0 && value !== null) {
|
|
109
|
+
url.searchParams.append(key, String(value));
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
const headers = this._buildAuthHeaders(true);
|
|
114
|
+
const controller = new AbortController();
|
|
115
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
116
|
+
try {
|
|
117
|
+
const response = await fetch(url.toString(), {
|
|
118
|
+
method,
|
|
119
|
+
headers,
|
|
120
|
+
body: jsonData ? JSON.stringify(jsonData) : void 0,
|
|
121
|
+
signal: controller.signal
|
|
122
|
+
});
|
|
123
|
+
clearTimeout(timeoutId);
|
|
124
|
+
if (response.status === 200) {
|
|
125
|
+
return await response.json();
|
|
126
|
+
} else if (response.status === 401) {
|
|
127
|
+
throw new NebulaAuthenticationException("Invalid API key");
|
|
128
|
+
} else if (response.status === 429) {
|
|
129
|
+
throw new NebulaRateLimitException("Rate limit exceeded");
|
|
130
|
+
} else if (response.status === 400) {
|
|
131
|
+
const errorData = await response.json().catch(() => ({}));
|
|
132
|
+
throw new NebulaValidationException(errorData.message || "Validation error", errorData.details);
|
|
133
|
+
} else {
|
|
134
|
+
const errorData = await response.json().catch(() => ({}));
|
|
135
|
+
throw new NebulaException(errorData.message || `API error: ${response.status}`, response.status, errorData);
|
|
136
|
+
}
|
|
137
|
+
} catch (error) {
|
|
138
|
+
clearTimeout(timeoutId);
|
|
139
|
+
if (error instanceof NebulaException) {
|
|
140
|
+
throw error;
|
|
141
|
+
}
|
|
142
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
143
|
+
throw new NebulaClientException(`Request timed out after ${this.timeout} milliseconds`);
|
|
144
|
+
}
|
|
145
|
+
if (error instanceof Error) {
|
|
146
|
+
throw new NebulaClientException(`Request failed: ${error.message}`, error);
|
|
147
|
+
}
|
|
148
|
+
throw new NebulaClientException(`Request failed: ${String(error)}`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
// Cluster Management Methods
|
|
152
|
+
/** Create a new cluster */
|
|
153
|
+
async createCluster(name, description, metadata) {
|
|
154
|
+
const data = { name };
|
|
155
|
+
if (description) data.description = description;
|
|
156
|
+
if (metadata) data.metadata = metadata;
|
|
157
|
+
const response = await this._makeRequest("POST", "/v3/collections", data);
|
|
158
|
+
const result = response.results || response;
|
|
159
|
+
return this._clusterFromDict(result);
|
|
160
|
+
}
|
|
161
|
+
/** Get a specific cluster by ID */
|
|
162
|
+
async getCluster(clusterId) {
|
|
163
|
+
const response = await this._makeRequest("GET", `/v3/collections/${clusterId}`);
|
|
164
|
+
const result = response.results || response;
|
|
165
|
+
return this._clusterFromDict(result);
|
|
166
|
+
}
|
|
167
|
+
/** Get a specific cluster by name */
|
|
168
|
+
async getClusterByName(name) {
|
|
169
|
+
const response = await this._makeRequest("GET", `/v3/collections/name/${name}`);
|
|
170
|
+
const result = response.results || response;
|
|
171
|
+
return this._clusterFromDict(result);
|
|
172
|
+
}
|
|
173
|
+
/** Get all clusters */
|
|
174
|
+
async listClusters(limit = 100, offset = 0) {
|
|
175
|
+
const params = { limit, offset };
|
|
176
|
+
const response = await this._makeRequest("GET", "/v3/collections", void 0, params);
|
|
177
|
+
let clusters;
|
|
178
|
+
if (response.results) {
|
|
179
|
+
clusters = response.results;
|
|
180
|
+
} else if (Array.isArray(response)) {
|
|
181
|
+
clusters = response;
|
|
182
|
+
} else {
|
|
183
|
+
clusters = [response];
|
|
184
|
+
}
|
|
185
|
+
return clusters.map((cluster) => this._clusterFromDict(cluster));
|
|
186
|
+
}
|
|
187
|
+
// Conversations Methods
|
|
188
|
+
/** List conversations for the authenticated user */
|
|
189
|
+
async listConversations(limit = 100, offset = 0) {
|
|
190
|
+
const params = { limit, offset };
|
|
191
|
+
const response = await this._makeRequest("GET", "/v3/conversations", void 0, params);
|
|
192
|
+
let conversations;
|
|
193
|
+
if (response && response.results) {
|
|
194
|
+
conversations = response.results;
|
|
195
|
+
} else if (Array.isArray(response)) {
|
|
196
|
+
conversations = response;
|
|
197
|
+
} else {
|
|
198
|
+
conversations = response ? [response] : [];
|
|
199
|
+
}
|
|
200
|
+
return conversations;
|
|
201
|
+
}
|
|
202
|
+
/** Update a cluster */
|
|
203
|
+
async updateCluster(clusterId, name, description, metadata) {
|
|
204
|
+
const data = {};
|
|
205
|
+
if (name !== void 0) data.name = name;
|
|
206
|
+
if (description !== void 0) data.description = description;
|
|
207
|
+
if (metadata !== void 0) data.metadata = metadata;
|
|
208
|
+
const response = await this._makeRequest("POST", `/v3/collections/${clusterId}`, data);
|
|
209
|
+
const result = response.results || response;
|
|
210
|
+
return this._clusterFromDict(result);
|
|
211
|
+
}
|
|
212
|
+
/** Delete a cluster */
|
|
213
|
+
async deleteCluster(clusterId) {
|
|
214
|
+
await this._makeRequest("DELETE", `/v3/collections/${clusterId}`);
|
|
215
|
+
return true;
|
|
216
|
+
}
|
|
217
|
+
// Memory Management Methods
|
|
218
|
+
/**
|
|
219
|
+
* Legacy convenience: store raw text content into a cluster as a document
|
|
220
|
+
*/
|
|
221
|
+
async store(content, clusterId, metadata = {}) {
|
|
222
|
+
const docMetadata = {
|
|
223
|
+
...metadata,
|
|
224
|
+
memory_type: "memory",
|
|
225
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
226
|
+
};
|
|
227
|
+
const data = {
|
|
228
|
+
metadata: JSON.stringify(docMetadata),
|
|
229
|
+
ingestion_mode: "fast",
|
|
230
|
+
collection_ids: JSON.stringify([clusterId]),
|
|
231
|
+
raw_text: String(content || "")
|
|
232
|
+
};
|
|
233
|
+
const url = `${this.baseUrl}/v3/documents`;
|
|
234
|
+
const headers = this._buildAuthHeaders(false);
|
|
235
|
+
const response = await fetch(url, {
|
|
236
|
+
method: "POST",
|
|
237
|
+
headers,
|
|
238
|
+
body: this._formDataFromObject(data)
|
|
239
|
+
});
|
|
240
|
+
if (!response.ok) {
|
|
241
|
+
const errorData = await response.json().catch(() => ({}));
|
|
242
|
+
throw new NebulaException(
|
|
243
|
+
errorData.message || `Failed to create document: ${response.status}`,
|
|
244
|
+
response.status,
|
|
245
|
+
errorData
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
const respData = await response.json();
|
|
249
|
+
const id = respData?.results?.document_id || respData?.results?.id || respData?.id || "";
|
|
250
|
+
const result = {
|
|
251
|
+
id: String(id),
|
|
252
|
+
content: String(content || ""),
|
|
253
|
+
metadata: docMetadata,
|
|
254
|
+
cluster_ids: [clusterId],
|
|
255
|
+
created_at: docMetadata.timestamp,
|
|
256
|
+
updated_at: docMetadata.timestamp
|
|
257
|
+
};
|
|
258
|
+
return result;
|
|
259
|
+
}
|
|
260
|
+
/** Store a single memory */
|
|
261
|
+
async storeMemory(memory) {
|
|
262
|
+
let mem;
|
|
263
|
+
if ("cluster_id" in memory) {
|
|
264
|
+
mem = memory;
|
|
265
|
+
} else {
|
|
266
|
+
mem = {
|
|
267
|
+
cluster_id: memory.cluster_id,
|
|
268
|
+
content: memory.content,
|
|
269
|
+
role: memory.role,
|
|
270
|
+
parent_id: memory.parent_id,
|
|
271
|
+
metadata: memory.metadata || {}
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
if (mem.role) {
|
|
275
|
+
let convId = mem.parent_id;
|
|
276
|
+
if (!convId) {
|
|
277
|
+
const created = await this._makeRequest("POST", "/v3/conversations", {});
|
|
278
|
+
const conv = created.results || created;
|
|
279
|
+
convId = conv.id;
|
|
280
|
+
if (!convId) {
|
|
281
|
+
throw new NebulaClientException("Failed to create conversation: no id returned");
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
const payload = {
|
|
285
|
+
messages: [
|
|
286
|
+
{
|
|
287
|
+
content: String(mem.content),
|
|
288
|
+
role: mem.role,
|
|
289
|
+
metadata: mem.metadata
|
|
290
|
+
}
|
|
291
|
+
],
|
|
292
|
+
collection_id: mem.cluster_id
|
|
293
|
+
};
|
|
294
|
+
await this._makeRequest("POST", `/v3/conversations/${convId}/messages`, payload);
|
|
295
|
+
return String(convId);
|
|
296
|
+
}
|
|
297
|
+
const contentText = String(mem.content || "");
|
|
298
|
+
const contentHash = await this._sha256(contentText);
|
|
299
|
+
const docMetadata = { ...mem.metadata };
|
|
300
|
+
docMetadata.memory_type = "memory";
|
|
301
|
+
docMetadata.content_hash = contentHash;
|
|
302
|
+
const data = {
|
|
303
|
+
metadata: JSON.stringify(docMetadata),
|
|
304
|
+
ingestion_mode: "fast",
|
|
305
|
+
collection_ids: JSON.stringify([mem.cluster_id]),
|
|
306
|
+
raw_text: contentText
|
|
307
|
+
};
|
|
308
|
+
const url = `${this.baseUrl}/v3/documents`;
|
|
309
|
+
const headers = this._buildAuthHeaders(false);
|
|
310
|
+
const response = await fetch(url, {
|
|
311
|
+
method: "POST",
|
|
312
|
+
headers,
|
|
313
|
+
body: this._formDataFromObject(data)
|
|
314
|
+
});
|
|
315
|
+
if (!response.ok) {
|
|
316
|
+
const errorData = await response.json().catch(() => ({}));
|
|
317
|
+
throw new NebulaException(
|
|
318
|
+
errorData.message || `Failed to create document: ${response.status}`,
|
|
319
|
+
response.status,
|
|
320
|
+
errorData
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
const respData = await response.json();
|
|
324
|
+
if (respData.results) {
|
|
325
|
+
if (respData.results.document_id) return String(respData.results.document_id);
|
|
326
|
+
if (respData.results.id) return String(respData.results.id);
|
|
327
|
+
}
|
|
328
|
+
return "";
|
|
329
|
+
}
|
|
330
|
+
/** Store multiple memories */
|
|
331
|
+
async storeMemories(memories) {
|
|
332
|
+
const results = [];
|
|
333
|
+
const convGroups = {};
|
|
334
|
+
const others = [];
|
|
335
|
+
for (const m of memories) {
|
|
336
|
+
if (m.role) {
|
|
337
|
+
const key = m.parent_id || `__new__::${m.cluster_id}`;
|
|
338
|
+
if (!convGroups[key]) convGroups[key] = [];
|
|
339
|
+
convGroups[key].push(m);
|
|
340
|
+
} else {
|
|
341
|
+
others.push(m);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
for (const [key, group] of Object.entries(convGroups)) {
|
|
345
|
+
const clusterId = group[0].cluster_id;
|
|
346
|
+
let convId;
|
|
347
|
+
if (key.startsWith("__new__::")) {
|
|
348
|
+
const created = await this._makeRequest("POST", "/v3/conversations", {});
|
|
349
|
+
const conv = created.results || created;
|
|
350
|
+
convId = conv.id;
|
|
351
|
+
if (!convId) {
|
|
352
|
+
throw new NebulaClientException("Failed to create conversation: no id returned");
|
|
353
|
+
}
|
|
354
|
+
} else {
|
|
355
|
+
convId = key;
|
|
356
|
+
}
|
|
357
|
+
const messages = group.map((m) => ({
|
|
358
|
+
content: String(m.content || ""),
|
|
359
|
+
role: m.role,
|
|
360
|
+
metadata: m.metadata || {}
|
|
361
|
+
}));
|
|
362
|
+
const payload = { messages, collection_id: clusterId };
|
|
363
|
+
await this._makeRequest("POST", `/v3/conversations/${convId}/messages`, payload);
|
|
364
|
+
results.push(...Array(group.length).fill(String(convId)));
|
|
365
|
+
}
|
|
366
|
+
for (const m of others) {
|
|
367
|
+
results.push(await this.storeMemory(m));
|
|
368
|
+
}
|
|
369
|
+
return results;
|
|
370
|
+
}
|
|
371
|
+
/** Delete a specific memory */
|
|
372
|
+
async delete(memoryId) {
|
|
373
|
+
try {
|
|
374
|
+
await this._makeRequest("DELETE", `/v3/documents/${memoryId}`);
|
|
375
|
+
return true;
|
|
376
|
+
} catch (error) {
|
|
377
|
+
if (error instanceof Error) {
|
|
378
|
+
throw error;
|
|
379
|
+
}
|
|
380
|
+
throw new NebulaClientException(`Unknown error: ${String(error)}`);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
/** Get all memories from specific clusters */
|
|
384
|
+
async listMemories(clusterIds, limit = 100, offset = 0) {
|
|
385
|
+
const ids = Array.isArray(clusterIds) ? clusterIds : [clusterIds];
|
|
386
|
+
if (!ids.length) {
|
|
387
|
+
throw new NebulaClientException("cluster_ids must be provided to list_memories().");
|
|
388
|
+
}
|
|
389
|
+
const params = { limit, offset, collection_ids: ids };
|
|
390
|
+
const response = await this._makeRequest("GET", "/v3/documents", void 0, params);
|
|
391
|
+
let documents;
|
|
392
|
+
if (response.results) {
|
|
393
|
+
documents = response.results;
|
|
394
|
+
} else if (Array.isArray(response)) {
|
|
395
|
+
documents = response;
|
|
396
|
+
} else {
|
|
397
|
+
documents = [response];
|
|
398
|
+
}
|
|
399
|
+
return documents.map((doc) => this._memoryResponseFromDict(doc, ids));
|
|
400
|
+
}
|
|
401
|
+
/** Get a specific memory by ID */
|
|
402
|
+
async getMemory(memoryId) {
|
|
403
|
+
const response = await this._makeRequest("GET", `/v3/documents/${memoryId}`);
|
|
404
|
+
const content = response.text || response.content;
|
|
405
|
+
const chunks = Array.isArray(response.chunks) ? response.chunks : void 0;
|
|
406
|
+
const memoryData = {
|
|
407
|
+
id: response.id,
|
|
408
|
+
content,
|
|
409
|
+
chunks,
|
|
410
|
+
metadata: response.metadata || {},
|
|
411
|
+
collection_ids: response.collection_ids || []
|
|
412
|
+
};
|
|
413
|
+
return this._memoryResponseFromDict(memoryData, []);
|
|
414
|
+
}
|
|
415
|
+
// Search Methods
|
|
416
|
+
/** Search within specific clusters */
|
|
417
|
+
async search(query, clusters, limitOrOptions, retrievalType = "advanced" /* ADVANCED */, filters, searchSettings) {
|
|
418
|
+
const clusterIds = Array.isArray(clusters) ? clusters : [clusters];
|
|
419
|
+
if (!clusterIds.length) {
|
|
420
|
+
throw new NebulaClientException("cluster_ids must be provided to search().");
|
|
421
|
+
}
|
|
422
|
+
let limit = 10;
|
|
423
|
+
if (typeof limitOrOptions === "number") {
|
|
424
|
+
limit = limitOrOptions;
|
|
425
|
+
} else if (typeof limitOrOptions === "object" && limitOrOptions) {
|
|
426
|
+
if (typeof limitOrOptions.limit === "number") limit = limitOrOptions.limit;
|
|
427
|
+
}
|
|
428
|
+
if (typeof retrievalType === "string") {
|
|
429
|
+
retrievalType = RetrievalType[retrievalType.toUpperCase()] || "advanced" /* ADVANCED */;
|
|
430
|
+
}
|
|
431
|
+
const effectiveSettings = { ...searchSettings };
|
|
432
|
+
effectiveSettings.limit = limit;
|
|
433
|
+
effectiveSettings.use_semantic_search = false;
|
|
434
|
+
effectiveSettings.use_fulltext_search = false;
|
|
435
|
+
effectiveSettings.use_hybrid_search = false;
|
|
436
|
+
effectiveSettings.chunk_settings = {
|
|
437
|
+
...effectiveSettings.chunk_settings || {},
|
|
438
|
+
enabled: false
|
|
439
|
+
};
|
|
440
|
+
effectiveSettings.search_strategy = "rag_fusion";
|
|
441
|
+
effectiveSettings.num_sub_queries = 3;
|
|
442
|
+
const gs = { ...effectiveSettings.graph_settings };
|
|
443
|
+
gs.enabled = true;
|
|
444
|
+
gs.bfs_enabled = true;
|
|
445
|
+
gs.bfs_max_depth = 2;
|
|
446
|
+
effectiveSettings.graph_settings = gs;
|
|
447
|
+
if (retrievalType !== "advanced" /* ADVANCED */) {
|
|
448
|
+
effectiveSettings.retrieval_type = retrievalType;
|
|
449
|
+
}
|
|
450
|
+
const userFilters = { ...effectiveSettings.filters };
|
|
451
|
+
if (filters) {
|
|
452
|
+
Object.assign(userFilters, filters);
|
|
453
|
+
}
|
|
454
|
+
userFilters.collection_ids = { $overlap: clusterIds };
|
|
455
|
+
effectiveSettings.filters = userFilters;
|
|
456
|
+
const data = {
|
|
457
|
+
query,
|
|
458
|
+
search_mode: "custom",
|
|
459
|
+
search_settings: effectiveSettings
|
|
460
|
+
};
|
|
461
|
+
const response = await this._makeRequest("POST", "/v3/retrieval/search", data);
|
|
462
|
+
let chunkResults = [];
|
|
463
|
+
let graphResults = [];
|
|
464
|
+
if (response.results) {
|
|
465
|
+
chunkResults = response.results.chunk_search_results || [];
|
|
466
|
+
graphResults = response.results.graph_search_results || [];
|
|
467
|
+
}
|
|
468
|
+
const out = [];
|
|
469
|
+
out.push(...chunkResults.map((result) => this._searchResultFromDict(result)));
|
|
470
|
+
for (const g of graphResults) {
|
|
471
|
+
out.push(this._searchResultFromGraphDict(g));
|
|
472
|
+
}
|
|
473
|
+
return out;
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* Legacy wrapper: store a two-message conversation turn as a document
|
|
477
|
+
*/
|
|
478
|
+
async storeConversation(userMessage, assistantMessage, clusterId, sessionId) {
|
|
479
|
+
const content = `User: ${String(userMessage || "")}
|
|
480
|
+
Assistant: ${String(assistantMessage || "")}`;
|
|
481
|
+
const metadata = { session_id: sessionId, content_type: "conversation" };
|
|
482
|
+
return this.store(content, clusterId, metadata);
|
|
483
|
+
}
|
|
484
|
+
/**
|
|
485
|
+
* Legacy wrapper: search conversations optionally scoped by session
|
|
486
|
+
*/
|
|
487
|
+
async searchConversations(query, clusterId, sessionId, includeAllSessions = true) {
|
|
488
|
+
const filters = { "metadata.content_type": "conversation" };
|
|
489
|
+
if (sessionId && !includeAllSessions) {
|
|
490
|
+
filters["metadata.session_id"] = sessionId;
|
|
491
|
+
}
|
|
492
|
+
return this.search(query, [clusterId], { limit: 10 }, "advanced" /* ADVANCED */, filters);
|
|
493
|
+
}
|
|
494
|
+
// Health Check
|
|
495
|
+
async healthCheck() {
|
|
496
|
+
return this._makeRequest("GET", "/health");
|
|
497
|
+
}
|
|
498
|
+
// Helpers
|
|
499
|
+
_clusterFromDict(data) {
|
|
500
|
+
let createdAt;
|
|
501
|
+
if (data.created_at) {
|
|
502
|
+
createdAt = typeof data.created_at === "string" ? data.created_at : data.created_at.toISOString();
|
|
503
|
+
}
|
|
504
|
+
let updatedAt;
|
|
505
|
+
if (data.updated_at) {
|
|
506
|
+
updatedAt = typeof data.updated_at === "string" ? data.updated_at : data.updated_at.toISOString();
|
|
507
|
+
}
|
|
508
|
+
const clusterId = String(data.id || "");
|
|
509
|
+
const clusterName = data.name || "";
|
|
510
|
+
const clusterDescription = data.description;
|
|
511
|
+
const clusterOwnerId = data.owner_id ? String(data.owner_id) : void 0;
|
|
512
|
+
const memoryCount = data.document_count || 0;
|
|
513
|
+
const metadata = {
|
|
514
|
+
graph_cluster_status: data.graph_cluster_status || "",
|
|
515
|
+
graph_sync_status: data.graph_sync_status || "",
|
|
516
|
+
user_count: data.user_count || 0,
|
|
517
|
+
document_count: data.document_count || 0
|
|
518
|
+
};
|
|
519
|
+
return {
|
|
520
|
+
id: clusterId,
|
|
521
|
+
name: clusterName,
|
|
522
|
+
description: clusterDescription,
|
|
523
|
+
metadata,
|
|
524
|
+
created_at: createdAt,
|
|
525
|
+
updated_at: updatedAt,
|
|
526
|
+
memory_count: memoryCount,
|
|
527
|
+
owner_id: clusterOwnerId
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
_memoryResponseFromDict(data, clusterIds) {
|
|
531
|
+
let createdAt;
|
|
532
|
+
if (data.created_at) {
|
|
533
|
+
createdAt = typeof data.created_at === "string" ? data.created_at : data.created_at.toISOString();
|
|
534
|
+
}
|
|
535
|
+
let updatedAt;
|
|
536
|
+
if (data.updated_at) {
|
|
537
|
+
updatedAt = typeof data.updated_at === "string" ? data.updated_at : data.updated_at.toISOString();
|
|
538
|
+
}
|
|
539
|
+
const memoryId = String(data.id || "");
|
|
540
|
+
const content = data.content || data.text;
|
|
541
|
+
let chunks;
|
|
542
|
+
if (data.chunks && Array.isArray(data.chunks)) {
|
|
543
|
+
if (data.chunks.every((x) => typeof x === "string")) {
|
|
544
|
+
chunks = data.chunks;
|
|
545
|
+
} else {
|
|
546
|
+
chunks = data.chunks.filter((item) => item && typeof item === "object" && "text" in item).map((item) => item.text);
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
const metadata = { ...data.metadata };
|
|
550
|
+
if (data.document_id) {
|
|
551
|
+
metadata.document_id = data.document_id;
|
|
552
|
+
}
|
|
553
|
+
let finalId = memoryId;
|
|
554
|
+
if (data.document_id && !memoryId) {
|
|
555
|
+
finalId = data.document_id;
|
|
556
|
+
}
|
|
557
|
+
if (data.document_metadata) {
|
|
558
|
+
Object.assign(metadata, data.document_metadata);
|
|
559
|
+
}
|
|
560
|
+
return {
|
|
561
|
+
id: finalId,
|
|
562
|
+
content,
|
|
563
|
+
chunks,
|
|
564
|
+
metadata,
|
|
565
|
+
cluster_ids: data.collection_ids || clusterIds,
|
|
566
|
+
created_at: createdAt,
|
|
567
|
+
updated_at: updatedAt
|
|
568
|
+
};
|
|
569
|
+
}
|
|
570
|
+
_searchResultFromDict(data) {
|
|
571
|
+
const content = data.content || data.text || "";
|
|
572
|
+
const resultId = data.id || data.chunk_id || "";
|
|
573
|
+
return {
|
|
574
|
+
id: String(resultId),
|
|
575
|
+
content: String(content),
|
|
576
|
+
score: Number(data.score || 0),
|
|
577
|
+
metadata: data.metadata || {},
|
|
578
|
+
source: data.source
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
_searchResultFromGraphDict(data) {
|
|
582
|
+
const rid = data.id ? String(data.id) : "";
|
|
583
|
+
const rtype = GraphSearchResultType[(data.result_type || "entity").toUpperCase()] || "entity" /* ENTITY */;
|
|
584
|
+
const content = data.content || {};
|
|
585
|
+
const score = data.score !== void 0 ? Number(data.score) : 0;
|
|
586
|
+
const metadata = data.metadata || {};
|
|
587
|
+
const chunkIds = Array.isArray(data.chunk_ids) ? data.chunk_ids : void 0;
|
|
588
|
+
let entity;
|
|
589
|
+
let rel;
|
|
590
|
+
let comm;
|
|
591
|
+
if (rtype === "entity" /* ENTITY */) {
|
|
592
|
+
entity = {
|
|
593
|
+
id: content.id ? String(content.id) : void 0,
|
|
594
|
+
name: content.name || "",
|
|
595
|
+
description: content.description || "",
|
|
596
|
+
metadata: content.metadata || {}
|
|
597
|
+
};
|
|
598
|
+
} else if (rtype === "relationship" /* RELATIONSHIP */) {
|
|
599
|
+
rel = {
|
|
600
|
+
id: content.id ? String(content.id) : void 0,
|
|
601
|
+
subject: content.subject || "",
|
|
602
|
+
predicate: content.predicate || "",
|
|
603
|
+
object: content.object || "",
|
|
604
|
+
subject_id: content.subject_id ? String(content.subject_id) : void 0,
|
|
605
|
+
object_id: content.object_id ? String(content.object_id) : void 0,
|
|
606
|
+
description: content.description,
|
|
607
|
+
metadata: content.metadata || {}
|
|
608
|
+
};
|
|
609
|
+
} else {
|
|
610
|
+
comm = {
|
|
611
|
+
id: content.id ? String(content.id) : void 0,
|
|
612
|
+
name: content.name || "",
|
|
613
|
+
summary: content.summary || "",
|
|
614
|
+
metadata: content.metadata || {}
|
|
615
|
+
};
|
|
616
|
+
}
|
|
617
|
+
return {
|
|
618
|
+
id: rid,
|
|
619
|
+
score,
|
|
620
|
+
metadata,
|
|
621
|
+
source: "graph",
|
|
622
|
+
content: void 0,
|
|
623
|
+
graph_result_type: rtype,
|
|
624
|
+
graph_entity: entity,
|
|
625
|
+
graph_relationship: rel,
|
|
626
|
+
graph_community: comm,
|
|
627
|
+
chunk_ids: chunkIds
|
|
628
|
+
};
|
|
629
|
+
}
|
|
630
|
+
async _sha256(message) {
|
|
631
|
+
const msgBuffer = new TextEncoder().encode(message);
|
|
632
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", msgBuffer);
|
|
633
|
+
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
634
|
+
const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
635
|
+
return hashHex;
|
|
636
|
+
}
|
|
637
|
+
_formDataFromObject(obj) {
|
|
638
|
+
const formData = new FormData();
|
|
639
|
+
Object.entries(obj).forEach(([key, value]) => {
|
|
640
|
+
formData.append(key, value);
|
|
641
|
+
});
|
|
642
|
+
return formData;
|
|
643
|
+
}
|
|
644
|
+
};
|
|
645
|
+
|
|
646
|
+
// src/index.ts
|
|
647
|
+
var index_default = NebulaSDK;
|
|
648
|
+
|
|
649
|
+
export { GraphSearchResultType, NebulaAuthenticationException, NebulaClientException, NebulaClusterNotFoundException, NebulaException, NebulaRateLimitException, NebulaSDK, NebulaValidationException, RetrievalType, index_default as default };
|
|
650
|
+
//# sourceMappingURL=index.mjs.map
|
|
651
|
+
//# sourceMappingURL=index.mjs.map
|