@reverbia/sdk 1.0.0-next.20251124100226 → 1.0.0-next.20251125084053

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.
@@ -31,575 +31,298 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
33
  createMemoryContextSystemMessage: () => createMemoryContextSystemMessage,
34
+ decryptData: () => decryptData,
35
+ decryptDataBytes: () => decryptDataBytes,
36
+ encryptData: () => encryptData,
34
37
  extractConversationContext: () => extractConversationContext,
35
38
  formatMemoriesForChat: () => formatMemoriesForChat,
36
39
  useChat: () => useChat,
40
+ useEncryption: () => useEncryption,
37
41
  useMemory: () => useMemory
38
42
  });
39
43
  module.exports = __toCommonJS(index_exports);
40
44
 
41
45
  // src/react/useChat.ts
42
46
  var import_react = require("react");
43
- var import_client = require("@reverbia/sdk");
44
- function useChat(options) {
45
- const { getToken } = options || {};
46
- const [isLoading, setIsLoading] = (0, import_react.useState)(false);
47
- const sendMessage = (0, import_react.useCallback)(
48
- async ({
49
- messages,
50
- model
51
- }) => {
52
- if (!messages?.length) {
53
- const error = "messages are required to call sendMessage.";
54
- return { data: null, error };
55
- }
56
- if (!model) {
57
- const error = "model is required to call sendMessage.";
58
- return { data: null, error };
59
- }
60
- if (!getToken) {
61
- const error = "Token getter function is required.";
62
- return { data: null, error };
47
+
48
+ // src/client/core/bodySerializer.gen.ts
49
+ var jsonBodySerializer = {
50
+ bodySerializer: (body) => JSON.stringify(
51
+ body,
52
+ (_key, value) => typeof value === "bigint" ? value.toString() : value
53
+ )
54
+ };
55
+
56
+ // src/client/core/params.gen.ts
57
+ var extraPrefixesMap = {
58
+ $body_: "body",
59
+ $headers_: "headers",
60
+ $path_: "path",
61
+ $query_: "query"
62
+ };
63
+ var extraPrefixes = Object.entries(extraPrefixesMap);
64
+
65
+ // src/client/core/serverSentEvents.gen.ts
66
+ var createSseClient = ({
67
+ onRequest,
68
+ onSseError,
69
+ onSseEvent,
70
+ responseTransformer,
71
+ responseValidator,
72
+ sseDefaultRetryDelay,
73
+ sseMaxRetryAttempts,
74
+ sseMaxRetryDelay,
75
+ sseSleepFn,
76
+ url,
77
+ ...options
78
+ }) => {
79
+ let lastEventId;
80
+ const sleep = sseSleepFn ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
81
+ const createStream = async function* () {
82
+ let retryDelay = sseDefaultRetryDelay ?? 3e3;
83
+ let attempt = 0;
84
+ const signal = options.signal ?? new AbortController().signal;
85
+ while (true) {
86
+ if (signal.aborted) break;
87
+ attempt++;
88
+ const headers = options.headers instanceof Headers ? options.headers : new Headers(options.headers);
89
+ if (lastEventId !== void 0) {
90
+ headers.set("Last-Event-ID", lastEventId);
63
91
  }
64
- setIsLoading(true);
65
92
  try {
66
- const token = await getToken();
67
- if (!token) {
68
- const error = "No access token available.";
69
- setIsLoading(false);
70
- return { data: null, error };
93
+ const requestInit = {
94
+ redirect: "follow",
95
+ ...options,
96
+ body: options.serializedBody,
97
+ headers,
98
+ signal
99
+ };
100
+ let request = new Request(url, requestInit);
101
+ if (onRequest) {
102
+ request = await onRequest(url, requestInit);
71
103
  }
72
- const completion = await (0, import_client.postApiV1ChatCompletions)({
73
- body: {
74
- messages,
75
- model
76
- },
77
- headers: {
78
- Authorization: `Bearer ${token}`
104
+ const _fetch = options.fetch ?? globalThis.fetch;
105
+ const response = await _fetch(request);
106
+ if (!response.ok)
107
+ throw new Error(
108
+ `SSE failed: ${response.status} ${response.statusText}`
109
+ );
110
+ if (!response.body) throw new Error("No body in SSE response");
111
+ const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
112
+ let buffer = "";
113
+ const abortHandler = () => {
114
+ try {
115
+ reader.cancel();
116
+ } catch {
79
117
  }
80
- });
81
- if (!completion.data) {
82
- const error = completion.error?.error ?? "API did not return a completion response.";
83
- setIsLoading(false);
84
- return { data: null, error };
118
+ };
119
+ signal.addEventListener("abort", abortHandler);
120
+ try {
121
+ while (true) {
122
+ const { done, value } = await reader.read();
123
+ if (done) break;
124
+ buffer += value;
125
+ const chunks = buffer.split("\n\n");
126
+ buffer = chunks.pop() ?? "";
127
+ for (const chunk of chunks) {
128
+ const lines = chunk.split("\n");
129
+ const dataLines = [];
130
+ let eventName;
131
+ for (const line of lines) {
132
+ if (line.startsWith("data:")) {
133
+ dataLines.push(line.replace(/^data:\s*/, ""));
134
+ } else if (line.startsWith("event:")) {
135
+ eventName = line.replace(/^event:\s*/, "");
136
+ } else if (line.startsWith("id:")) {
137
+ lastEventId = line.replace(/^id:\s*/, "");
138
+ } else if (line.startsWith("retry:")) {
139
+ const parsed = Number.parseInt(
140
+ line.replace(/^retry:\s*/, ""),
141
+ 10
142
+ );
143
+ if (!Number.isNaN(parsed)) {
144
+ retryDelay = parsed;
145
+ }
146
+ }
147
+ }
148
+ let data;
149
+ let parsedJson = false;
150
+ if (dataLines.length) {
151
+ const rawData = dataLines.join("\n");
152
+ try {
153
+ data = JSON.parse(rawData);
154
+ parsedJson = true;
155
+ } catch {
156
+ data = rawData;
157
+ }
158
+ }
159
+ if (parsedJson) {
160
+ if (responseValidator) {
161
+ await responseValidator(data);
162
+ }
163
+ if (responseTransformer) {
164
+ data = await responseTransformer(data);
165
+ }
166
+ }
167
+ onSseEvent?.({
168
+ data,
169
+ event: eventName,
170
+ id: lastEventId,
171
+ retry: retryDelay
172
+ });
173
+ if (dataLines.length) {
174
+ yield data;
175
+ }
176
+ }
177
+ }
178
+ } finally {
179
+ signal.removeEventListener("abort", abortHandler);
180
+ reader.releaseLock();
85
181
  }
86
- if (typeof completion.data === "string") {
87
- const error = "API returned a string response instead of a completion object.";
88
- setIsLoading(false);
89
- return { data: null, error };
182
+ break;
183
+ } catch (error) {
184
+ onSseError?.(error);
185
+ if (sseMaxRetryAttempts !== void 0 && attempt >= sseMaxRetryAttempts) {
186
+ break;
90
187
  }
91
- setIsLoading(false);
92
- return { data: completion.data, error: null };
93
- } catch (err) {
94
- const error = err instanceof Error ? err.message : "Failed to send message.";
95
- setIsLoading(false);
96
- return { data: null, error };
188
+ const backoff = Math.min(
189
+ retryDelay * 2 ** (attempt - 1),
190
+ sseMaxRetryDelay ?? 3e4
191
+ );
192
+ await sleep(backoff);
97
193
  }
98
- },
99
- [getToken]
100
- );
101
- return {
102
- isLoading,
103
- sendMessage
194
+ }
104
195
  };
105
- }
106
-
107
- // src/react/useMemory.ts
108
- var import_react2 = require("react");
109
- var import_client6 = require("@reverbia/sdk");
110
-
111
- // src/lib/memory/service.ts
112
- var FACT_EXTRACTION_PROMPT = `You are a memory extraction system. Extract durable user memories from chat messages.
113
-
114
- CRITICAL: You MUST respond with ONLY valid JSON. No explanations, no markdown, no code blocks, just pure JSON.
115
-
116
- Only extract facts that will be useful in future conversations, such as identity, stable preferences, ongoing projects, skills, and constraints.
117
-
118
- Do not extract sensitive attributes, temporary things, or single-use instructions.
119
-
120
- If there are no memories to extract, return: {"items": []}
121
-
122
- Response format (JSON only, no other text):
196
+ const stream = createStream();
197
+ return { stream };
198
+ };
123
199
 
124
- {
125
- "items": [
126
- {
127
- "type": "identity",
128
- "namespace": "identity",
129
- "key": "name",
130
- "value": "Charlie",
131
- "rawEvidence": "I'm Charlie",
132
- "confidence": 0.98,
133
- "pii": true
134
- },
135
- {
136
- "type": "identity",
137
- "namespace": "work",
138
- "key": "company",
139
- "value": "ZetaChain",
140
- "rawEvidence": "called ZetaChain",
141
- "confidence": 0.99,
142
- "pii": false
143
- },
144
- {
145
- "type": "preference",
146
- "namespace": "answer_style",
147
- "key": "verbosity",
148
- "value": "concise_direct",
149
- "rawEvidence": "I prefer concise, direct answers",
150
- "confidence": 0.96,
151
- "pii": false
152
- },
153
- {
154
- "type": "identity",
155
- "namespace": "timezone",
156
- "key": "tz",
157
- "value": "America/Los_Angeles",
158
- "rawEvidence": "I'm in PST",
159
- "confidence": 0.9,
160
- "pii": false
161
- }
162
- ]
163
- }`;
164
- var preprocessMemories = (items, minConfidence = 0.6) => {
165
- if (!items || !Array.isArray(items)) {
166
- return [];
200
+ // src/client/core/pathSerializer.gen.ts
201
+ var separatorArrayExplode = (style) => {
202
+ switch (style) {
203
+ case "label":
204
+ return ".";
205
+ case "matrix":
206
+ return ";";
207
+ case "simple":
208
+ return ",";
209
+ default:
210
+ return "&";
167
211
  }
168
- const validItems = items.filter((item) => {
169
- if (item.namespace == null || item.key == null || item.value == null) {
170
- console.warn(
171
- "Dropping memory item with null/undefined namespace, key, or value:",
172
- item
173
- );
174
- return false;
175
- }
176
- const namespace = String(item.namespace).trim();
177
- const key = String(item.key).trim();
178
- const value = String(item.value).trim();
179
- if (namespace === "" || key === "" || value === "") {
180
- console.warn(
181
- "Dropping memory item with empty namespace, key, or value after trimming:",
182
- item
183
- );
184
- return false;
185
- }
186
- if (typeof item.confidence !== "number" || item.confidence < minConfidence) {
187
- console.warn(
188
- `Dropping memory item with confidence ${item.confidence} below threshold ${minConfidence}:`,
189
- item
190
- );
191
- return false;
192
- }
193
- return true;
194
- });
195
- const deduplicatedMap = /* @__PURE__ */ new Map();
196
- for (const item of validItems) {
197
- const uniqueKey = `${item.namespace}:${item.key}:${item.value}`;
198
- const existing = deduplicatedMap.get(uniqueKey);
199
- if (!existing || item.confidence > existing.confidence) {
200
- deduplicatedMap.set(uniqueKey, item);
201
- } else {
202
- console.debug(
203
- `Deduplicating memory item: keeping entry with higher confidence (${existing.confidence} > ${item.confidence})`,
204
- { namespace: item.namespace, key: item.key, value: item.value }
205
- );
206
- }
212
+ };
213
+ var separatorArrayNoExplode = (style) => {
214
+ switch (style) {
215
+ case "form":
216
+ return ",";
217
+ case "pipeDelimited":
218
+ return "|";
219
+ case "spaceDelimited":
220
+ return "%20";
221
+ default:
222
+ return ",";
207
223
  }
208
- return Array.from(deduplicatedMap.values());
209
224
  };
210
-
211
- // src/lib/memory/db.ts
212
- var import_dexie = __toESM(require("dexie"));
213
- var MemoryDatabase = class extends import_dexie.default {
214
- constructor() {
215
- super("MemoryDatabase");
216
- this.version(2).stores({
217
- memories: "++id, uniqueKey, compositeKey, namespace, key, type, createdAt, updatedAt"
218
- });
219
- this.version(3).stores({
220
- memories: "++id, uniqueKey, compositeKey, namespace, key, type, createdAt, updatedAt"
221
- });
225
+ var separatorObjectExplode = (style) => {
226
+ switch (style) {
227
+ case "label":
228
+ return ".";
229
+ case "matrix":
230
+ return ";";
231
+ case "simple":
232
+ return ",";
233
+ default:
234
+ return "&";
222
235
  }
223
236
  };
224
- var memoryDb = new MemoryDatabase();
225
- var saveMemory = async (memory) => {
226
- const compositeKey = `${memory.namespace}:${memory.key}`;
227
- const uniqueKey = `${memory.namespace}:${memory.key}:${memory.value}`;
228
- const now = Date.now();
229
- const existing = await memoryDb.memories.where("uniqueKey").equals(uniqueKey).first();
230
- if (existing) {
231
- const shouldPreserveEmbedding = existing.value === memory.value && existing.rawEvidence === memory.rawEvidence && existing.type === memory.type && existing.namespace === memory.namespace && existing.key === memory.key && existing.embedding !== void 0 && existing.embedding.length > 0;
232
- const updateData = {
233
- ...memory,
234
- compositeKey,
235
- uniqueKey,
236
- updatedAt: now,
237
- createdAt: existing.createdAt
238
- };
239
- if (shouldPreserveEmbedding) {
240
- updateData.embedding = existing.embedding;
241
- updateData.embeddingModel = existing.embeddingModel;
242
- } else {
243
- updateData.embedding = [];
244
- updateData.embeddingModel = void 0;
237
+ var serializeArrayParam = ({
238
+ allowReserved,
239
+ explode,
240
+ name,
241
+ style,
242
+ value
243
+ }) => {
244
+ if (!explode) {
245
+ const joinedValues2 = (allowReserved ? value : value.map((v) => encodeURIComponent(v))).join(separatorArrayNoExplode(style));
246
+ switch (style) {
247
+ case "label":
248
+ return `.${joinedValues2}`;
249
+ case "matrix":
250
+ return `;${name}=${joinedValues2}`;
251
+ case "simple":
252
+ return joinedValues2;
253
+ default:
254
+ return `${name}=${joinedValues2}`;
245
255
  }
246
- await memoryDb.memories.update(existing.id, updateData);
247
- } else {
248
- await memoryDb.memories.add({
249
- ...memory,
250
- compositeKey,
251
- uniqueKey,
252
- createdAt: now,
253
- updatedAt: now
254
- });
255
256
  }
257
+ const separator = separatorArrayExplode(style);
258
+ const joinedValues = value.map((v) => {
259
+ if (style === "label" || style === "simple") {
260
+ return allowReserved ? v : encodeURIComponent(v);
261
+ }
262
+ return serializePrimitiveParam({
263
+ allowReserved,
264
+ name,
265
+ value: v
266
+ });
267
+ }).join(separator);
268
+ return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
256
269
  };
257
- var saveMemories = async (memories) => {
258
- await Promise.all(memories.map((memory) => saveMemory(memory)));
259
- };
260
- var getAllMemories = async () => {
261
- return memoryDb.memories.toArray();
262
- };
263
- var cosineSimilarity = (a, b) => {
264
- if (a.length !== b.length) {
265
- throw new Error("Vectors must have the same length");
266
- }
267
- let dotProduct = 0;
268
- let normA = 0;
269
- let normB = 0;
270
- for (let i = 0; i < a.length; i++) {
271
- dotProduct += a[i] * b[i];
272
- normA += a[i] * a[i];
273
- normB += b[i] * b[i];
270
+ var serializePrimitiveParam = ({
271
+ allowReserved,
272
+ name,
273
+ value
274
+ }) => {
275
+ if (value === void 0 || value === null) {
276
+ return "";
274
277
  }
275
- const denominator = Math.sqrt(normA) * Math.sqrt(normB);
276
- if (denominator === 0) {
277
- return 0;
278
+ if (typeof value === "object") {
279
+ throw new Error(
280
+ "Deeply-nested arrays/objects aren\u2019t supported. Provide your own `querySerializer()` to handle these."
281
+ );
278
282
  }
279
- return dotProduct / denominator;
283
+ return `${name}=${allowReserved ? value : encodeURIComponent(value)}`;
280
284
  };
281
- var searchSimilarMemories = async (queryEmbedding, limit = 10, minSimilarity = 0.6) => {
282
- const allMemories = await getAllMemories();
283
- const memoriesWithEmbeddings = allMemories.filter(
284
- (m) => m.embedding && m.embedding.length > 0
285
- );
286
- console.log(
287
- `[Memory Search] Total memories: ${allMemories.length}, memories with embeddings: ${memoriesWithEmbeddings.length}`
288
- );
289
- if (memoriesWithEmbeddings.length === 0) {
290
- console.warn(
291
- "[Memory Search] No memories with embeddings found. Memories may need embeddings generated. Use generateAndStoreEmbeddings() to generate embeddings for existing memories."
292
- );
293
- return [];
285
+ var serializeObjectParam = ({
286
+ allowReserved,
287
+ explode,
288
+ name,
289
+ style,
290
+ value,
291
+ valueOnly
292
+ }) => {
293
+ if (value instanceof Date) {
294
+ return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`;
294
295
  }
295
- const allResults = memoriesWithEmbeddings.map((memory) => {
296
- const similarity = cosineSimilarity(queryEmbedding, memory.embedding);
297
- return {
298
- ...memory,
299
- similarity
300
- };
301
- }).sort((a, b) => b.similarity - a.similarity);
302
- console.log(
303
- `[Memory Search] All similarity scores:`,
304
- allResults.map((r) => ({
305
- key: `${r.namespace}:${r.key}`,
306
- value: r.value,
307
- similarity: r.similarity.toFixed(4)
308
- }))
309
- );
310
- const results = allResults.filter((result) => result.similarity >= minSimilarity).slice(0, limit);
311
- if (results.length === 0 && allResults.length > 0) {
312
- const topSimilarity = allResults[0].similarity;
313
- const suggestedThreshold = Math.max(0.3, topSimilarity - 0.1);
314
- console.warn(
315
- `[Memory Search] No memories above threshold ${minSimilarity}. Highest similarity was ${topSimilarity.toFixed(4)}. Consider lowering the threshold to ${suggestedThreshold.toFixed(2)}`
316
- );
317
- } else {
318
- console.log(
319
- `[Memory Search] Found ${results.length} memories above similarity threshold ${minSimilarity}. Top similarity: ${results[0]?.similarity.toFixed(4) || "N/A"}`
320
- );
296
+ if (style !== "deepObject" && !explode) {
297
+ let values = [];
298
+ Object.entries(value).forEach(([key, v]) => {
299
+ values = [
300
+ ...values,
301
+ key,
302
+ allowReserved ? v : encodeURIComponent(v)
303
+ ];
304
+ });
305
+ const joinedValues2 = values.join(",");
306
+ switch (style) {
307
+ case "form":
308
+ return `${name}=${joinedValues2}`;
309
+ case "label":
310
+ return `.${joinedValues2}`;
311
+ case "matrix":
312
+ return `;${name}=${joinedValues2}`;
313
+ default:
314
+ return joinedValues2;
315
+ }
321
316
  }
322
- return results;
323
- };
324
-
325
- // src/client/core/bodySerializer.gen.ts
326
- var jsonBodySerializer = {
327
- bodySerializer: (body) => JSON.stringify(
328
- body,
329
- (_key, value) => typeof value === "bigint" ? value.toString() : value
330
- )
331
- };
332
-
333
- // src/client/core/params.gen.ts
334
- var extraPrefixesMap = {
335
- $body_: "body",
336
- $headers_: "headers",
337
- $path_: "path",
338
- $query_: "query"
339
- };
340
- var extraPrefixes = Object.entries(extraPrefixesMap);
341
-
342
- // src/client/core/serverSentEvents.gen.ts
343
- var createSseClient = ({
344
- onRequest,
345
- onSseError,
346
- onSseEvent,
347
- responseTransformer,
348
- responseValidator,
349
- sseDefaultRetryDelay,
350
- sseMaxRetryAttempts,
351
- sseMaxRetryDelay,
352
- sseSleepFn,
353
- url,
354
- ...options
355
- }) => {
356
- let lastEventId;
357
- const sleep = sseSleepFn ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
358
- const createStream = async function* () {
359
- let retryDelay = sseDefaultRetryDelay ?? 3e3;
360
- let attempt = 0;
361
- const signal = options.signal ?? new AbortController().signal;
362
- while (true) {
363
- if (signal.aborted) break;
364
- attempt++;
365
- const headers = options.headers instanceof Headers ? options.headers : new Headers(options.headers);
366
- if (lastEventId !== void 0) {
367
- headers.set("Last-Event-ID", lastEventId);
368
- }
369
- try {
370
- const requestInit = {
371
- redirect: "follow",
372
- ...options,
373
- body: options.serializedBody,
374
- headers,
375
- signal
376
- };
377
- let request = new Request(url, requestInit);
378
- if (onRequest) {
379
- request = await onRequest(url, requestInit);
380
- }
381
- const _fetch = options.fetch ?? globalThis.fetch;
382
- const response = await _fetch(request);
383
- if (!response.ok)
384
- throw new Error(
385
- `SSE failed: ${response.status} ${response.statusText}`
386
- );
387
- if (!response.body) throw new Error("No body in SSE response");
388
- const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
389
- let buffer = "";
390
- const abortHandler = () => {
391
- try {
392
- reader.cancel();
393
- } catch {
394
- }
395
- };
396
- signal.addEventListener("abort", abortHandler);
397
- try {
398
- while (true) {
399
- const { done, value } = await reader.read();
400
- if (done) break;
401
- buffer += value;
402
- const chunks = buffer.split("\n\n");
403
- buffer = chunks.pop() ?? "";
404
- for (const chunk of chunks) {
405
- const lines = chunk.split("\n");
406
- const dataLines = [];
407
- let eventName;
408
- for (const line of lines) {
409
- if (line.startsWith("data:")) {
410
- dataLines.push(line.replace(/^data:\s*/, ""));
411
- } else if (line.startsWith("event:")) {
412
- eventName = line.replace(/^event:\s*/, "");
413
- } else if (line.startsWith("id:")) {
414
- lastEventId = line.replace(/^id:\s*/, "");
415
- } else if (line.startsWith("retry:")) {
416
- const parsed = Number.parseInt(
417
- line.replace(/^retry:\s*/, ""),
418
- 10
419
- );
420
- if (!Number.isNaN(parsed)) {
421
- retryDelay = parsed;
422
- }
423
- }
424
- }
425
- let data;
426
- let parsedJson = false;
427
- if (dataLines.length) {
428
- const rawData = dataLines.join("\n");
429
- try {
430
- data = JSON.parse(rawData);
431
- parsedJson = true;
432
- } catch {
433
- data = rawData;
434
- }
435
- }
436
- if (parsedJson) {
437
- if (responseValidator) {
438
- await responseValidator(data);
439
- }
440
- if (responseTransformer) {
441
- data = await responseTransformer(data);
442
- }
443
- }
444
- onSseEvent?.({
445
- data,
446
- event: eventName,
447
- id: lastEventId,
448
- retry: retryDelay
449
- });
450
- if (dataLines.length) {
451
- yield data;
452
- }
453
- }
454
- }
455
- } finally {
456
- signal.removeEventListener("abort", abortHandler);
457
- reader.releaseLock();
458
- }
459
- break;
460
- } catch (error) {
461
- onSseError?.(error);
462
- if (sseMaxRetryAttempts !== void 0 && attempt >= sseMaxRetryAttempts) {
463
- break;
464
- }
465
- const backoff = Math.min(
466
- retryDelay * 2 ** (attempt - 1),
467
- sseMaxRetryDelay ?? 3e4
468
- );
469
- await sleep(backoff);
470
- }
471
- }
472
- };
473
- const stream = createStream();
474
- return { stream };
475
- };
476
-
477
- // src/client/core/pathSerializer.gen.ts
478
- var separatorArrayExplode = (style) => {
479
- switch (style) {
480
- case "label":
481
- return ".";
482
- case "matrix":
483
- return ";";
484
- case "simple":
485
- return ",";
486
- default:
487
- return "&";
488
- }
489
- };
490
- var separatorArrayNoExplode = (style) => {
491
- switch (style) {
492
- case "form":
493
- return ",";
494
- case "pipeDelimited":
495
- return "|";
496
- case "spaceDelimited":
497
- return "%20";
498
- default:
499
- return ",";
500
- }
501
- };
502
- var separatorObjectExplode = (style) => {
503
- switch (style) {
504
- case "label":
505
- return ".";
506
- case "matrix":
507
- return ";";
508
- case "simple":
509
- return ",";
510
- default:
511
- return "&";
512
- }
513
- };
514
- var serializeArrayParam = ({
515
- allowReserved,
516
- explode,
517
- name,
518
- style,
519
- value
520
- }) => {
521
- if (!explode) {
522
- const joinedValues2 = (allowReserved ? value : value.map((v) => encodeURIComponent(v))).join(separatorArrayNoExplode(style));
523
- switch (style) {
524
- case "label":
525
- return `.${joinedValues2}`;
526
- case "matrix":
527
- return `;${name}=${joinedValues2}`;
528
- case "simple":
529
- return joinedValues2;
530
- default:
531
- return `${name}=${joinedValues2}`;
532
- }
533
- }
534
- const separator = separatorArrayExplode(style);
535
- const joinedValues = value.map((v) => {
536
- if (style === "label" || style === "simple") {
537
- return allowReserved ? v : encodeURIComponent(v);
538
- }
539
- return serializePrimitiveParam({
540
- allowReserved,
541
- name,
542
- value: v
543
- });
544
- }).join(separator);
545
- return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
546
- };
547
- var serializePrimitiveParam = ({
548
- allowReserved,
549
- name,
550
- value
551
- }) => {
552
- if (value === void 0 || value === null) {
553
- return "";
554
- }
555
- if (typeof value === "object") {
556
- throw new Error(
557
- "Deeply-nested arrays/objects aren\u2019t supported. Provide your own `querySerializer()` to handle these."
558
- );
559
- }
560
- return `${name}=${allowReserved ? value : encodeURIComponent(value)}`;
561
- };
562
- var serializeObjectParam = ({
563
- allowReserved,
564
- explode,
565
- name,
566
- style,
567
- value,
568
- valueOnly
569
- }) => {
570
- if (value instanceof Date) {
571
- return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`;
572
- }
573
- if (style !== "deepObject" && !explode) {
574
- let values = [];
575
- Object.entries(value).forEach(([key, v]) => {
576
- values = [
577
- ...values,
578
- key,
579
- allowReserved ? v : encodeURIComponent(v)
580
- ];
581
- });
582
- const joinedValues2 = values.join(",");
583
- switch (style) {
584
- case "form":
585
- return `${name}=${joinedValues2}`;
586
- case "label":
587
- return `.${joinedValues2}`;
588
- case "matrix":
589
- return `;${name}=${joinedValues2}`;
590
- default:
591
- return joinedValues2;
592
- }
593
- }
594
- const separator = separatorObjectExplode(style);
595
- const joinedValues = Object.entries(value).map(
596
- ([key, v]) => serializePrimitiveParam({
597
- allowReserved,
598
- name: style === "deepObject" ? `${name}[${key}]` : key,
599
- value: v
600
- })
601
- ).join(separator);
602
- return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
317
+ const separator = separatorObjectExplode(style);
318
+ const joinedValues = Object.entries(value).map(
319
+ ([key, v]) => serializePrimitiveParam({
320
+ allowReserved,
321
+ name: style === "deepObject" ? `${name}[${key}]` : key,
322
+ value: v
323
+ })
324
+ ).join(separator);
325
+ return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
603
326
  };
604
327
 
605
328
  // src/client/core/utils.gen.ts
@@ -1050,91 +773,619 @@ var createClient = (config = {}) => {
1050
773
  ...result
1051
774
  };
1052
775
  }
1053
- const textError = await response.text();
1054
- let jsonError;
1055
- try {
1056
- jsonError = JSON.parse(textError);
1057
- } catch {
776
+ const textError = await response.text();
777
+ let jsonError;
778
+ try {
779
+ jsonError = JSON.parse(textError);
780
+ } catch {
781
+ }
782
+ const error = jsonError ?? textError;
783
+ let finalError = error;
784
+ for (const fn of interceptors.error.fns) {
785
+ if (fn) {
786
+ finalError = await fn(error, response, opts);
787
+ }
788
+ }
789
+ finalError = finalError || {};
790
+ if (opts.throwOnError) {
791
+ throw finalError;
792
+ }
793
+ return {
794
+ error: finalError,
795
+ ...result
796
+ };
797
+ };
798
+ const makeMethodFn = (method) => (options) => request({ ...options, method });
799
+ const makeSseFn = (method) => async (options) => {
800
+ const { opts, url } = await beforeRequest(options);
801
+ return createSseClient({
802
+ ...opts,
803
+ body: opts.body,
804
+ headers: opts.headers,
805
+ method,
806
+ onRequest: async (url2, init) => {
807
+ let request2 = new Request(url2, init);
808
+ const requestInit = {
809
+ ...init,
810
+ method: init.method,
811
+ url: url2
812
+ };
813
+ for (const fn of interceptors.request.fns) {
814
+ if (fn) {
815
+ await fn(requestInit);
816
+ request2 = new Request(requestInit.url, requestInit);
817
+ }
818
+ }
819
+ return request2;
820
+ },
821
+ url
822
+ });
823
+ };
824
+ return {
825
+ buildUrl,
826
+ connect: makeMethodFn("CONNECT"),
827
+ delete: makeMethodFn("DELETE"),
828
+ get: makeMethodFn("GET"),
829
+ getConfig,
830
+ head: makeMethodFn("HEAD"),
831
+ interceptors,
832
+ options: makeMethodFn("OPTIONS"),
833
+ patch: makeMethodFn("PATCH"),
834
+ post: makeMethodFn("POST"),
835
+ put: makeMethodFn("PUT"),
836
+ request,
837
+ setConfig,
838
+ sse: {
839
+ connect: makeSseFn("CONNECT"),
840
+ delete: makeSseFn("DELETE"),
841
+ get: makeSseFn("GET"),
842
+ head: makeSseFn("HEAD"),
843
+ options: makeSseFn("OPTIONS"),
844
+ patch: makeSseFn("PATCH"),
845
+ post: makeSseFn("POST"),
846
+ put: makeSseFn("PUT"),
847
+ trace: makeSseFn("TRACE")
848
+ },
849
+ trace: makeMethodFn("TRACE")
850
+ };
851
+ };
852
+
853
+ // src/clientConfig.ts
854
+ var createClientConfig = (config) => ({
855
+ ...config,
856
+ baseUrl: "https://ai-portal-dev.zetachain.com"
857
+ });
858
+
859
+ // src/client/client.gen.ts
860
+ var client = createClient(createClientConfig(createConfig()));
861
+
862
+ // src/react/useChat.ts
863
+ function useChat(options) {
864
+ const { getToken, onData: globalOnData, onFinish, onError } = options || {};
865
+ const [isLoading, setIsLoading] = (0, import_react.useState)(false);
866
+ const abortControllerRef = (0, import_react.useRef)(null);
867
+ const stop = (0, import_react.useCallback)(() => {
868
+ if (abortControllerRef.current) {
869
+ abortControllerRef.current.abort();
870
+ abortControllerRef.current = null;
871
+ }
872
+ }, []);
873
+ (0, import_react.useEffect)(() => {
874
+ return () => {
875
+ if (abortControllerRef.current) {
876
+ abortControllerRef.current.abort();
877
+ abortControllerRef.current = null;
878
+ }
879
+ };
880
+ }, []);
881
+ const sendMessage = (0, import_react.useCallback)(
882
+ async ({
883
+ messages,
884
+ model,
885
+ onData
886
+ }) => {
887
+ if (!messages?.length) {
888
+ const errorMsg = "messages are required to call sendMessage.";
889
+ if (onError) onError(new Error(errorMsg));
890
+ return { data: null, error: errorMsg };
891
+ }
892
+ if (!model) {
893
+ const errorMsg = "model is required to call sendMessage.";
894
+ if (onError) onError(new Error(errorMsg));
895
+ return { data: null, error: errorMsg };
896
+ }
897
+ if (!getToken) {
898
+ const errorMsg = "Token getter function is required.";
899
+ if (onError) onError(new Error(errorMsg));
900
+ return { data: null, error: errorMsg };
901
+ }
902
+ if (abortControllerRef.current) {
903
+ abortControllerRef.current.abort();
904
+ }
905
+ const abortController = new AbortController();
906
+ abortControllerRef.current = abortController;
907
+ setIsLoading(true);
908
+ try {
909
+ const token = await getToken();
910
+ if (!token) {
911
+ const errorMsg = "No access token available.";
912
+ setIsLoading(false);
913
+ if (onError) onError(new Error(errorMsg));
914
+ return { data: null, error: errorMsg };
915
+ }
916
+ const sseResult = await client.sse.post({
917
+ url: "/api/v1/chat/completions",
918
+ body: {
919
+ messages,
920
+ model,
921
+ stream: true
922
+ },
923
+ headers: {
924
+ "Content-Type": "application/json",
925
+ Authorization: `Bearer ${token}`
926
+ },
927
+ signal: abortController.signal
928
+ });
929
+ let accumulatedContent = "";
930
+ let completionId = "";
931
+ let completionModel = "";
932
+ let usage;
933
+ let finishReason;
934
+ for await (const chunk of sseResult.stream) {
935
+ if (typeof chunk === "string" && (chunk.trim() === "[DONE]" || chunk.includes("[DONE]"))) {
936
+ continue;
937
+ }
938
+ if (chunk && typeof chunk === "object") {
939
+ const chunkData = chunk;
940
+ if (chunkData.id && !completionId) {
941
+ completionId = chunkData.id;
942
+ }
943
+ if (chunkData.model && !completionModel) {
944
+ completionModel = chunkData.model;
945
+ }
946
+ if (chunkData.usage) {
947
+ usage = chunkData.usage;
948
+ }
949
+ if (chunkData.choices && Array.isArray(chunkData.choices) && chunkData.choices.length > 0) {
950
+ const choice = chunkData.choices[0];
951
+ if (choice.delta?.content) {
952
+ const content = choice.delta.content;
953
+ accumulatedContent += content;
954
+ if (onData) {
955
+ onData(content);
956
+ }
957
+ if (globalOnData) {
958
+ globalOnData(content);
959
+ }
960
+ }
961
+ if (choice.finish_reason) {
962
+ finishReason = choice.finish_reason;
963
+ }
964
+ }
965
+ }
966
+ }
967
+ const completion = {
968
+ id: completionId,
969
+ model: completionModel,
970
+ choices: [
971
+ {
972
+ index: 0,
973
+ message: {
974
+ role: "assistant",
975
+ content: accumulatedContent
976
+ },
977
+ finish_reason: finishReason
978
+ }
979
+ ],
980
+ usage
981
+ };
982
+ setIsLoading(false);
983
+ if (onFinish) {
984
+ onFinish(completion);
985
+ }
986
+ return { data: completion, error: null };
987
+ } catch (err) {
988
+ if (err instanceof Error && err.name === "AbortError") {
989
+ setIsLoading(false);
990
+ return { data: null, error: "Request aborted" };
991
+ }
992
+ const errorMsg = err instanceof Error ? err.message : "Failed to send message.";
993
+ const errorObj = err instanceof Error ? err : new Error(errorMsg);
994
+ setIsLoading(false);
995
+ if (onError) {
996
+ onError(errorObj);
997
+ }
998
+ return { data: null, error: errorMsg };
999
+ } finally {
1000
+ if (abortControllerRef.current === abortController) {
1001
+ abortControllerRef.current = null;
1002
+ }
1003
+ }
1004
+ },
1005
+ [getToken, globalOnData, onFinish, onError]
1006
+ );
1007
+ return {
1008
+ isLoading,
1009
+ sendMessage,
1010
+ stop
1011
+ };
1012
+ }
1013
+
1014
+ // src/react/useEncryption.ts
1015
+ var import_react2 = require("react");
1016
+ var import_react_auth = require("@privy-io/react-auth");
1017
+ var SIGN_MESSAGE = "The app is asking you to sign this message to generate a key, which will be used to encrypt data.";
1018
+ var SIGNATURE_STORAGE_KEY = "privy_encryption_key";
1019
+ function getStorageItem(key) {
1020
+ if (typeof window === "undefined" || !window.localStorage) {
1021
+ return null;
1022
+ }
1023
+ try {
1024
+ return localStorage.getItem(key);
1025
+ } catch {
1026
+ return null;
1027
+ }
1028
+ }
1029
+ function setStorageItem(key, value) {
1030
+ if (typeof window === "undefined" || !window.localStorage) {
1031
+ return false;
1032
+ }
1033
+ try {
1034
+ localStorage.setItem(key, value);
1035
+ return true;
1036
+ } catch {
1037
+ return false;
1038
+ }
1039
+ }
1040
+ function hexToBytes(hex) {
1041
+ const cleanHex = hex.startsWith("0x") ? hex.slice(2) : hex;
1042
+ const bytes = new Uint8Array(cleanHex.length / 2);
1043
+ for (let i = 0; i < cleanHex.length; i += 2) {
1044
+ bytes[i / 2] = parseInt(cleanHex.slice(i, i + 2), 16);
1045
+ }
1046
+ return bytes;
1047
+ }
1048
+ function bytesToHex(bytes) {
1049
+ return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
1050
+ }
1051
+ async function deriveKeyFromSignature(signature) {
1052
+ const sigBytes = hexToBytes(signature);
1053
+ const hashBuffer = await crypto.subtle.digest(
1054
+ "SHA-256",
1055
+ sigBytes.buffer
1056
+ );
1057
+ const hashBytes = new Uint8Array(hashBuffer);
1058
+ return bytesToHex(hashBytes);
1059
+ }
1060
+ async function getEncryptionKey() {
1061
+ const keyHex = getStorageItem(SIGNATURE_STORAGE_KEY);
1062
+ if (!keyHex) {
1063
+ throw new Error("Encryption key not found. Please sign in first.");
1064
+ }
1065
+ const keyBytes = hexToBytes(keyHex);
1066
+ return crypto.subtle.importKey(
1067
+ "raw",
1068
+ keyBytes.buffer,
1069
+ { name: "AES-GCM" },
1070
+ false,
1071
+ ["encrypt", "decrypt"]
1072
+ );
1073
+ }
1074
+ async function encryptData(plaintext) {
1075
+ const key = await getEncryptionKey();
1076
+ const plaintextBytes = typeof plaintext === "string" ? new TextEncoder().encode(plaintext) : plaintext;
1077
+ const iv = crypto.getRandomValues(new Uint8Array(12));
1078
+ const encryptedData = await crypto.subtle.encrypt(
1079
+ {
1080
+ name: "AES-GCM",
1081
+ iv
1082
+ },
1083
+ key,
1084
+ plaintextBytes.buffer
1085
+ );
1086
+ const encryptedBytes = new Uint8Array(encryptedData);
1087
+ const combined = new Uint8Array(iv.length + encryptedBytes.length);
1088
+ combined.set(iv, 0);
1089
+ combined.set(encryptedBytes, iv.length);
1090
+ return bytesToHex(combined);
1091
+ }
1092
+ async function decryptData(encryptedHex) {
1093
+ const key = await getEncryptionKey();
1094
+ const combined = hexToBytes(encryptedHex);
1095
+ const iv = combined.slice(0, 12);
1096
+ const encryptedData = combined.slice(12);
1097
+ const decryptedData = await crypto.subtle.decrypt(
1098
+ {
1099
+ name: "AES-GCM",
1100
+ iv
1101
+ },
1102
+ key,
1103
+ encryptedData
1104
+ );
1105
+ return new TextDecoder().decode(decryptedData);
1106
+ }
1107
+ async function decryptDataBytes(encryptedHex) {
1108
+ const key = await getEncryptionKey();
1109
+ const combined = hexToBytes(encryptedHex);
1110
+ const iv = combined.slice(0, 12);
1111
+ const encryptedData = combined.slice(12);
1112
+ const decryptedData = await crypto.subtle.decrypt(
1113
+ {
1114
+ name: "AES-GCM",
1115
+ iv
1116
+ },
1117
+ key,
1118
+ encryptedData
1119
+ );
1120
+ return new Uint8Array(decryptedData);
1121
+ }
1122
+ function useEncryption(authenticated) {
1123
+ const { signMessage } = (0, import_react_auth.useSignMessage)();
1124
+ const { wallets } = (0, import_react_auth.useWallets)();
1125
+ const hasRequestedSignature = (0, import_react2.useRef)(false);
1126
+ const hasCheckedStorage = (0, import_react2.useRef)(false);
1127
+ (0, import_react2.useEffect)(() => {
1128
+ if (!authenticated || wallets.length === 0) {
1129
+ return;
1130
+ }
1131
+ const existingKey = getStorageItem(SIGNATURE_STORAGE_KEY);
1132
+ if (existingKey) {
1133
+ if (!hasCheckedStorage.current) {
1134
+ hasCheckedStorage.current = true;
1135
+ }
1136
+ return;
1137
+ }
1138
+ const requestSignature = async () => {
1139
+ if (!hasRequestedSignature.current) {
1140
+ hasRequestedSignature.current = true;
1141
+ try {
1142
+ const { signature } = await signMessage(
1143
+ { message: SIGN_MESSAGE },
1144
+ {
1145
+ address: wallets[0].address
1146
+ }
1147
+ );
1148
+ const encryptionKey = await deriveKeyFromSignature(signature);
1149
+ const stored = setStorageItem(SIGNATURE_STORAGE_KEY, encryptionKey);
1150
+ if (!stored) {
1151
+ throw new Error("Failed to store encryption key in localStorage");
1152
+ }
1153
+ } catch (error) {
1154
+ hasRequestedSignature.current = false;
1155
+ }
1156
+ }
1157
+ };
1158
+ requestSignature();
1159
+ }, [
1160
+ authenticated,
1161
+ wallets.length > 0 ? wallets[0]?.address : null,
1162
+ signMessage
1163
+ ]);
1164
+ (0, import_react2.useEffect)(() => {
1165
+ if (!authenticated) {
1166
+ hasRequestedSignature.current = false;
1167
+ hasCheckedStorage.current = false;
1168
+ }
1169
+ }, [authenticated]);
1170
+ }
1171
+
1172
+ // src/react/useMemory.ts
1173
+ var import_react3 = require("react");
1174
+ var import_client6 = require("@reverbia/sdk");
1175
+
1176
+ // src/lib/memory/service.ts
1177
+ var FACT_EXTRACTION_PROMPT = `You are a memory extraction system. Extract durable user memories from chat messages.
1178
+
1179
+ CRITICAL: You MUST respond with ONLY valid JSON. No explanations, no markdown, no code blocks, just pure JSON.
1180
+
1181
+ Only extract facts that will be useful in future conversations, such as identity, stable preferences, ongoing projects, skills, and constraints.
1182
+
1183
+ Do not extract sensitive attributes, temporary things, or single-use instructions.
1184
+
1185
+ If there are no memories to extract, return: {"items": []}
1186
+
1187
+ Response format (JSON only, no other text):
1188
+
1189
+ {
1190
+ "items": [
1191
+ {
1192
+ "type": "identity",
1193
+ "namespace": "identity",
1194
+ "key": "name",
1195
+ "value": "Charlie",
1196
+ "rawEvidence": "I'm Charlie",
1197
+ "confidence": 0.98,
1198
+ "pii": true
1199
+ },
1200
+ {
1201
+ "type": "identity",
1202
+ "namespace": "work",
1203
+ "key": "company",
1204
+ "value": "ZetaChain",
1205
+ "rawEvidence": "called ZetaChain",
1206
+ "confidence": 0.99,
1207
+ "pii": false
1208
+ },
1209
+ {
1210
+ "type": "preference",
1211
+ "namespace": "answer_style",
1212
+ "key": "verbosity",
1213
+ "value": "concise_direct",
1214
+ "rawEvidence": "I prefer concise, direct answers",
1215
+ "confidence": 0.96,
1216
+ "pii": false
1217
+ },
1218
+ {
1219
+ "type": "identity",
1220
+ "namespace": "timezone",
1221
+ "key": "tz",
1222
+ "value": "America/Los_Angeles",
1223
+ "rawEvidence": "I'm in PST",
1224
+ "confidence": 0.9,
1225
+ "pii": false
1226
+ }
1227
+ ]
1228
+ }`;
1229
+ var preprocessMemories = (items, minConfidence = 0.6) => {
1230
+ if (!items || !Array.isArray(items)) {
1231
+ return [];
1232
+ }
1233
+ const validItems = items.filter((item) => {
1234
+ if (item.namespace == null || item.key == null || item.value == null) {
1235
+ console.warn(
1236
+ "Dropping memory item with null/undefined namespace, key, or value:",
1237
+ item
1238
+ );
1239
+ return false;
1058
1240
  }
1059
- const error = jsonError ?? textError;
1060
- let finalError = error;
1061
- for (const fn of interceptors.error.fns) {
1062
- if (fn) {
1063
- finalError = await fn(error, response, opts);
1064
- }
1241
+ const namespace = String(item.namespace).trim();
1242
+ const key = String(item.key).trim();
1243
+ const value = String(item.value).trim();
1244
+ if (namespace === "" || key === "" || value === "") {
1245
+ console.warn(
1246
+ "Dropping memory item with empty namespace, key, or value after trimming:",
1247
+ item
1248
+ );
1249
+ return false;
1065
1250
  }
1066
- finalError = finalError || {};
1067
- if (opts.throwOnError) {
1068
- throw finalError;
1251
+ if (typeof item.confidence !== "number" || item.confidence < minConfidence) {
1252
+ console.warn(
1253
+ `Dropping memory item with confidence ${item.confidence} below threshold ${minConfidence}:`,
1254
+ item
1255
+ );
1256
+ return false;
1069
1257
  }
1070
- return {
1071
- error: finalError,
1072
- ...result
1258
+ return true;
1259
+ });
1260
+ const deduplicatedMap = /* @__PURE__ */ new Map();
1261
+ for (const item of validItems) {
1262
+ const uniqueKey = `${item.namespace}:${item.key}:${item.value}`;
1263
+ const existing = deduplicatedMap.get(uniqueKey);
1264
+ if (!existing || item.confidence > existing.confidence) {
1265
+ deduplicatedMap.set(uniqueKey, item);
1266
+ } else {
1267
+ console.debug(
1268
+ `Deduplicating memory item: keeping entry with higher confidence (${existing.confidence} > ${item.confidence})`,
1269
+ { namespace: item.namespace, key: item.key, value: item.value }
1270
+ );
1271
+ }
1272
+ }
1273
+ return Array.from(deduplicatedMap.values());
1274
+ };
1275
+
1276
+ // src/lib/memory/db.ts
1277
+ var import_dexie = __toESM(require("dexie"));
1278
+ var MemoryDatabase = class extends import_dexie.default {
1279
+ constructor() {
1280
+ super("MemoryDatabase");
1281
+ this.version(2).stores({
1282
+ memories: "++id, uniqueKey, compositeKey, namespace, key, type, createdAt, updatedAt"
1283
+ });
1284
+ this.version(3).stores({
1285
+ memories: "++id, uniqueKey, compositeKey, namespace, key, type, createdAt, updatedAt"
1286
+ });
1287
+ }
1288
+ };
1289
+ var memoryDb = new MemoryDatabase();
1290
+ var saveMemory = async (memory) => {
1291
+ const compositeKey = `${memory.namespace}:${memory.key}`;
1292
+ const uniqueKey = `${memory.namespace}:${memory.key}:${memory.value}`;
1293
+ const now = Date.now();
1294
+ const existing = await memoryDb.memories.where("uniqueKey").equals(uniqueKey).first();
1295
+ if (existing) {
1296
+ const shouldPreserveEmbedding = existing.value === memory.value && existing.rawEvidence === memory.rawEvidence && existing.type === memory.type && existing.namespace === memory.namespace && existing.key === memory.key && existing.embedding !== void 0 && existing.embedding.length > 0;
1297
+ const updateData = {
1298
+ ...memory,
1299
+ compositeKey,
1300
+ uniqueKey,
1301
+ updatedAt: now,
1302
+ createdAt: existing.createdAt
1073
1303
  };
1074
- };
1075
- const makeMethodFn = (method) => (options) => request({ ...options, method });
1076
- const makeSseFn = (method) => async (options) => {
1077
- const { opts, url } = await beforeRequest(options);
1078
- return createSseClient({
1079
- ...opts,
1080
- body: opts.body,
1081
- headers: opts.headers,
1082
- method,
1083
- onRequest: async (url2, init) => {
1084
- let request2 = new Request(url2, init);
1085
- const requestInit = {
1086
- ...init,
1087
- method: init.method,
1088
- url: url2
1089
- };
1090
- for (const fn of interceptors.request.fns) {
1091
- if (fn) {
1092
- await fn(requestInit);
1093
- request2 = new Request(requestInit.url, requestInit);
1094
- }
1095
- }
1096
- return request2;
1097
- },
1098
- url
1304
+ if (shouldPreserveEmbedding) {
1305
+ updateData.embedding = existing.embedding;
1306
+ updateData.embeddingModel = existing.embeddingModel;
1307
+ } else {
1308
+ updateData.embedding = [];
1309
+ updateData.embeddingModel = void 0;
1310
+ }
1311
+ await memoryDb.memories.update(existing.id, updateData);
1312
+ } else {
1313
+ await memoryDb.memories.add({
1314
+ ...memory,
1315
+ compositeKey,
1316
+ uniqueKey,
1317
+ createdAt: now,
1318
+ updatedAt: now
1099
1319
  });
1100
- };
1101
- return {
1102
- buildUrl,
1103
- connect: makeMethodFn("CONNECT"),
1104
- delete: makeMethodFn("DELETE"),
1105
- get: makeMethodFn("GET"),
1106
- getConfig,
1107
- head: makeMethodFn("HEAD"),
1108
- interceptors,
1109
- options: makeMethodFn("OPTIONS"),
1110
- patch: makeMethodFn("PATCH"),
1111
- post: makeMethodFn("POST"),
1112
- put: makeMethodFn("PUT"),
1113
- request,
1114
- setConfig,
1115
- sse: {
1116
- connect: makeSseFn("CONNECT"),
1117
- delete: makeSseFn("DELETE"),
1118
- get: makeSseFn("GET"),
1119
- head: makeSseFn("HEAD"),
1120
- options: makeSseFn("OPTIONS"),
1121
- patch: makeSseFn("PATCH"),
1122
- post: makeSseFn("POST"),
1123
- put: makeSseFn("PUT"),
1124
- trace: makeSseFn("TRACE")
1125
- },
1126
- trace: makeMethodFn("TRACE")
1127
- };
1320
+ }
1321
+ };
1322
+ var saveMemories = async (memories) => {
1323
+ await Promise.all(memories.map((memory) => saveMemory(memory)));
1324
+ };
1325
+ var getAllMemories = async () => {
1326
+ return memoryDb.memories.toArray();
1327
+ };
1328
+ var cosineSimilarity = (a, b) => {
1329
+ if (a.length !== b.length) {
1330
+ throw new Error("Vectors must have the same length");
1331
+ }
1332
+ let dotProduct = 0;
1333
+ let normA = 0;
1334
+ let normB = 0;
1335
+ for (let i = 0; i < a.length; i++) {
1336
+ dotProduct += a[i] * b[i];
1337
+ normA += a[i] * a[i];
1338
+ normB += b[i] * b[i];
1339
+ }
1340
+ const denominator = Math.sqrt(normA) * Math.sqrt(normB);
1341
+ if (denominator === 0) {
1342
+ return 0;
1343
+ }
1344
+ return dotProduct / denominator;
1345
+ };
1346
+ var searchSimilarMemories = async (queryEmbedding, limit = 10, minSimilarity = 0.6) => {
1347
+ const allMemories = await getAllMemories();
1348
+ const memoriesWithEmbeddings = allMemories.filter(
1349
+ (m) => m.embedding && m.embedding.length > 0
1350
+ );
1351
+ console.log(
1352
+ `[Memory Search] Total memories: ${allMemories.length}, memories with embeddings: ${memoriesWithEmbeddings.length}`
1353
+ );
1354
+ if (memoriesWithEmbeddings.length === 0) {
1355
+ console.warn(
1356
+ "[Memory Search] No memories with embeddings found. Memories may need embeddings generated. Use generateAndStoreEmbeddings() to generate embeddings for existing memories."
1357
+ );
1358
+ return [];
1359
+ }
1360
+ const allResults = memoriesWithEmbeddings.map((memory) => {
1361
+ const similarity = cosineSimilarity(queryEmbedding, memory.embedding);
1362
+ return {
1363
+ ...memory,
1364
+ similarity
1365
+ };
1366
+ }).sort((a, b) => b.similarity - a.similarity);
1367
+ console.log(
1368
+ `[Memory Search] All similarity scores:`,
1369
+ allResults.map((r) => ({
1370
+ key: `${r.namespace}:${r.key}`,
1371
+ value: r.value,
1372
+ similarity: r.similarity.toFixed(4)
1373
+ }))
1374
+ );
1375
+ const results = allResults.filter((result) => result.similarity >= minSimilarity).slice(0, limit);
1376
+ if (results.length === 0 && allResults.length > 0) {
1377
+ const topSimilarity = allResults[0].similarity;
1378
+ const suggestedThreshold = Math.max(0.3, topSimilarity - 0.1);
1379
+ console.warn(
1380
+ `[Memory Search] No memories above threshold ${minSimilarity}. Highest similarity was ${topSimilarity.toFixed(4)}. Consider lowering the threshold to ${suggestedThreshold.toFixed(2)}`
1381
+ );
1382
+ } else {
1383
+ console.log(
1384
+ `[Memory Search] Found ${results.length} memories above similarity threshold ${minSimilarity}. Top similarity: ${results[0]?.similarity.toFixed(4) || "N/A"}`
1385
+ );
1386
+ }
1387
+ return results;
1128
1388
  };
1129
-
1130
- // src/clientConfig.ts
1131
- var createClientConfig = (config) => ({
1132
- ...config,
1133
- baseUrl: "https://ai-portal-dev.zetachain.com"
1134
- });
1135
-
1136
- // src/client/client.gen.ts
1137
- var client = createClient(createClientConfig(createConfig()));
1138
1389
 
1139
1390
  // src/client/sdk.gen.ts
1140
1391
  var postApiV1Embeddings = (options) => {
@@ -1252,8 +1503,8 @@ function useMemory(options = {}) {
1252
1503
  onFactsExtracted,
1253
1504
  getToken
1254
1505
  } = options;
1255
- const extractionInProgressRef = (0, import_react2.useRef)(false);
1256
- const extractMemoriesFromMessage = (0, import_react2.useCallback)(
1506
+ const extractionInProgressRef = (0, import_react3.useRef)(false);
1507
+ const extractMemoriesFromMessage = (0, import_react3.useCallback)(
1257
1508
  async (options2) => {
1258
1509
  const { messages, model } = options2;
1259
1510
  if (!getToken || extractionInProgressRef.current) {
@@ -1422,7 +1673,7 @@ function useMemory(options = {}) {
1422
1673
  onFactsExtracted
1423
1674
  ]
1424
1675
  );
1425
- const searchMemories = (0, import_react2.useCallback)(
1676
+ const searchMemories = (0, import_react3.useCallback)(
1426
1677
  async (query, limit = 10, minSimilarity = 0.6) => {
1427
1678
  if (!getToken || !embeddingModel) {
1428
1679
  console.warn(
@@ -1524,8 +1775,12 @@ var extractConversationContext = (messages, maxMessages = 3) => {
1524
1775
  // Annotate the CommonJS export names for ESM import in node:
1525
1776
  0 && (module.exports = {
1526
1777
  createMemoryContextSystemMessage,
1778
+ decryptData,
1779
+ decryptDataBytes,
1780
+ encryptData,
1527
1781
  extractConversationContext,
1528
1782
  formatMemoriesForChat,
1529
1783
  useChat,
1784
+ useEncryption,
1530
1785
  useMemory
1531
1786
  });