@cilow/sdk 0.2.0 → 0.2.1

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.
Files changed (45) hide show
  1. package/README.md +412 -199
  2. package/dist/client.d.mts +224 -0
  3. package/dist/client.d.ts +224 -0
  4. package/dist/client.js +509 -0
  5. package/dist/client.js.map +1 -0
  6. package/dist/client.mjs +505 -0
  7. package/dist/client.mjs.map +1 -0
  8. package/dist/index.d.mts +94 -390
  9. package/dist/index.d.ts +94 -390
  10. package/dist/index.js +745 -350
  11. package/dist/index.js.map +1 -0
  12. package/dist/index.mjs +732 -318
  13. package/dist/index.mjs.map +1 -0
  14. package/dist/providers/langchain.js +821 -0
  15. package/dist/providers/langchain.js.map +1 -0
  16. package/dist/providers/langchain.mjs +816 -0
  17. package/dist/providers/langchain.mjs.map +1 -0
  18. package/dist/providers/openai.js +737 -0
  19. package/dist/providers/openai.js.map +1 -0
  20. package/dist/providers/openai.mjs +732 -0
  21. package/dist/providers/openai.mjs.map +1 -0
  22. package/dist/providers/vercel.js +866 -0
  23. package/dist/providers/vercel.js.map +1 -0
  24. package/dist/providers/vercel.mjs +860 -0
  25. package/dist/providers/vercel.mjs.map +1 -0
  26. package/dist/react/hooks.d.mts +327 -0
  27. package/dist/react/hooks.d.ts +327 -0
  28. package/dist/react/hooks.js +1183 -0
  29. package/dist/react/hooks.js.map +1 -0
  30. package/dist/react/hooks.mjs +1172 -0
  31. package/dist/react/hooks.mjs.map +1 -0
  32. package/dist/types.d.mts +494 -0
  33. package/dist/types.d.ts +494 -0
  34. package/dist/types.js +18 -0
  35. package/dist/types.js.map +1 -0
  36. package/dist/types.mjs +14 -0
  37. package/dist/types.mjs.map +1 -0
  38. package/dist/websocket.d.mts +160 -0
  39. package/dist/websocket.d.ts +160 -0
  40. package/dist/websocket.js +342 -0
  41. package/dist/websocket.js.map +1 -0
  42. package/dist/websocket.mjs +339 -0
  43. package/dist/websocket.mjs.map +1 -0
  44. package/package.json +90 -31
  45. package/LICENSE +0 -21
package/dist/index.js CHANGED
@@ -1,482 +1,877 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
1
+ 'use strict';
19
2
 
20
- // src/index.ts
21
- var index_exports = {};
22
- __export(index_exports, {
23
- AuthenticationError: () => AuthenticationError,
24
- CilowClient: () => CilowClient,
25
- CilowError: () => CilowError,
26
- ConnectionError: () => ConnectionError,
27
- NotFoundError: () => NotFoundError,
28
- RateLimitError: () => RateLimitError,
29
- ValidationError: () => ValidationError
30
- });
31
- module.exports = __toCommonJS(index_exports);
3
+ Object.defineProperty(exports, '__esModule', { value: true });
32
4
 
33
- // src/errors.ts
34
- var CilowError = class _CilowError extends Error {
35
- constructor(message, statusCode, details) {
5
+ // src/client.ts
6
+ async function fetchWithRetry(url, options, config) {
7
+ const controller = new AbortController();
8
+ const timeoutId = setTimeout(() => controller.abort(), config.timeout);
9
+ let lastError = null;
10
+ for (let attempt = 0; attempt <= config.retries; attempt++) {
11
+ try {
12
+ const response = await fetch(url, {
13
+ ...options,
14
+ signal: controller.signal
15
+ });
16
+ clearTimeout(timeoutId);
17
+ if (!response.ok) {
18
+ const errorBody = await response.text();
19
+ let apiError;
20
+ try {
21
+ apiError = JSON.parse(errorBody);
22
+ } catch {
23
+ apiError = {
24
+ code: `HTTP_${response.status}`,
25
+ message: errorBody || response.statusText
26
+ };
27
+ }
28
+ throw new CilowApiError(apiError.message, apiError.code, response.status, apiError.details);
29
+ }
30
+ return response;
31
+ } catch (error) {
32
+ lastError = error;
33
+ if (error instanceof CilowApiError) {
34
+ throw error;
35
+ }
36
+ if (config.debug) {
37
+ console.warn(`Cilow API request failed (attempt ${attempt + 1}/${config.retries + 1}):`, error);
38
+ }
39
+ if (attempt < config.retries) {
40
+ await new Promise((resolve) => setTimeout(resolve, Math.pow(2, attempt) * 100));
41
+ }
42
+ }
43
+ }
44
+ clearTimeout(timeoutId);
45
+ throw lastError || new Error("Request failed");
46
+ }
47
+ var CilowApiError = class extends Error {
48
+ constructor(message, code, statusCode, details) {
36
49
  super(message);
37
- this.name = "CilowError";
50
+ this.code = code;
38
51
  this.statusCode = statusCode;
39
52
  this.details = details;
40
- Object.setPrototypeOf(this, _CilowError.prototype);
41
- }
42
- };
43
- var ConnectionError = class _ConnectionError extends CilowError {
44
- constructor(message, details) {
45
- super(message, void 0, details);
46
- this.name = "ConnectionError";
47
- Object.setPrototypeOf(this, _ConnectionError.prototype);
48
- }
49
- };
50
- var AuthenticationError = class _AuthenticationError extends CilowError {
51
- constructor(message = "Invalid API key or unauthorized", details) {
52
- super(message, 401, details);
53
- this.name = "AuthenticationError";
54
- Object.setPrototypeOf(this, _AuthenticationError.prototype);
55
- }
56
- };
57
- var NotFoundError = class _NotFoundError extends CilowError {
58
- constructor(message = "Resource not found", details) {
59
- super(message, 404, details);
60
- this.name = "NotFoundError";
61
- Object.setPrototypeOf(this, _NotFoundError.prototype);
62
- }
63
- };
64
- var ValidationError = class _ValidationError extends CilowError {
65
- constructor(message = "Validation error", details) {
66
- super(message, 422, details);
67
- this.name = "ValidationError";
68
- Object.setPrototypeOf(this, _ValidationError.prototype);
53
+ this.name = "CilowApiError";
69
54
  }
70
55
  };
71
- var RateLimitError = class _RateLimitError extends CilowError {
72
- constructor(message = "Rate limit exceeded", retryAfter, details) {
73
- super(message, 429, details);
74
- this.name = "RateLimitError";
75
- this.retryAfter = retryAfter;
76
- Object.setPrototypeOf(this, _RateLimitError.prototype);
77
- }
78
- };
79
-
80
- // src/client.ts
81
- function toCamelCase(obj) {
82
- if (Array.isArray(obj)) {
83
- return obj.map((item) => toCamelCase(item));
84
- }
85
- if (obj !== null && typeof obj === "object") {
86
- return Object.entries(obj).reduce((acc, [key, value]) => {
87
- const camelKey = key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
88
- acc[camelKey] = toCamelCase(value);
89
- return acc;
90
- }, {});
91
- }
92
- return obj;
93
- }
94
- function toSnakeCase(obj) {
95
- if (Array.isArray(obj)) {
96
- return obj.map((item) => toSnakeCase(item));
97
- }
98
- if (obj !== null && typeof obj === "object") {
99
- return Object.entries(obj).reduce((acc, [key, value]) => {
100
- const snakeKey = key.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
101
- acc[snakeKey] = toSnakeCase(value);
102
- return acc;
103
- }, {});
104
- }
105
- return obj;
106
- }
107
56
  var CilowClient = class {
108
- constructor(config = {}) {
109
- this.baseUrl = (config.baseUrl ?? "http://localhost:8080").replace(/\/$/, "");
57
+ constructor(config) {
58
+ this.baseUrl = config.apiUrl.replace(/\/$/, "");
110
59
  this.apiKey = config.apiKey;
111
- this.accessToken = config.accessToken;
112
60
  this.timeout = config.timeout ?? 3e4;
61
+ this.retries = config.retries ?? 3;
62
+ this.debug = config.debug ?? false;
63
+ const authHeaders = this.apiKey.startsWith("cilow_") ? { "X-API-Key": this.apiKey } : { Authorization: `Bearer ${this.apiKey}` };
64
+ this.headers = {
65
+ "Content-Type": "application/json",
66
+ ...authHeaders,
67
+ ...config.headers
68
+ };
113
69
  }
114
70
  /**
115
- * Set the JWT access token for Bearer authentication
116
- */
117
- setAccessToken(token) {
118
- this.accessToken = token;
119
- }
120
- /**
121
- * Make API request with error handling
71
+ * Make an API request
122
72
  */
123
- async request(method, endpoint, data, useAuth = true) {
124
- const url = `${this.baseUrl}/api/v1${endpoint}`;
125
- const headers = {
126
- "Content-Type": "application/json"
127
- };
128
- if (useAuth) {
129
- if (this.apiKey) {
130
- headers["X-API-Key"] = this.apiKey;
73
+ async request(method, path, body, queryParams) {
74
+ let url = `${this.baseUrl}${path}`;
75
+ if (queryParams) {
76
+ const params = new URLSearchParams();
77
+ for (const [key, value] of Object.entries(queryParams)) {
78
+ if (value !== void 0) {
79
+ params.append(key, String(value));
80
+ }
131
81
  }
132
- if (this.accessToken) {
133
- headers["Authorization"] = `Bearer ${this.accessToken}`;
82
+ const queryString = params.toString();
83
+ if (queryString) {
84
+ url += `?${queryString}`;
134
85
  }
135
86
  }
136
- const controller = new AbortController();
137
- const timeoutId = setTimeout(() => controller.abort(), this.timeout);
138
- try {
139
- const response = await fetch(url, {
87
+ if (this.debug) {
88
+ console.log(`Cilow API: ${method} ${url}`);
89
+ }
90
+ const response = await fetchWithRetry(
91
+ url,
92
+ {
140
93
  method,
141
- headers,
142
- body: data ? JSON.stringify(toSnakeCase(data)) : void 0,
143
- signal: controller.signal
144
- });
145
- clearTimeout(timeoutId);
146
- if (!response.ok) {
147
- const errorText = await response.text();
148
- switch (response.status) {
149
- case 401:
150
- throw new AuthenticationError("Invalid API key or unauthorized");
151
- case 404:
152
- throw new NotFoundError(`Resource not found: ${endpoint}`);
153
- case 422:
154
- throw new ValidationError(`Validation error: ${errorText}`);
155
- case 429:
156
- const retryAfter = response.headers.get("Retry-After");
157
- throw new RateLimitError(
158
- "Rate limit exceeded",
159
- retryAfter ? parseInt(retryAfter, 10) : void 0
160
- );
161
- default:
162
- throw new CilowError(`API error ${response.status}: ${errorText}`, response.status);
163
- }
164
- }
165
- const json = await response.json();
166
- return toCamelCase(json);
167
- } catch (error) {
168
- clearTimeout(timeoutId);
169
- if (error instanceof CilowError) {
170
- throw error;
171
- }
172
- if (error instanceof Error) {
173
- if (error.name === "AbortError") {
174
- throw new ConnectionError("Request timeout");
175
- }
176
- throw new ConnectionError(`Failed to connect to Cilow API: ${error.message}`);
177
- }
178
- throw new ConnectionError("Unknown error occurred");
94
+ headers: this.headers,
95
+ body: body ? JSON.stringify(body) : void 0
96
+ },
97
+ { timeout: this.timeout, retries: this.retries, debug: this.debug }
98
+ );
99
+ const text = await response.text();
100
+ if (!text) {
101
+ return void 0;
179
102
  }
103
+ return JSON.parse(text);
180
104
  }
181
105
  // ===========================================================================
182
- // Health & Status
106
+ // Simple API (remember, recall, forget)
183
107
  // ===========================================================================
184
108
  /**
185
- * Check API server health
186
- */
187
- async healthCheck() {
188
- const response = await fetch(`${this.baseUrl}/health`);
189
- const json = await response.json();
190
- return toCamelCase(json);
109
+ * Store a memory (simple API)
110
+ *
111
+ * @param content - The content to remember
112
+ * @param options - Optional configuration
113
+ * @returns The created memory ID
114
+ *
115
+ * @example
116
+ * ```typescript
117
+ * await cilow.remember("User prefers dark mode", {
118
+ * tags: ["preference"],
119
+ * userId: "user-123"
120
+ * });
121
+ * ```
122
+ */
123
+ async remember(content, options) {
124
+ const response = await this.request("POST", "/api/v1/memory/add", {
125
+ content,
126
+ tags: options?.tags ?? [],
127
+ user_id: options?.userId,
128
+ session_id: options?.sessionId,
129
+ metadata: options?.metadata,
130
+ type: options?.tier
131
+ });
132
+ return response.memory_id || response.id || "";
133
+ }
134
+ /**
135
+ * Search memories (simple API)
136
+ *
137
+ * @param query - Search query text
138
+ * @param options - Search options
139
+ * @returns Array of search results
140
+ *
141
+ * @example
142
+ * ```typescript
143
+ * const memories = await cilow.recall("user preferences", {
144
+ * limit: 10,
145
+ * tags: ["preference"]
146
+ * });
147
+ * ```
148
+ */
149
+ async recall(query, options) {
150
+ const response = await this.request("POST", "/api/v1/memory/search", {
151
+ query,
152
+ limit: options?.limit ?? 10,
153
+ min_score: options?.minRelevance ?? 0.3,
154
+ tags: options?.tags,
155
+ user_id: options?.userId
156
+ });
157
+ return (response.results ?? []).map((r) => ({
158
+ memory: {
159
+ id: r.memory_id,
160
+ content: r.content,
161
+ tags: r.tags ?? [],
162
+ tier: "hot",
163
+ status: "active",
164
+ accessCount: 0,
165
+ tokenCount: Math.ceil(r.content.length / 4),
166
+ metadata: {},
167
+ createdAt: r.created_at ?? (/* @__PURE__ */ new Date()).toISOString(),
168
+ updatedAt: r.created_at ?? (/* @__PURE__ */ new Date()).toISOString(),
169
+ lastAccessedAt: (/* @__PURE__ */ new Date()).toISOString()
170
+ },
171
+ score: r.similarity,
172
+ highlights: []
173
+ }));
174
+ }
175
+ /**
176
+ * Delete memories (simple API)
177
+ *
178
+ * @param filter - Filter criteria for deletion
179
+ * @returns Number of memories deleted
180
+ *
181
+ * @example
182
+ * ```typescript
183
+ * // Delete by tags
184
+ * await cilow.forget({ tags: ["temporary"] });
185
+ *
186
+ * // Delete by user
187
+ * await cilow.forget({ userId: "user-123" });
188
+ *
189
+ * // Delete specific memory
190
+ * await cilow.forget({ memoryId: "mem-abc" });
191
+ * ```
192
+ */
193
+ async forget(filter) {
194
+ if (filter.memoryId) {
195
+ await this.deleteMemory(filter.memoryId);
196
+ return 1;
197
+ }
198
+ const response = await this.request("DELETE", "/api/v1/memories/bulk", {
199
+ filter_tags: filter.tags,
200
+ user_id: filter.userId,
201
+ session_id: filter.sessionId,
202
+ older_than: filter.olderThan
203
+ });
204
+ return response.deleted ?? 0;
191
205
  }
192
206
  // ===========================================================================
193
- // Memory Operations
207
+ // Memory CRUD Operations
194
208
  // ===========================================================================
195
209
  /**
196
- * Add a new memory to the system
210
+ * Create a new memory
197
211
  */
198
- async addMemory(options) {
199
- const response = await this.request("POST", "/memory/add", options);
200
- return response.memoryId;
212
+ async createMemory(content, options) {
213
+ return this.request("POST", "/api/v1/memories", {
214
+ content,
215
+ tags: options?.tags ?? [],
216
+ user_id: options?.userId,
217
+ session_id: options?.sessionId,
218
+ metadata: options?.metadata,
219
+ tier: options?.tier
220
+ });
201
221
  }
202
222
  /**
203
223
  * Get a memory by ID
204
224
  */
205
- async getMemory(memoryId, userId) {
206
- const endpoint = userId ? `/memory/${memoryId}?user_id=${userId}` : `/memory/${memoryId}`;
207
- return this.request("GET", endpoint);
225
+ async getMemory(memoryId) {
226
+ return this.request("GET", `/api/v1/memories/${memoryId}`);
208
227
  }
209
228
  /**
210
- * Update an existing memory
229
+ * Update a memory
211
230
  */
212
- async updateMemory(memoryId, options) {
213
- return this.request("PUT", `/memory/${memoryId}`, options);
231
+ async updateMemory(memoryId, updates) {
232
+ return this.request("PATCH", `/api/v1/memories/${memoryId}`, {
233
+ content: updates.content,
234
+ tags: updates.tags,
235
+ metadata: updates.metadata,
236
+ tier: updates.tier
237
+ });
214
238
  }
215
239
  /**
216
240
  * Delete a memory
217
241
  */
218
242
  async deleteMemory(memoryId) {
219
- await this.request("DELETE", `/memory/${memoryId}`);
220
- return true;
243
+ await this.request("DELETE", `/api/v1/memories/${memoryId}`);
221
244
  }
222
245
  /**
223
- * Search memories with semantic similarity
246
+ * List memories with pagination
224
247
  */
225
- async searchMemories(options) {
248
+ async listMemories(options) {
226
249
  const response = await this.request(
227
- "POST",
228
- "/memory/search",
229
- options
250
+ "GET",
251
+ "/api/v1/memory/list",
252
+ void 0,
253
+ {
254
+ limit: options?.limit ?? 20,
255
+ offset: options?.offset ?? 0,
256
+ user_id: options?.userId,
257
+ session_id: options?.sessionId,
258
+ tags: options?.tags?.join(","),
259
+ type: options?.tier
260
+ }
230
261
  );
231
- return Array.isArray(response) ? response : response.memories ?? [];
262
+ const items = (response.memories ?? []).map((m) => ({
263
+ id: m.memory_id || m.id || "",
264
+ content: m.content,
265
+ tags: m.tags ?? [],
266
+ createdAt: m.created_at ?? (/* @__PURE__ */ new Date()).toISOString(),
267
+ tier: m.type || "hot"
268
+ }));
269
+ const limit = options?.limit ?? 20;
270
+ const offset = options?.offset ?? 0;
271
+ const total = response.total ?? items.length;
272
+ return {
273
+ items,
274
+ total,
275
+ limit,
276
+ offset,
277
+ hasMore: offset + items.length < total
278
+ };
279
+ }
280
+ // ===========================================================================
281
+ // Search Operations
282
+ // ===========================================================================
283
+ /**
284
+ * Search memories with full options
285
+ */
286
+ async searchMemories(query) {
287
+ const response = await this.request("POST", "/api/v1/memories/search", {
288
+ text: query.text,
289
+ limit: query.limit ?? 10,
290
+ min_relevance: query.minRelevance ?? 0.3,
291
+ filter_tags: query.tags,
292
+ user_id: query.userId,
293
+ session_id: query.sessionId,
294
+ tier: query.tier,
295
+ created_after: query.createdAfter,
296
+ created_before: query.createdBefore,
297
+ include_archived: query.includeArchived,
298
+ mode: query.mode ?? "hybrid"
299
+ });
300
+ return response.results ?? [];
301
+ }
302
+ /**
303
+ * Advanced search with reranking and boosts
304
+ */
305
+ async advancedSearch(query) {
306
+ const response = await this.request("POST", "/api/v1/memories/search/advanced", {
307
+ text: query.text,
308
+ limit: query.limit ?? 10,
309
+ min_relevance: query.minRelevance ?? 0.3,
310
+ filter_tags: query.tags,
311
+ required_tags: query.requiredTags,
312
+ excluded_tags: query.excludedTags,
313
+ user_id: query.userId,
314
+ session_id: query.sessionId,
315
+ recency_boost: query.recencyBoost,
316
+ frequency_boost: query.frequencyBoost,
317
+ metadata_filters: query.metadataFilters,
318
+ reranker: query.reranker
319
+ });
320
+ return response.results ?? [];
232
321
  }
233
322
  /**
234
- * Get memory system statistics
323
+ * Get context for AI applications
235
324
  */
236
- async getMemoryStats() {
237
- return this.request("GET", "/memory/stats");
325
+ async getContext(query, options) {
326
+ const maxTokens = options?.maxTokens ?? 4e3;
327
+ const tokensPerChar = 0.25;
328
+ const results = await this.searchMemories({
329
+ text: query,
330
+ limit: 30,
331
+ minRelevance: 0.3,
332
+ userId: options?.userId,
333
+ tags: options?.tags
334
+ });
335
+ let context = "";
336
+ let estimatedTokens = 0;
337
+ const memoryIds = [];
338
+ const scores = [];
339
+ for (const result of results) {
340
+ const memoryText = `[Relevance: ${(result.score * 100).toFixed(0)}%]
341
+ ${result.memory.content}
342
+
343
+ `;
344
+ const memoryTokens = Math.ceil(memoryText.length * tokensPerChar);
345
+ if (estimatedTokens + memoryTokens > maxTokens) break;
346
+ context += memoryText;
347
+ estimatedTokens += memoryTokens;
348
+ memoryIds.push(result.memory.id);
349
+ scores.push(result.score);
350
+ }
351
+ return {
352
+ context: context.trim(),
353
+ memoriesUsed: memoryIds.length,
354
+ estimatedTokens,
355
+ memoryIds,
356
+ scores
357
+ };
238
358
  }
359
+ // ===========================================================================
360
+ // Conversation Operations
361
+ // ===========================================================================
239
362
  /**
240
- * List memories with pagination
363
+ * Store a conversation turn
241
364
  */
242
- async listMemories(options) {
243
- const params = new URLSearchParams();
244
- if (options?.limit) params.set("limit", options.limit.toString());
245
- if (options?.offset) params.set("offset", options.offset.toString());
246
- if (options?.tags) params.set("tags", options.tags.join(","));
247
- if (options?.userId) params.set("user_id", options.userId);
248
- const endpoint = params.toString() ? `/memory/list?${params}` : "/memory/list";
249
- const response = await this.request("GET", endpoint);
250
- return Array.isArray(response) ? response : response.memories ?? [];
365
+ async storeConversation(turn) {
366
+ const content = `User: ${turn.userMessage}
367
+
368
+ Assistant: ${turn.assistantResponse}`;
369
+ const tags = ["conversation"];
370
+ if (turn.sessionId) {
371
+ tags.push(`session:${turn.sessionId}`);
372
+ }
373
+ return this.remember(content, {
374
+ tags,
375
+ userId: turn.userId,
376
+ sessionId: turn.sessionId,
377
+ metadata: {
378
+ type: "conversation",
379
+ ...turn.metadata
380
+ }
381
+ });
382
+ }
383
+ /**
384
+ * Get conversation history for a session
385
+ */
386
+ async getConversationHistory(sessionId, options) {
387
+ const response = await this.listMemories({
388
+ sessionId,
389
+ tags: ["conversation"],
390
+ limit: options?.limit ?? 50,
391
+ offset: options?.offset ?? 0
392
+ });
393
+ return response.items;
251
394
  }
252
395
  // ===========================================================================
253
- // Vector Operations
396
+ // Graph Operations
254
397
  // ===========================================================================
255
398
  /**
256
- * Store a vector embedding directly
399
+ * Get a graph node
257
400
  */
258
- async storeVector(options) {
259
- const response = await this.request(
260
- "POST",
261
- "/vectors",
262
- options
263
- );
264
- return response.vectorId ?? response.id ?? "";
401
+ async getGraphNode(nodeId) {
402
+ return this.request("GET", `/api/v1/graph/nodes/${nodeId}`);
265
403
  }
266
404
  /**
267
- * Search for similar vectors
405
+ * Create a graph node
268
406
  */
269
- async searchVectors(options) {
270
- const response = await this.request("POST", "/vectors/search", options);
271
- return response;
407
+ async createGraphNode(type, name, properties) {
408
+ return this.request("POST", "/api/v1/graph/nodes", {
409
+ type,
410
+ name,
411
+ properties: properties ?? {}
412
+ });
272
413
  }
273
414
  /**
274
- * Get a vector by ID
415
+ * Create a graph edge
275
416
  */
276
- async getVector(vectorId) {
277
- return this.request("GET", `/vectors/${vectorId}`);
417
+ async createGraphEdge(sourceId, targetId, type, properties) {
418
+ return this.request("POST", "/api/v1/graph/edges", {
419
+ source_id: sourceId,
420
+ target_id: targetId,
421
+ type,
422
+ properties: properties ?? {}
423
+ });
278
424
  }
279
425
  /**
280
- * Delete a vector
426
+ * Traverse the graph from a starting node
281
427
  */
282
- async deleteVector(vectorId) {
283
- await this.request("DELETE", `/vectors/${vectorId}`);
284
- return true;
428
+ async traverseGraph(options) {
429
+ return this.request("POST", "/api/v1/graph/traverse", {
430
+ start_node_id: options.startNodeId,
431
+ max_depth: options.maxDepth ?? 3,
432
+ relationship_types: options.relationshipTypes,
433
+ limit: options.limit ?? 100,
434
+ direction: options.direction ?? "both"
435
+ });
285
436
  }
286
- // ===========================================================================
287
- // Graph Operations
288
- // ===========================================================================
289
437
  /**
290
- * Query the knowledge graph with natural language
438
+ * Get related nodes for a memory
291
439
  */
292
- async queryGraph(query, limit = 10) {
440
+ async getRelatedNodes(memoryId) {
293
441
  const response = await this.request(
294
- "POST",
295
- "/graph/query",
296
- { query, limit }
442
+ "GET",
443
+ `/api/v1/memories/${memoryId}/related-nodes`
297
444
  );
298
- return Array.isArray(response) ? response : response.results ?? [];
445
+ return response.nodes ?? [];
299
446
  }
447
+ // ===========================================================================
448
+ // Statistics & Admin
449
+ // ===========================================================================
300
450
  /**
301
- * Add a node to the knowledge graph
451
+ * Get memory statistics
302
452
  */
303
- async addGraphNode(options) {
304
- const response = await this.request(
305
- "POST",
306
- "/graph/nodes",
307
- options
308
- );
309
- return response.nodeId ?? response.id ?? "";
453
+ async getStats() {
454
+ return this.request("GET", "/api/v1/stats");
310
455
  }
311
456
  /**
312
- * Get a graph node by ID
457
+ * Get all tags with counts
313
458
  */
314
- async getGraphNode(nodeId) {
315
- return this.request("GET", `/graph/nodes/${nodeId}`);
459
+ async getTags() {
460
+ const response = await this.request("GET", "/api/v1/tags");
461
+ return response.tags ?? [];
316
462
  }
317
463
  /**
318
- * Delete a graph node
464
+ * Get user statistics
319
465
  */
320
- async deleteGraphNode(nodeId) {
321
- await this.request("DELETE", `/graph/nodes/${nodeId}`);
322
- return true;
466
+ async getUserStats(userId) {
467
+ return this.request("GET", `/api/v1/users/${userId}/stats`);
323
468
  }
324
469
  /**
325
- * Get knowledge graph statistics
470
+ * Health check
326
471
  */
327
- async getGraphStats() {
328
- return this.request("GET", "/graph/stats");
472
+ async healthCheck() {
473
+ return this.request("GET", "/health");
329
474
  }
330
475
  // ===========================================================================
331
- // Agent Operations
476
+ // Batch Operations
332
477
  // ===========================================================================
333
478
  /**
334
- * Create a new AI agent
479
+ * Batch create memories
480
+ */
481
+ async batchCreate(items) {
482
+ const response = await this.request("POST", "/api/v1/memories/batch", {
483
+ memories: items.map((item) => ({
484
+ content: item.content,
485
+ tags: item.options?.tags ?? [],
486
+ user_id: item.options?.userId,
487
+ session_id: item.options?.sessionId,
488
+ metadata: item.options?.metadata
489
+ }))
490
+ });
491
+ return response.ids ?? [];
492
+ }
493
+ /**
494
+ * Batch delete memories
335
495
  */
336
- async createAgent(options) {
337
- const response = await this.request("POST", "/agents/create", {
338
- name: options.name,
339
- type: options.agentType ?? "react",
340
- config: options.config
496
+ async batchDelete(memoryIds) {
497
+ const response = await this.request("DELETE", "/api/v1/memories/batch", {
498
+ ids: memoryIds
341
499
  });
342
- return response.agentId;
500
+ return response.deleted ?? 0;
501
+ }
502
+ };
503
+ function createClient(config) {
504
+ return new CilowClient(config);
505
+ }
506
+
507
+ // src/types.ts
508
+ function isMemoryEvent(event) {
509
+ return event.type.startsWith("memory.");
510
+ }
511
+ function isGraphEvent(event) {
512
+ return event.type.startsWith("graph.");
513
+ }
514
+ function isApiError(obj) {
515
+ return typeof obj === "object" && obj !== null && "code" in obj && "message" in obj;
516
+ }
517
+
518
+ // src/websocket.ts
519
+ var CilowWebSocket = class {
520
+ constructor(config) {
521
+ this.ws = null;
522
+ this.state = "disconnected";
523
+ this.reconnectCount = 0;
524
+ this.heartbeatTimer = null;
525
+ this.reconnectTimer = null;
526
+ this.messageQueue = [];
527
+ this.subscriptions = [];
528
+ this.listeners = /* @__PURE__ */ new Map();
529
+ this.allListeners = /* @__PURE__ */ new Set();
530
+ const httpUrl = config.apiUrl.replace(/\/$/, "");
531
+ this.wsUrl = config.wsUrl ?? httpUrl.replace(/^http/, "ws") + "/ws";
532
+ this.apiKey = config.apiKey;
533
+ this.reconnectAttempts = config.reconnectAttempts ?? 5;
534
+ this.reconnectDelay = config.reconnectDelay ?? 1e3;
535
+ this.heartbeatInterval = config.heartbeatInterval ?? 3e4;
536
+ this.messageQueueSize = config.messageQueueSize ?? 100;
343
537
  }
344
538
  /**
345
- * Get agent details
539
+ * Get current connection state
346
540
  */
347
- async getAgent(agentId) {
348
- return this.request("GET", `/agents/${agentId}`);
541
+ get connectionState() {
542
+ return this.state;
349
543
  }
350
544
  /**
351
- * Execute a task with an AI agent
545
+ * Check if connected
352
546
  */
353
- async executeTask(agentId, options) {
354
- return this.request("POST", `/agents/${agentId}/execute`, options);
547
+ get isConnected() {
548
+ return this.state === "connected";
355
549
  }
356
- // ===========================================================================
357
- // Fact Extraction
358
- // ===========================================================================
359
550
  /**
360
- * Extract facts from content using intelligent extraction
551
+ * Connect to the WebSocket server
361
552
  */
362
- async extractFacts(content, sourceContext) {
363
- const response = await this.request("POST", "/memory/extract", {
364
- content,
365
- sourceContext
553
+ async connect() {
554
+ if (this.state === "connected" || this.state === "connecting") {
555
+ return;
556
+ }
557
+ this.state = "connecting";
558
+ this.emitStatusEvent("connecting");
559
+ return new Promise((resolve, reject) => {
560
+ try {
561
+ const url = new URL(this.wsUrl);
562
+ url.searchParams.set("token", this.apiKey);
563
+ this.ws = new WebSocket(url.toString());
564
+ this.ws.onopen = () => {
565
+ this.state = "connected";
566
+ this.reconnectCount = 0;
567
+ this.emitStatusEvent("connected");
568
+ this.startHeartbeat();
569
+ this.flushMessageQueue();
570
+ this.resubscribe();
571
+ resolve();
572
+ };
573
+ this.ws.onclose = (event) => {
574
+ this.handleClose(event);
575
+ };
576
+ this.ws.onerror = (error) => {
577
+ if (this.state === "connecting") {
578
+ reject(new Error("WebSocket connection failed"));
579
+ }
580
+ this.handleError(error);
581
+ };
582
+ this.ws.onmessage = (event) => {
583
+ this.handleMessage(event);
584
+ };
585
+ } catch (error) {
586
+ this.state = "disconnected";
587
+ reject(error);
588
+ }
366
589
  });
367
- return response.facts ?? [];
368
590
  }
369
- // ===========================================================================
370
- // Authentication Operations
371
- // ===========================================================================
372
591
  /**
373
- * Register a new user account
592
+ * Disconnect from the WebSocket server
374
593
  */
375
- async register(email, password, name) {
376
- const response = await this.request(
377
- "POST",
378
- "/auth/register",
379
- { email, password, name },
380
- false
381
- );
382
- this.accessToken = response.accessToken;
383
- return response;
594
+ disconnect() {
595
+ this.stopHeartbeat();
596
+ this.clearReconnectTimer();
597
+ if (this.ws) {
598
+ this.ws.onclose = null;
599
+ this.ws.close(1e3, "Client disconnect");
600
+ this.ws = null;
601
+ }
602
+ this.state = "disconnected";
603
+ this.emitStatusEvent("disconnected", "Client initiated disconnect");
384
604
  }
385
605
  /**
386
- * Login with email and password
606
+ * Subscribe to events with optional filter
387
607
  */
388
- async login(email, password) {
389
- const response = await this.request(
390
- "POST",
391
- "/auth/login",
392
- { email, password },
393
- false
394
- );
395
- this.accessToken = response.accessToken;
396
- return response;
608
+ subscribe(filter) {
609
+ if (filter) {
610
+ this.subscriptions.push(filter);
611
+ }
612
+ if (this.isConnected) {
613
+ this.sendSubscription(filter);
614
+ }
615
+ }
616
+ /**
617
+ * Unsubscribe from events
618
+ */
619
+ unsubscribe(filter) {
620
+ if (filter) {
621
+ this.subscriptions = this.subscriptions.filter(
622
+ (s) => s.userId !== filter.userId || s.sessionId !== filter.sessionId || JSON.stringify(s.tags) !== JSON.stringify(filter.tags)
623
+ );
624
+ } else {
625
+ this.subscriptions = [];
626
+ }
627
+ if (this.isConnected) {
628
+ this.send({
629
+ type: "unsubscribe",
630
+ filter
631
+ });
632
+ }
397
633
  }
398
634
  /**
399
- * Refresh the current access token
635
+ * Add event listener for specific event type
400
636
  */
401
- async refreshToken() {
402
- const response = await this.request("POST", "/auth/refresh");
403
- this.accessToken = response.accessToken;
404
- return response;
637
+ on(eventType, listener) {
638
+ if (!this.listeners.has(eventType)) {
639
+ this.listeners.set(eventType, /* @__PURE__ */ new Set());
640
+ }
641
+ this.listeners.get(eventType).add(listener);
642
+ return () => {
643
+ this.listeners.get(eventType)?.delete(listener);
644
+ };
405
645
  }
406
646
  /**
407
- * Get the currently authenticated user
647
+ * Add listener for all events
408
648
  */
409
- async getCurrentUser() {
410
- return this.request("GET", "/auth/me");
649
+ onAny(listener) {
650
+ this.allListeners.add(listener);
651
+ return () => {
652
+ this.allListeners.delete(listener);
653
+ };
411
654
  }
412
655
  /**
413
- * Logout and invalidate current session
656
+ * Remove event listener
414
657
  */
415
- async logout() {
416
- await this.request("POST", "/auth/logout");
417
- this.accessToken = void 0;
418
- return true;
658
+ off(eventType, listener) {
659
+ this.listeners.get(eventType)?.delete(listener);
419
660
  }
420
661
  /**
421
- * Create a new API key for programmatic access
662
+ * Remove all listeners for an event type
422
663
  */
423
- async createApiKey(options) {
424
- const response = await this.request("POST", "/auth/api-keys", options);
425
- return {
426
- keyId: response.keyId ?? response.id ?? "",
427
- name: response.name,
428
- key: response.apiKey ?? response.key,
429
- permissions: response.permissions ?? [],
430
- expiresAt: response.expiresAt,
431
- isActive: true
432
- };
664
+ offAll(eventType) {
665
+ if (eventType) {
666
+ this.listeners.delete(eventType);
667
+ } else {
668
+ this.listeners.clear();
669
+ this.allListeners.clear();
670
+ }
433
671
  }
434
672
  /**
435
- * List all API keys for the current user
673
+ * Listen for memory created events
436
674
  */
437
- async listApiKeys() {
438
- const response = await this.request("GET", "/auth/api-keys");
439
- return Array.isArray(response) ? response : response.keys ?? [];
675
+ onMemoryCreated(listener) {
676
+ return this.on("memory.created", listener);
440
677
  }
441
678
  /**
442
- * Revoke an API key
679
+ * Listen for memory updated events
443
680
  */
444
- async revokeApiKey(keyId) {
445
- await this.request("DELETE", `/auth/api-keys/${keyId}`);
446
- return true;
681
+ onMemoryUpdated(listener) {
682
+ return this.on("memory.updated", listener);
447
683
  }
448
684
  /**
449
- * List all active sessions for the current user
685
+ * Listen for memory deleted events
450
686
  */
451
- async listSessions() {
452
- const response = await this.request(
453
- "GET",
454
- "/auth/sessions"
455
- );
456
- return Array.isArray(response) ? response : response.sessions ?? [];
687
+ onMemoryDeleted(listener) {
688
+ return this.on("memory.deleted", listener);
457
689
  }
458
690
  /**
459
- * Revoke a specific session
691
+ * Listen for memory tier changed events
460
692
  */
461
- async revokeSession(sessionId) {
462
- await this.request("DELETE", `/auth/sessions/${sessionId}`);
463
- return true;
693
+ onMemoryTierChanged(listener) {
694
+ return this.on("memory.tier_changed", listener);
464
695
  }
465
696
  /**
466
- * Revoke all sessions except the current one
697
+ * Listen for graph node created events
467
698
  */
468
- async revokeAllSessions() {
469
- await this.request("DELETE", "/auth/sessions");
470
- return true;
699
+ onGraphNodeCreated(listener) {
700
+ return this.on("graph.node_created", listener);
701
+ }
702
+ /**
703
+ * Listen for graph edge created events
704
+ */
705
+ onGraphEdgeCreated(listener) {
706
+ return this.on("graph.edge_created", listener);
707
+ }
708
+ /**
709
+ * Listen for connection status changes
710
+ */
711
+ onConnectionStatus(listener) {
712
+ return this.on("connection.status", listener);
713
+ }
714
+ /**
715
+ * Wait for specific event (one-time)
716
+ */
717
+ once(eventType, timeout) {
718
+ return new Promise((resolve, reject) => {
719
+ const timeoutId = timeout ? setTimeout(() => {
720
+ unsubscribe();
721
+ reject(new Error(`Timeout waiting for event: ${eventType}`));
722
+ }, timeout) : null;
723
+ const unsubscribe = this.on(eventType, (event) => {
724
+ if (timeoutId) clearTimeout(timeoutId);
725
+ unsubscribe();
726
+ resolve(event);
727
+ });
728
+ });
729
+ }
730
+ // ===========================================================================
731
+ // Private Methods
732
+ // ===========================================================================
733
+ send(message) {
734
+ const data = JSON.stringify(message);
735
+ if (this.isConnected && this.ws) {
736
+ this.ws.send(data);
737
+ } else {
738
+ if (this.messageQueue.length >= this.messageQueueSize) {
739
+ this.messageQueue.shift();
740
+ }
741
+ this.messageQueue.push(data);
742
+ }
743
+ }
744
+ sendSubscription(filter) {
745
+ this.send({
746
+ type: "subscribe",
747
+ filter: filter ?? {}
748
+ });
749
+ }
750
+ resubscribe() {
751
+ for (const filter of this.subscriptions) {
752
+ this.sendSubscription(filter);
753
+ }
754
+ }
755
+ flushMessageQueue() {
756
+ while (this.messageQueue.length > 0 && this.isConnected && this.ws) {
757
+ const message = this.messageQueue.shift();
758
+ if (message) {
759
+ this.ws.send(message);
760
+ }
761
+ }
762
+ }
763
+ handleMessage(event) {
764
+ try {
765
+ const data = JSON.parse(event.data);
766
+ this.emit(data);
767
+ } catch (error) {
768
+ console.error("Failed to parse WebSocket message:", error);
769
+ }
770
+ }
771
+ handleClose(event) {
772
+ this.stopHeartbeat();
773
+ if (event.code === 1e3) {
774
+ this.state = "disconnected";
775
+ this.emitStatusEvent("disconnected", "Connection closed normally");
776
+ return;
777
+ }
778
+ if (this.reconnectCount < this.reconnectAttempts) {
779
+ this.state = "reconnecting";
780
+ this.emitStatusEvent("reconnecting", `Reconnecting (attempt ${this.reconnectCount + 1}/${this.reconnectAttempts})`);
781
+ this.scheduleReconnect();
782
+ } else {
783
+ this.state = "disconnected";
784
+ this.emitStatusEvent("disconnected", "Max reconnection attempts reached");
785
+ }
786
+ }
787
+ handleError(_error) {
788
+ console.error("WebSocket error occurred");
789
+ }
790
+ scheduleReconnect() {
791
+ this.clearReconnectTimer();
792
+ const delay = this.reconnectDelay * Math.pow(2, this.reconnectCount);
793
+ this.reconnectCount++;
794
+ this.reconnectTimer = setTimeout(async () => {
795
+ try {
796
+ await this.connect();
797
+ } catch {
798
+ }
799
+ }, delay);
800
+ }
801
+ clearReconnectTimer() {
802
+ if (this.reconnectTimer) {
803
+ clearTimeout(this.reconnectTimer);
804
+ this.reconnectTimer = null;
805
+ }
806
+ }
807
+ startHeartbeat() {
808
+ this.stopHeartbeat();
809
+ this.heartbeatTimer = setInterval(() => {
810
+ if (this.isConnected) {
811
+ this.send({ type: "ping" });
812
+ }
813
+ }, this.heartbeatInterval);
814
+ }
815
+ stopHeartbeat() {
816
+ if (this.heartbeatTimer) {
817
+ clearInterval(this.heartbeatTimer);
818
+ this.heartbeatTimer = null;
819
+ }
820
+ }
821
+ emit(event) {
822
+ const typeListeners = this.listeners.get(event.type);
823
+ if (typeListeners) {
824
+ for (const listener of typeListeners) {
825
+ try {
826
+ listener(event);
827
+ } catch (error) {
828
+ console.error("Error in event listener:", error);
829
+ }
830
+ }
831
+ }
832
+ for (const listener of this.allListeners) {
833
+ try {
834
+ listener(event);
835
+ } catch (error) {
836
+ console.error("Error in event listener:", error);
837
+ }
838
+ }
839
+ }
840
+ emitStatusEvent(status, reason) {
841
+ const event = {
842
+ type: "connection.status",
843
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
844
+ status: status === "connecting" ? "reconnecting" : status,
845
+ reason
846
+ };
847
+ this.emit(event);
848
+ }
849
+ };
850
+ function createWebSocket(config) {
851
+ return new CilowWebSocket(config);
852
+ }
853
+
854
+ // src/index.ts
855
+ var Cilow = class extends CilowClient {
856
+ constructor(config) {
857
+ super(config);
471
858
  }
472
859
  };
473
- // Annotate the CommonJS export names for ESM import in node:
474
- 0 && (module.exports = {
475
- AuthenticationError,
476
- CilowClient,
477
- CilowError,
478
- ConnectionError,
479
- NotFoundError,
480
- RateLimitError,
481
- ValidationError
482
- });
860
+ function createCilow(config) {
861
+ return new Cilow(config);
862
+ }
863
+ var src_default = Cilow;
864
+
865
+ exports.Cilow = Cilow;
866
+ exports.CilowApiError = CilowApiError;
867
+ exports.CilowClient = CilowClient;
868
+ exports.CilowWebSocket = CilowWebSocket;
869
+ exports.createCilow = createCilow;
870
+ exports.createClient = createClient;
871
+ exports.createWebSocket = createWebSocket;
872
+ exports.default = src_default;
873
+ exports.isApiError = isApiError;
874
+ exports.isGraphEvent = isGraphEvent;
875
+ exports.isMemoryEvent = isMemoryEvent;
876
+ //# sourceMappingURL=index.js.map
877
+ //# sourceMappingURL=index.js.map