@reverbia/sdk 1.0.0 → 1.1.0-next.20251230221037

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 (110) hide show
  1. package/README.md +290 -45
  2. package/dist/expo/index.cjs +3428 -0
  3. package/dist/expo/index.d.mts +1217 -0
  4. package/dist/expo/index.d.ts +1217 -0
  5. package/dist/expo/index.mjs +3395 -0
  6. package/dist/index.cjs +972 -0
  7. package/dist/index.d.mts +1514 -0
  8. package/dist/index.d.ts +1514 -0
  9. package/dist/index.mjs +934 -0
  10. package/dist/next/index.cjs +64 -0
  11. package/dist/next/index.d.mts +23 -0
  12. package/dist/next/index.d.ts +23 -0
  13. package/dist/next/index.mjs +39 -0
  14. package/dist/polyfills/index.cjs +61 -0
  15. package/dist/polyfills/index.d.mts +9 -0
  16. package/dist/polyfills/index.d.ts +9 -0
  17. package/dist/polyfills/index.mjs +34 -0
  18. package/dist/react/chunk-KUFGQF6E.mjs +290 -0
  19. package/dist/react/chunk-T56Y62G7.mjs +410 -0
  20. package/dist/react/index.cjs +7982 -0
  21. package/dist/react/index.d.mts +3139 -0
  22. package/dist/react/index.d.ts +3139 -0
  23. package/dist/react/index.mjs +7209 -0
  24. package/dist/react/storage-Z2NBANCK.mjs +29 -0
  25. package/dist/react/useEncryption-5RTXKDNZ.mjs +31 -0
  26. package/dist/vercel/index.cjs +86 -0
  27. package/dist/vercel/index.d.mts +119 -0
  28. package/dist/vercel/index.d.ts +119 -0
  29. package/dist/vercel/index.mjs +57 -0
  30. package/package.json +91 -16
  31. package/dist/cjs/client/client/client.gen.d.ts +0 -2
  32. package/dist/cjs/client/client/client.gen.js +0 -203
  33. package/dist/cjs/client/client/index.d.ts +0 -8
  34. package/dist/cjs/client/client/index.js +0 -16
  35. package/dist/cjs/client/client/types.gen.d.ts +0 -99
  36. package/dist/cjs/client/client/types.gen.js +0 -3
  37. package/dist/cjs/client/client/utils.gen.d.ts +0 -40
  38. package/dist/cjs/client/client/utils.gen.js +0 -314
  39. package/dist/cjs/client/client.gen.d.ts +0 -12
  40. package/dist/cjs/client/client.gen.js +0 -6
  41. package/dist/cjs/client/core/auth.gen.d.ts +0 -18
  42. package/dist/cjs/client/core/auth.gen.js +0 -18
  43. package/dist/cjs/client/core/bodySerializer.gen.d.ts +0 -25
  44. package/dist/cjs/client/core/bodySerializer.gen.js +0 -60
  45. package/dist/cjs/client/core/params.gen.d.ts +0 -43
  46. package/dist/cjs/client/core/params.gen.js +0 -104
  47. package/dist/cjs/client/core/pathSerializer.gen.d.ts +0 -33
  48. package/dist/cjs/client/core/pathSerializer.gen.js +0 -123
  49. package/dist/cjs/client/core/queryKeySerializer.gen.d.ts +0 -18
  50. package/dist/cjs/client/core/queryKeySerializer.gen.js +0 -105
  51. package/dist/cjs/client/core/serverSentEvents.gen.d.ts +0 -71
  52. package/dist/cjs/client/core/serverSentEvents.gen.js +0 -139
  53. package/dist/cjs/client/core/types.gen.d.ts +0 -78
  54. package/dist/cjs/client/core/types.gen.js +0 -3
  55. package/dist/cjs/client/core/utils.gen.d.ts +0 -19
  56. package/dist/cjs/client/core/utils.gen.js +0 -93
  57. package/dist/cjs/client/index.d.ts +0 -2
  58. package/dist/cjs/client/index.js +0 -18
  59. package/dist/cjs/client/sdk.gen.d.ts +0 -27
  60. package/dist/cjs/client/sdk.gen.js +0 -33
  61. package/dist/cjs/client/types.gen.d.ts +0 -120
  62. package/dist/cjs/client/types.gen.js +0 -3
  63. package/dist/esm/client/client/client.gen.d.ts +0 -2
  64. package/dist/esm/client/client/client.gen.js +0 -199
  65. package/dist/esm/client/client/index.d.ts +0 -8
  66. package/dist/esm/client/client/index.js +0 -6
  67. package/dist/esm/client/client/types.gen.d.ts +0 -99
  68. package/dist/esm/client/client/types.gen.js +0 -2
  69. package/dist/esm/client/client/utils.gen.d.ts +0 -40
  70. package/dist/esm/client/client/utils.gen.js +0 -302
  71. package/dist/esm/client/client.gen.d.ts +0 -12
  72. package/dist/esm/client/client.gen.js +0 -3
  73. package/dist/esm/client/core/auth.gen.d.ts +0 -18
  74. package/dist/esm/client/core/auth.gen.js +0 -14
  75. package/dist/esm/client/core/bodySerializer.gen.d.ts +0 -25
  76. package/dist/esm/client/core/bodySerializer.gen.js +0 -57
  77. package/dist/esm/client/core/params.gen.d.ts +0 -43
  78. package/dist/esm/client/core/params.gen.js +0 -100
  79. package/dist/esm/client/core/pathSerializer.gen.d.ts +0 -33
  80. package/dist/esm/client/core/pathSerializer.gen.js +0 -114
  81. package/dist/esm/client/core/queryKeySerializer.gen.d.ts +0 -18
  82. package/dist/esm/client/core/queryKeySerializer.gen.js +0 -99
  83. package/dist/esm/client/core/serverSentEvents.gen.d.ts +0 -71
  84. package/dist/esm/client/core/serverSentEvents.gen.js +0 -135
  85. package/dist/esm/client/core/types.gen.d.ts +0 -78
  86. package/dist/esm/client/core/types.gen.js +0 -2
  87. package/dist/esm/client/core/utils.gen.d.ts +0 -19
  88. package/dist/esm/client/core/utils.gen.js +0 -87
  89. package/dist/esm/client/index.d.ts +0 -2
  90. package/dist/esm/client/index.js +0 -2
  91. package/dist/esm/client/sdk.gen.d.ts +0 -27
  92. package/dist/esm/client/sdk.gen.js +0 -28
  93. package/dist/esm/client/types.gen.d.ts +0 -120
  94. package/dist/esm/client/types.gen.js +0 -2
  95. package/dist/types/client/client/client.gen.d.ts +0 -2
  96. package/dist/types/client/client/index.d.ts +0 -8
  97. package/dist/types/client/client/types.gen.d.ts +0 -99
  98. package/dist/types/client/client/utils.gen.d.ts +0 -40
  99. package/dist/types/client/client.gen.d.ts +0 -12
  100. package/dist/types/client/core/auth.gen.d.ts +0 -18
  101. package/dist/types/client/core/bodySerializer.gen.d.ts +0 -25
  102. package/dist/types/client/core/params.gen.d.ts +0 -43
  103. package/dist/types/client/core/pathSerializer.gen.d.ts +0 -33
  104. package/dist/types/client/core/queryKeySerializer.gen.d.ts +0 -18
  105. package/dist/types/client/core/serverSentEvents.gen.d.ts +0 -71
  106. package/dist/types/client/core/types.gen.d.ts +0 -78
  107. package/dist/types/client/core/utils.gen.d.ts +0 -19
  108. package/dist/types/client/index.d.ts +0 -2
  109. package/dist/types/client/sdk.gen.d.ts +0 -27
  110. package/dist/types/client/types.gen.d.ts +0 -120
@@ -0,0 +1,3428 @@
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);
19
+ var __decorateClass = (decorators, target, key, kind) => {
20
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
21
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
22
+ if (decorator = decorators[i])
23
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
24
+ if (kind && result) __defProp(target, key, result);
25
+ return result;
26
+ };
27
+
28
+ // src/expo/index.ts
29
+ var index_exports = {};
30
+ __export(index_exports, {
31
+ ChatConversation: () => Conversation,
32
+ ChatMessage: () => Message,
33
+ StoredMemoryModel: () => Memory,
34
+ chatStorageMigrations: () => chatStorageMigrations,
35
+ chatStorageSchema: () => chatStorageSchema,
36
+ generateCompositeKey: () => generateCompositeKey,
37
+ generateConversationId: () => generateConversationId,
38
+ generateUniqueKey: () => generateUniqueKey,
39
+ memoryStorageSchema: () => memoryStorageSchema,
40
+ sdkMigrations: () => sdkMigrations,
41
+ sdkModelClasses: () => sdkModelClasses,
42
+ sdkSchema: () => sdkSchema,
43
+ useChat: () => useChat,
44
+ useChatStorage: () => useChatStorage,
45
+ useImageGeneration: () => useImageGeneration,
46
+ useMemoryStorage: () => useMemoryStorage,
47
+ useModels: () => useModels
48
+ });
49
+ module.exports = __toCommonJS(index_exports);
50
+
51
+ // src/expo/useChat.ts
52
+ var import_react = require("react");
53
+
54
+ // src/clientConfig.ts
55
+ var BASE_URL = "https://ai-portal-dev.zetachain.com";
56
+ var createClientConfig = (config) => ({
57
+ ...config,
58
+ baseUrl: BASE_URL
59
+ });
60
+
61
+ // src/lib/chat/useChat/utils.ts
62
+ var VALIDATION_ERROR_MESSAGES = {
63
+ messages_required: "messages are required to call sendMessage.",
64
+ model_required: "model is required to call sendMessage.",
65
+ token_getter_required: "Token getter function is required.",
66
+ token_unavailable: "No access token available."
67
+ };
68
+ function validateMessages(messages) {
69
+ if (!messages?.length) {
70
+ return {
71
+ valid: false,
72
+ error: "messages_required",
73
+ message: VALIDATION_ERROR_MESSAGES.messages_required
74
+ };
75
+ }
76
+ return { valid: true };
77
+ }
78
+ function validateModel(model) {
79
+ if (!model) {
80
+ return {
81
+ valid: false,
82
+ error: "model_required",
83
+ message: VALIDATION_ERROR_MESSAGES.model_required
84
+ };
85
+ }
86
+ return { valid: true };
87
+ }
88
+ function validateTokenGetter(getToken) {
89
+ if (!getToken) {
90
+ return {
91
+ valid: false,
92
+ error: "token_getter_required",
93
+ message: VALIDATION_ERROR_MESSAGES.token_getter_required
94
+ };
95
+ }
96
+ return { valid: true };
97
+ }
98
+ function validateToken(token) {
99
+ if (!token) {
100
+ return {
101
+ valid: false,
102
+ error: "token_unavailable",
103
+ message: VALIDATION_ERROR_MESSAGES.token_unavailable
104
+ };
105
+ }
106
+ return { valid: true };
107
+ }
108
+ function extractTextFromContentPart(part) {
109
+ if (part.type === "text" && part.text) {
110
+ return part.text;
111
+ }
112
+ return "";
113
+ }
114
+ function messagesToInput(messages) {
115
+ return messages.map((msg) => {
116
+ const role = msg.role || "user";
117
+ const content = Array.isArray(msg.content) ? msg.content.map(extractTextFromContentPart).filter(Boolean).join("\n") : String(msg.content || "");
118
+ return `${role}: ${content}`;
119
+ }).join("\n\n");
120
+ }
121
+ function createStreamAccumulator() {
122
+ return {
123
+ content: "",
124
+ thinking: "",
125
+ responseId: "",
126
+ responseModel: "",
127
+ usage: {}
128
+ };
129
+ }
130
+ function buildResponseResponse(accumulator) {
131
+ const output = [];
132
+ if (accumulator.thinking) {
133
+ output.push({
134
+ type: "reasoning",
135
+ role: "assistant",
136
+ content: [{ type: "output_text", text: accumulator.thinking }],
137
+ status: "completed"
138
+ });
139
+ }
140
+ output.push({
141
+ type: "message",
142
+ role: "assistant",
143
+ content: [{ type: "output_text", text: accumulator.content }],
144
+ status: "completed"
145
+ });
146
+ return {
147
+ id: accumulator.responseId,
148
+ model: accumulator.responseModel,
149
+ object: "response",
150
+ output,
151
+ usage: Object.keys(accumulator.usage).length > 0 ? accumulator.usage : void 0
152
+ };
153
+ }
154
+ function createErrorResult(message, onError) {
155
+ if (onError) {
156
+ onError(new Error(message));
157
+ }
158
+ return { data: null, error: message };
159
+ }
160
+ function handleError(err, onError) {
161
+ const errorMsg = err instanceof Error ? err.message : "Failed to send message.";
162
+ const errorObj = err instanceof Error ? err : new Error(errorMsg);
163
+ if (onError) {
164
+ onError(errorObj);
165
+ }
166
+ return { data: null, error: errorMsg };
167
+ }
168
+ function parseSSEDataLine(line) {
169
+ if (!line.startsWith("data: ")) {
170
+ return null;
171
+ }
172
+ const data = line.substring(6).trim();
173
+ if (data === "[DONE]") {
174
+ return null;
175
+ }
176
+ try {
177
+ return JSON.parse(data);
178
+ } catch {
179
+ return null;
180
+ }
181
+ }
182
+
183
+ // src/expo/useChat.ts
184
+ function processSSELines(lines, accumulator, onData, globalOnData, onThinking, globalOnThinking) {
185
+ for (const line of lines) {
186
+ const chunk = parseSSEDataLine(line);
187
+ if (!chunk) continue;
188
+ if (chunk.type === "response.created" && chunk.response && typeof chunk.response === "object") {
189
+ const response = chunk.response;
190
+ if (response.id && !accumulator.responseId) {
191
+ accumulator.responseId = response.id;
192
+ }
193
+ if (response.model && !accumulator.responseModel) {
194
+ accumulator.responseModel = response.model;
195
+ }
196
+ continue;
197
+ }
198
+ if (chunk.type === "response.completed" && chunk.response && typeof chunk.response === "object") {
199
+ const response = chunk.response;
200
+ if (response.usage) {
201
+ accumulator.usage = {
202
+ ...accumulator.usage,
203
+ prompt_tokens: response.usage.input_tokens,
204
+ completion_tokens: response.usage.output_tokens,
205
+ total_tokens: (response.usage.input_tokens || 0) + (response.usage.output_tokens || 0)
206
+ };
207
+ }
208
+ continue;
209
+ }
210
+ if (chunk.id && !accumulator.responseId) {
211
+ accumulator.responseId = chunk.id;
212
+ }
213
+ if (chunk.model && !accumulator.responseModel) {
214
+ accumulator.responseModel = chunk.model;
215
+ }
216
+ if (chunk.usage) {
217
+ accumulator.usage = { ...accumulator.usage, ...chunk.usage };
218
+ }
219
+ if (chunk.type === "response.reasoning.delta" || chunk.type === "response.reasoning_summary_text.delta" || chunk.type === "response.thinking.delta") {
220
+ const delta = chunk.delta;
221
+ if (delta) {
222
+ const deltaText = typeof delta === "string" ? delta : delta.OfString || delta.OfResponseReasoningSummaryDeltaEventDelta;
223
+ if (deltaText) {
224
+ accumulator.thinking += deltaText;
225
+ if (onThinking) onThinking(deltaText);
226
+ if (globalOnThinking) globalOnThinking(deltaText);
227
+ }
228
+ }
229
+ continue;
230
+ }
231
+ if (chunk.type === "response.output_text.delta" && chunk.delta) {
232
+ const deltaText = typeof chunk.delta === "string" ? chunk.delta : chunk.delta.OfString;
233
+ if (deltaText) {
234
+ accumulator.content += deltaText;
235
+ if (onData) onData(deltaText);
236
+ if (globalOnData) globalOnData(deltaText);
237
+ }
238
+ }
239
+ }
240
+ }
241
+ function useChat(options) {
242
+ const {
243
+ getToken,
244
+ baseUrl = BASE_URL,
245
+ onData: globalOnData,
246
+ onThinking: globalOnThinking,
247
+ onFinish,
248
+ onError
249
+ } = options || {};
250
+ const [isLoading, setIsLoading] = (0, import_react.useState)(false);
251
+ const abortControllerRef = (0, import_react.useRef)(null);
252
+ const stop = (0, import_react.useCallback)(() => {
253
+ if (abortControllerRef.current) {
254
+ abortControllerRef.current.abort();
255
+ abortControllerRef.current = null;
256
+ }
257
+ }, []);
258
+ (0, import_react.useEffect)(() => {
259
+ return () => {
260
+ if (abortControllerRef.current) {
261
+ abortControllerRef.current.abort();
262
+ abortControllerRef.current = null;
263
+ }
264
+ };
265
+ }, []);
266
+ const sendMessage = (0, import_react.useCallback)(
267
+ async ({
268
+ messages,
269
+ model,
270
+ onData,
271
+ onThinking,
272
+ // Responses API options
273
+ store,
274
+ previousResponseId,
275
+ conversation,
276
+ temperature,
277
+ maxOutputTokens,
278
+ tools,
279
+ toolChoice,
280
+ reasoning,
281
+ thinking
282
+ }) => {
283
+ const messagesValidation = validateMessages(messages);
284
+ if (!messagesValidation.valid) {
285
+ return createErrorResult(messagesValidation.message, onError);
286
+ }
287
+ const modelValidation = validateModel(model);
288
+ if (!modelValidation.valid) {
289
+ return createErrorResult(modelValidation.message, onError);
290
+ }
291
+ const tokenGetterValidation = validateTokenGetter(getToken);
292
+ if (!tokenGetterValidation.valid) {
293
+ return createErrorResult(tokenGetterValidation.message, onError);
294
+ }
295
+ if (abortControllerRef.current) {
296
+ abortControllerRef.current.abort();
297
+ }
298
+ const abortController = new AbortController();
299
+ abortControllerRef.current = abortController;
300
+ setIsLoading(true);
301
+ try {
302
+ const token = await getToken();
303
+ const tokenValidation = validateToken(token);
304
+ if (!tokenValidation.valid) {
305
+ setIsLoading(false);
306
+ return createErrorResult(tokenValidation.message, onError);
307
+ }
308
+ const result = await new Promise((resolve) => {
309
+ const xhr = new XMLHttpRequest();
310
+ const url = `${baseUrl}/api/v1/responses`;
311
+ const accumulator = createStreamAccumulator();
312
+ let lastProcessedIndex = 0;
313
+ let incompleteLineBuffer = "";
314
+ const abortHandler = () => {
315
+ xhr.abort();
316
+ };
317
+ abortController.signal.addEventListener("abort", abortHandler);
318
+ xhr.open("POST", url, true);
319
+ xhr.setRequestHeader("Content-Type", "application/json");
320
+ xhr.setRequestHeader("Authorization", `Bearer ${token}`);
321
+ xhr.setRequestHeader("Accept", "text/event-stream");
322
+ xhr.onprogress = () => {
323
+ const newData = xhr.responseText.substring(lastProcessedIndex);
324
+ lastProcessedIndex = xhr.responseText.length;
325
+ const dataToProcess = incompleteLineBuffer + newData;
326
+ incompleteLineBuffer = "";
327
+ const lines = dataToProcess.split("\n");
328
+ if (!newData.endsWith("\n") && lines.length > 0) {
329
+ incompleteLineBuffer = lines.pop() || "";
330
+ }
331
+ processSSELines(lines, accumulator, onData, globalOnData, onThinking, globalOnThinking);
332
+ };
333
+ xhr.onload = () => {
334
+ abortController.signal.removeEventListener("abort", abortHandler);
335
+ if (incompleteLineBuffer) {
336
+ processSSELines(
337
+ [incompleteLineBuffer.trim()],
338
+ accumulator,
339
+ onData,
340
+ globalOnData,
341
+ onThinking,
342
+ globalOnThinking
343
+ );
344
+ incompleteLineBuffer = "";
345
+ }
346
+ if (xhr.status >= 200 && xhr.status < 300) {
347
+ const response = buildResponseResponse(accumulator);
348
+ setIsLoading(false);
349
+ if (onFinish) onFinish(response);
350
+ resolve({ data: response, error: null });
351
+ } else {
352
+ const errorMsg = `Request failed with status ${xhr.status}`;
353
+ setIsLoading(false);
354
+ if (onError) onError(new Error(errorMsg));
355
+ resolve({ data: null, error: errorMsg });
356
+ }
357
+ };
358
+ xhr.onerror = () => {
359
+ abortController.signal.removeEventListener("abort", abortHandler);
360
+ const errorMsg = "Network error";
361
+ setIsLoading(false);
362
+ if (onError) onError(new Error(errorMsg));
363
+ resolve({ data: null, error: errorMsg });
364
+ };
365
+ xhr.onabort = () => {
366
+ abortController.signal.removeEventListener("abort", abortHandler);
367
+ setIsLoading(false);
368
+ resolve({ data: null, error: "Request aborted" });
369
+ };
370
+ xhr.send(
371
+ JSON.stringify({
372
+ input: messagesToInput(messages),
373
+ model,
374
+ stream: true,
375
+ // Responses API options (only include if defined)
376
+ ...store !== void 0 && { store },
377
+ ...previousResponseId && { previous_response_id: previousResponseId },
378
+ ...conversation && { conversation },
379
+ ...temperature !== void 0 && { temperature },
380
+ ...maxOutputTokens !== void 0 && { max_output_tokens: maxOutputTokens },
381
+ ...tools && { tools },
382
+ ...toolChoice && { tool_choice: toolChoice },
383
+ ...reasoning && { reasoning },
384
+ ...thinking && { thinking }
385
+ })
386
+ );
387
+ });
388
+ return result;
389
+ } catch (err) {
390
+ setIsLoading(false);
391
+ return handleError(err, onError);
392
+ } finally {
393
+ if (abortControllerRef.current === abortController) {
394
+ abortControllerRef.current = null;
395
+ }
396
+ }
397
+ },
398
+ [getToken, baseUrl, globalOnData, globalOnThinking, onFinish, onError]
399
+ );
400
+ return {
401
+ isLoading,
402
+ sendMessage,
403
+ stop
404
+ };
405
+ }
406
+
407
+ // src/expo/useChatStorage.ts
408
+ var import_react2 = require("react");
409
+
410
+ // src/lib/db/chat/schema.ts
411
+ var import_watermelondb = require("@nozbe/watermelondb");
412
+ var import_migrations = require("@nozbe/watermelondb/Schema/migrations");
413
+ var chatStorageSchema = (0, import_watermelondb.appSchema)({
414
+ version: 5,
415
+ tables: [
416
+ (0, import_watermelondb.tableSchema)({
417
+ name: "history",
418
+ columns: [
419
+ { name: "message_id", type: "number" },
420
+ { name: "conversation_id", type: "string", isIndexed: true },
421
+ { name: "role", type: "string", isIndexed: true },
422
+ { name: "content", type: "string" },
423
+ { name: "model", type: "string", isOptional: true },
424
+ { name: "files", type: "string", isOptional: true },
425
+ { name: "created_at", type: "number", isIndexed: true },
426
+ { name: "updated_at", type: "number" },
427
+ { name: "vector", type: "string", isOptional: true },
428
+ { name: "embedding_model", type: "string", isOptional: true },
429
+ { name: "usage", type: "string", isOptional: true },
430
+ { name: "sources", type: "string", isOptional: true },
431
+ { name: "response_duration", type: "number", isOptional: true },
432
+ { name: "was_stopped", type: "boolean", isOptional: true },
433
+ { name: "error", type: "string", isOptional: true },
434
+ { name: "thought_process", type: "string", isOptional: true },
435
+ // JSON stringified ActivityPhase[]
436
+ { name: "thinking", type: "string", isOptional: true }
437
+ // Reasoning/thinking content
438
+ ]
439
+ }),
440
+ (0, import_watermelondb.tableSchema)({
441
+ name: "conversations",
442
+ columns: [
443
+ { name: "conversation_id", type: "string", isIndexed: true },
444
+ { name: "title", type: "string" },
445
+ { name: "created_at", type: "number" },
446
+ { name: "updated_at", type: "number" },
447
+ { name: "is_deleted", type: "boolean", isIndexed: true }
448
+ ]
449
+ })
450
+ ]
451
+ });
452
+ var chatStorageMigrations = (0, import_migrations.schemaMigrations)({
453
+ migrations: [
454
+ {
455
+ toVersion: 2,
456
+ steps: [
457
+ (0, import_migrations.addColumns)({
458
+ table: "history",
459
+ columns: [{ name: "was_stopped", type: "boolean", isOptional: true }]
460
+ })
461
+ ]
462
+ },
463
+ {
464
+ toVersion: 3,
465
+ steps: [
466
+ (0, import_migrations.addColumns)({
467
+ table: "history",
468
+ columns: [{ name: "error", type: "string", isOptional: true }]
469
+ })
470
+ ]
471
+ },
472
+ {
473
+ toVersion: 4,
474
+ steps: [
475
+ (0, import_migrations.addColumns)({
476
+ table: "history",
477
+ columns: [
478
+ { name: "thought_process", type: "string", isOptional: true }
479
+ ]
480
+ })
481
+ ]
482
+ },
483
+ {
484
+ toVersion: 5,
485
+ steps: [
486
+ (0, import_migrations.addColumns)({
487
+ table: "history",
488
+ columns: [
489
+ { name: "thinking", type: "string", isOptional: true }
490
+ ]
491
+ })
492
+ ]
493
+ }
494
+ ]
495
+ });
496
+
497
+ // src/lib/db/chat/models.ts
498
+ var import_watermelondb2 = require("@nozbe/watermelondb");
499
+ var import_decorators = require("@nozbe/watermelondb/decorators");
500
+ var Message = class extends import_watermelondb2.Model {
501
+ };
502
+ Message.table = "history";
503
+ Message.associations = {
504
+ conversations: { type: "belongs_to", key: "conversation_id" }
505
+ };
506
+ __decorateClass([
507
+ (0, import_decorators.field)("message_id")
508
+ ], Message.prototype, "messageId", 2);
509
+ __decorateClass([
510
+ (0, import_decorators.text)("conversation_id")
511
+ ], Message.prototype, "conversationId", 2);
512
+ __decorateClass([
513
+ (0, import_decorators.text)("role")
514
+ ], Message.prototype, "role", 2);
515
+ __decorateClass([
516
+ (0, import_decorators.text)("content")
517
+ ], Message.prototype, "content", 2);
518
+ __decorateClass([
519
+ (0, import_decorators.text)("model")
520
+ ], Message.prototype, "model", 2);
521
+ __decorateClass([
522
+ (0, import_decorators.json)("files", (json3) => json3)
523
+ ], Message.prototype, "files", 2);
524
+ __decorateClass([
525
+ (0, import_decorators.date)("created_at")
526
+ ], Message.prototype, "createdAt", 2);
527
+ __decorateClass([
528
+ (0, import_decorators.date)("updated_at")
529
+ ], Message.prototype, "updatedAt", 2);
530
+ __decorateClass([
531
+ (0, import_decorators.json)("vector", (json3) => json3)
532
+ ], Message.prototype, "vector", 2);
533
+ __decorateClass([
534
+ (0, import_decorators.text)("embedding_model")
535
+ ], Message.prototype, "embeddingModel", 2);
536
+ __decorateClass([
537
+ (0, import_decorators.json)("usage", (json3) => json3)
538
+ ], Message.prototype, "usage", 2);
539
+ __decorateClass([
540
+ (0, import_decorators.json)("sources", (json3) => json3)
541
+ ], Message.prototype, "sources", 2);
542
+ __decorateClass([
543
+ (0, import_decorators.field)("response_duration")
544
+ ], Message.prototype, "responseDuration", 2);
545
+ __decorateClass([
546
+ (0, import_decorators.field)("was_stopped")
547
+ ], Message.prototype, "wasStopped", 2);
548
+ __decorateClass([
549
+ (0, import_decorators.text)("error")
550
+ ], Message.prototype, "error", 2);
551
+ __decorateClass([
552
+ (0, import_decorators.json)("thought_process", (json3) => json3)
553
+ ], Message.prototype, "thoughtProcess", 2);
554
+ __decorateClass([
555
+ (0, import_decorators.text)("thinking")
556
+ ], Message.prototype, "thinking", 2);
557
+ var Conversation = class extends import_watermelondb2.Model {
558
+ };
559
+ Conversation.table = "conversations";
560
+ Conversation.associations = {
561
+ history: { type: "has_many", foreignKey: "conversation_id" }
562
+ };
563
+ __decorateClass([
564
+ (0, import_decorators.text)("conversation_id")
565
+ ], Conversation.prototype, "conversationId", 2);
566
+ __decorateClass([
567
+ (0, import_decorators.text)("title")
568
+ ], Conversation.prototype, "title", 2);
569
+ __decorateClass([
570
+ (0, import_decorators.date)("created_at")
571
+ ], Conversation.prototype, "createdAt", 2);
572
+ __decorateClass([
573
+ (0, import_decorators.date)("updated_at")
574
+ ], Conversation.prototype, "updatedAt", 2);
575
+ __decorateClass([
576
+ (0, import_decorators.field)("is_deleted")
577
+ ], Conversation.prototype, "isDeleted", 2);
578
+
579
+ // src/lib/db/chat/types.ts
580
+ function generateConversationId() {
581
+ return `conv_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
582
+ }
583
+ function convertUsageToStored(usage) {
584
+ if (!usage) return void 0;
585
+ return {
586
+ promptTokens: usage.prompt_tokens,
587
+ completionTokens: usage.completion_tokens,
588
+ totalTokens: usage.total_tokens,
589
+ costMicroUsd: usage.cost_micro_usd
590
+ };
591
+ }
592
+ function finalizeThoughtProcess(thoughtProcess) {
593
+ if (!thoughtProcess?.length) return thoughtProcess;
594
+ return thoughtProcess.map(
595
+ (phase, idx) => idx === thoughtProcess.length - 1 ? { ...phase, status: "completed" } : phase
596
+ );
597
+ }
598
+
599
+ // src/lib/db/chat/operations.ts
600
+ var import_watermelondb3 = require("@nozbe/watermelondb");
601
+ function messageToStored(message) {
602
+ return {
603
+ uniqueId: message.id,
604
+ messageId: message.messageId,
605
+ conversationId: message.conversationId,
606
+ role: message.role,
607
+ content: message.content,
608
+ model: message.model,
609
+ files: message.files,
610
+ createdAt: message.createdAt,
611
+ updatedAt: message.updatedAt,
612
+ vector: message.vector,
613
+ embeddingModel: message.embeddingModel,
614
+ usage: message.usage,
615
+ sources: message.sources,
616
+ responseDuration: message.responseDuration,
617
+ wasStopped: message.wasStopped,
618
+ error: message.error,
619
+ thoughtProcess: message.thoughtProcess,
620
+ thinking: message.thinking
621
+ };
622
+ }
623
+ function conversationToStored(conversation) {
624
+ return {
625
+ uniqueId: conversation.id,
626
+ conversationId: conversation.conversationId,
627
+ title: conversation.title,
628
+ createdAt: conversation.createdAt,
629
+ updatedAt: conversation.updatedAt,
630
+ isDeleted: conversation.isDeleted
631
+ };
632
+ }
633
+ async function createConversationOp(ctx, opts, defaultTitle = "New Conversation") {
634
+ const convId = opts?.conversationId || generateConversationId();
635
+ const title = opts?.title || defaultTitle;
636
+ const created = await ctx.database.write(async () => {
637
+ return await ctx.conversationsCollection.create((conv) => {
638
+ conv._setRaw("conversation_id", convId);
639
+ conv._setRaw("title", title);
640
+ conv._setRaw("is_deleted", false);
641
+ });
642
+ });
643
+ return conversationToStored(created);
644
+ }
645
+ async function getConversationOp(ctx, id) {
646
+ const results = await ctx.conversationsCollection.query(import_watermelondb3.Q.where("conversation_id", id), import_watermelondb3.Q.where("is_deleted", false)).fetch();
647
+ return results.length > 0 ? conversationToStored(results[0]) : null;
648
+ }
649
+ async function getConversationsOp(ctx) {
650
+ const results = await ctx.conversationsCollection.query(import_watermelondb3.Q.where("is_deleted", false), import_watermelondb3.Q.sortBy("created_at", import_watermelondb3.Q.desc)).fetch();
651
+ return results.map(conversationToStored);
652
+ }
653
+ async function updateConversationTitleOp(ctx, id, title) {
654
+ const results = await ctx.conversationsCollection.query(import_watermelondb3.Q.where("conversation_id", id), import_watermelondb3.Q.where("is_deleted", false)).fetch();
655
+ if (results.length > 0) {
656
+ await ctx.database.write(async () => {
657
+ await results[0].update((conv) => {
658
+ conv._setRaw("title", title);
659
+ });
660
+ });
661
+ return true;
662
+ }
663
+ return false;
664
+ }
665
+ async function deleteConversationOp(ctx, id) {
666
+ const results = await ctx.conversationsCollection.query(import_watermelondb3.Q.where("conversation_id", id), import_watermelondb3.Q.where("is_deleted", false)).fetch();
667
+ if (results.length > 0) {
668
+ await ctx.database.write(async () => {
669
+ await results[0].update((conv) => {
670
+ conv._setRaw("is_deleted", true);
671
+ });
672
+ });
673
+ return true;
674
+ }
675
+ return false;
676
+ }
677
+ async function getMessagesOp(ctx, convId) {
678
+ const results = await ctx.messagesCollection.query(import_watermelondb3.Q.where("conversation_id", convId), import_watermelondb3.Q.sortBy("message_id", import_watermelondb3.Q.asc)).fetch();
679
+ return results.map(messageToStored);
680
+ }
681
+ async function getMessageCountOp(ctx, convId) {
682
+ return await ctx.messagesCollection.query(import_watermelondb3.Q.where("conversation_id", convId)).fetchCount();
683
+ }
684
+ async function clearMessagesOp(ctx, convId) {
685
+ const messages = await ctx.messagesCollection.query(import_watermelondb3.Q.where("conversation_id", convId)).fetch();
686
+ await ctx.database.write(async () => {
687
+ for (const message of messages) {
688
+ await message.destroyPermanently();
689
+ }
690
+ });
691
+ }
692
+ async function createMessageOp(ctx, opts) {
693
+ const existingCount = await getMessageCountOp(ctx, opts.conversationId);
694
+ const messageId = existingCount + 1;
695
+ const created = await ctx.database.write(async () => {
696
+ return await ctx.messagesCollection.create((msg) => {
697
+ msg._setRaw("message_id", messageId);
698
+ msg._setRaw("conversation_id", opts.conversationId);
699
+ msg._setRaw("role", opts.role);
700
+ msg._setRaw("content", opts.content);
701
+ if (opts.model) msg._setRaw("model", opts.model);
702
+ if (opts.files) msg._setRaw("files", JSON.stringify(opts.files));
703
+ if (opts.usage) msg._setRaw("usage", JSON.stringify(opts.usage));
704
+ if (opts.sources) msg._setRaw("sources", JSON.stringify(opts.sources));
705
+ if (opts.responseDuration !== void 0)
706
+ msg._setRaw("response_duration", opts.responseDuration);
707
+ if (opts.vector) msg._setRaw("vector", JSON.stringify(opts.vector));
708
+ if (opts.embeddingModel)
709
+ msg._setRaw("embedding_model", opts.embeddingModel);
710
+ if (opts.wasStopped) msg._setRaw("was_stopped", opts.wasStopped);
711
+ if (opts.error) msg._setRaw("error", opts.error);
712
+ if (opts.thoughtProcess)
713
+ msg._setRaw("thought_process", JSON.stringify(opts.thoughtProcess));
714
+ if (opts.thinking) msg._setRaw("thinking", opts.thinking);
715
+ });
716
+ });
717
+ return messageToStored(created);
718
+ }
719
+ async function updateMessageErrorOp(ctx, uniqueId, error) {
720
+ let message;
721
+ try {
722
+ message = await ctx.messagesCollection.find(uniqueId);
723
+ } catch {
724
+ return null;
725
+ }
726
+ await ctx.database.write(async () => {
727
+ await message.update((msg) => {
728
+ msg._setRaw("error", error);
729
+ });
730
+ });
731
+ return messageToStored(message);
732
+ }
733
+ async function updateMessageOp(ctx, uniqueId, opts) {
734
+ let message;
735
+ try {
736
+ message = await ctx.messagesCollection.find(uniqueId);
737
+ } catch {
738
+ return null;
739
+ }
740
+ await ctx.database.write(async () => {
741
+ await message.update((msg) => {
742
+ if (opts.content !== void 0) msg._setRaw("content", opts.content);
743
+ if (opts.model !== void 0) msg._setRaw("model", opts.model);
744
+ if (opts.files !== void 0)
745
+ msg._setRaw("files", JSON.stringify(opts.files));
746
+ if (opts.usage !== void 0)
747
+ msg._setRaw("usage", JSON.stringify(opts.usage));
748
+ if (opts.sources !== void 0)
749
+ msg._setRaw("sources", JSON.stringify(opts.sources));
750
+ if (opts.responseDuration !== void 0)
751
+ msg._setRaw("response_duration", opts.responseDuration);
752
+ if (opts.vector !== void 0)
753
+ msg._setRaw("vector", JSON.stringify(opts.vector));
754
+ if (opts.embeddingModel !== void 0)
755
+ msg._setRaw("embedding_model", opts.embeddingModel);
756
+ if (opts.wasStopped !== void 0)
757
+ msg._setRaw("was_stopped", opts.wasStopped);
758
+ if (opts.error !== void 0)
759
+ msg._setRaw("error", opts.error === null ? "" : opts.error);
760
+ if (opts.thoughtProcess !== void 0)
761
+ msg._setRaw("thought_process", JSON.stringify(opts.thoughtProcess));
762
+ if (opts.thinking !== void 0)
763
+ msg._setRaw("thinking", opts.thinking === null ? "" : opts.thinking);
764
+ });
765
+ });
766
+ return messageToStored(message);
767
+ }
768
+
769
+ // src/expo/useChatStorage.ts
770
+ function storedToLlmapiMessage(stored) {
771
+ const content = [
772
+ { type: "text", text: stored.content }
773
+ ];
774
+ if (stored.files?.length) {
775
+ for (const file of stored.files) {
776
+ if (file.url) {
777
+ content.push({
778
+ type: "image_url",
779
+ image_url: { url: file.url }
780
+ });
781
+ }
782
+ }
783
+ }
784
+ return {
785
+ role: stored.role,
786
+ content
787
+ };
788
+ }
789
+ function useChatStorage(options) {
790
+ const {
791
+ database,
792
+ conversationId: initialConversationId,
793
+ autoCreateConversation = true,
794
+ defaultConversationTitle = "New Conversation",
795
+ getToken,
796
+ baseUrl,
797
+ onData,
798
+ onFinish,
799
+ onError
800
+ } = options;
801
+ const [currentConversationId, setCurrentConversationId] = (0, import_react2.useState)(initialConversationId || null);
802
+ const messagesCollection = (0, import_react2.useMemo)(
803
+ () => database.get("history"),
804
+ [database]
805
+ );
806
+ const conversationsCollection = (0, import_react2.useMemo)(
807
+ () => database.get("conversations"),
808
+ [database]
809
+ );
810
+ const storageCtx = (0, import_react2.useMemo)(
811
+ () => ({
812
+ database,
813
+ messagesCollection,
814
+ conversationsCollection
815
+ }),
816
+ [database, messagesCollection, conversationsCollection]
817
+ );
818
+ const {
819
+ isLoading,
820
+ sendMessage: baseSendMessage,
821
+ stop
822
+ } = useChat({
823
+ getToken,
824
+ baseUrl,
825
+ onData,
826
+ onFinish,
827
+ onError
828
+ });
829
+ const createConversation = (0, import_react2.useCallback)(
830
+ async (opts) => {
831
+ const created = await createConversationOp(
832
+ storageCtx,
833
+ opts,
834
+ defaultConversationTitle
835
+ );
836
+ setCurrentConversationId(created.conversationId);
837
+ return created;
838
+ },
839
+ [storageCtx, defaultConversationTitle]
840
+ );
841
+ const getConversation = (0, import_react2.useCallback)(
842
+ async (id) => {
843
+ return getConversationOp(storageCtx, id);
844
+ },
845
+ [storageCtx]
846
+ );
847
+ const getConversations = (0, import_react2.useCallback)(async () => {
848
+ return getConversationsOp(storageCtx);
849
+ }, [storageCtx]);
850
+ const updateConversationTitle = (0, import_react2.useCallback)(
851
+ async (id, title) => {
852
+ return updateConversationTitleOp(storageCtx, id, title);
853
+ },
854
+ [storageCtx]
855
+ );
856
+ const deleteConversation = (0, import_react2.useCallback)(
857
+ async (id) => {
858
+ const deleted = await deleteConversationOp(storageCtx, id);
859
+ if (deleted && currentConversationId === id) {
860
+ setCurrentConversationId(null);
861
+ }
862
+ return deleted;
863
+ },
864
+ [storageCtx, currentConversationId]
865
+ );
866
+ const getMessages = (0, import_react2.useCallback)(
867
+ async (convId) => {
868
+ return getMessagesOp(storageCtx, convId);
869
+ },
870
+ [storageCtx]
871
+ );
872
+ const getMessageCount = (0, import_react2.useCallback)(
873
+ async (convId) => {
874
+ return getMessageCountOp(storageCtx, convId);
875
+ },
876
+ [storageCtx]
877
+ );
878
+ const clearMessages = (0, import_react2.useCallback)(
879
+ async (convId) => {
880
+ return clearMessagesOp(storageCtx, convId);
881
+ },
882
+ [storageCtx]
883
+ );
884
+ const updateMessage = (0, import_react2.useCallback)(
885
+ async (uniqueId, options2) => {
886
+ return updateMessageOp(storageCtx, uniqueId, options2);
887
+ },
888
+ [storageCtx]
889
+ );
890
+ const extractSourcesFromAssistantMessage = (0, import_react2.useCallback)(
891
+ (assistantMessage) => {
892
+ try {
893
+ const extractedSources = [];
894
+ const seenUrls = /* @__PURE__ */ new Set();
895
+ if (assistantMessage.sources) {
896
+ for (const source of assistantMessage.sources) {
897
+ if (source.url) {
898
+ seenUrls.add(source.url);
899
+ }
900
+ extractedSources.push(source);
901
+ }
902
+ }
903
+ const content = assistantMessage.content;
904
+ if (!content) {
905
+ return extractedSources;
906
+ }
907
+ const markdownLinkRegex = /\[([^\]]*)\]\(([^()]*(?:\([^()]*\)[^()]*)*)\)/g;
908
+ const plainUrlRegex = /https?:\/\/[^\s<>\[\]()'"]+/g;
909
+ let match;
910
+ while ((match = markdownLinkRegex.exec(content)) !== null) {
911
+ const title = match[1].trim();
912
+ const url = match[2].trim();
913
+ if (url && !seenUrls.has(url)) {
914
+ seenUrls.add(url);
915
+ extractedSources.push({
916
+ title: title || void 0,
917
+ url
918
+ });
919
+ }
920
+ }
921
+ while ((match = plainUrlRegex.exec(content)) !== null) {
922
+ const url = match[0].replace(/[.,;:!?]+$/, "").trim();
923
+ if (url && !seenUrls.has(url)) {
924
+ seenUrls.add(url);
925
+ try {
926
+ const urlObj = new URL(url);
927
+ extractedSources.push({
928
+ title: urlObj.hostname,
929
+ url
930
+ });
931
+ } catch {
932
+ extractedSources.push({
933
+ url
934
+ });
935
+ }
936
+ }
937
+ }
938
+ return extractedSources;
939
+ } catch {
940
+ return [];
941
+ }
942
+ },
943
+ []
944
+ );
945
+ const ensureConversation = (0, import_react2.useCallback)(async () => {
946
+ if (currentConversationId) {
947
+ const existing = await getConversation(currentConversationId);
948
+ if (existing) {
949
+ return currentConversationId;
950
+ }
951
+ if (autoCreateConversation) {
952
+ const newConv = await createConversation({
953
+ conversationId: currentConversationId
954
+ });
955
+ return newConv.conversationId;
956
+ }
957
+ }
958
+ if (autoCreateConversation) {
959
+ const newConv = await createConversation();
960
+ return newConv.conversationId;
961
+ }
962
+ throw new Error(
963
+ "No conversation ID provided and autoCreateConversation is disabled"
964
+ );
965
+ }, [
966
+ currentConversationId,
967
+ getConversation,
968
+ autoCreateConversation,
969
+ createConversation
970
+ ]);
971
+ const sendMessage = (0, import_react2.useCallback)(
972
+ async (args) => {
973
+ const {
974
+ content,
975
+ model,
976
+ messages: providedMessages,
977
+ includeHistory = true,
978
+ maxHistoryMessages = 50,
979
+ files,
980
+ onData: perRequestOnData,
981
+ onThinking: perRequestOnThinking,
982
+ sources,
983
+ thoughtProcess,
984
+ // Responses API options
985
+ store,
986
+ previousResponseId,
987
+ serverConversation,
988
+ temperature,
989
+ maxOutputTokens,
990
+ tools,
991
+ toolChoice,
992
+ reasoning,
993
+ thinking
994
+ } = args;
995
+ let convId;
996
+ try {
997
+ convId = await ensureConversation();
998
+ } catch (err) {
999
+ return {
1000
+ data: null,
1001
+ error: err instanceof Error ? err.message : "Failed to ensure conversation"
1002
+ };
1003
+ }
1004
+ let messagesToSend = [];
1005
+ if (includeHistory && !providedMessages) {
1006
+ const storedMessages = await getMessages(convId);
1007
+ const validMessages = storedMessages.filter((msg) => !msg.error);
1008
+ const limitedMessages = validMessages.slice(-maxHistoryMessages);
1009
+ messagesToSend = limitedMessages.map(storedToLlmapiMessage);
1010
+ } else if (providedMessages) {
1011
+ messagesToSend = providedMessages;
1012
+ }
1013
+ const userMessageContent = [
1014
+ { type: "text", text: content }
1015
+ ];
1016
+ if (files?.length) {
1017
+ for (const file of files) {
1018
+ if (file.url) {
1019
+ userMessageContent.push({
1020
+ type: "image_url",
1021
+ image_url: { url: file.url }
1022
+ });
1023
+ }
1024
+ }
1025
+ }
1026
+ const userMessage = {
1027
+ role: "user",
1028
+ content: userMessageContent
1029
+ };
1030
+ messagesToSend.push(userMessage);
1031
+ const sanitizedFiles = files?.map((file) => ({
1032
+ id: file.id,
1033
+ name: file.name,
1034
+ type: file.type,
1035
+ size: file.size,
1036
+ // Only keep URL if it's not a data URI (e.g., external URLs)
1037
+ url: file.url && !file.url.startsWith("data:") ? file.url : void 0
1038
+ }));
1039
+ let storedUserMessage;
1040
+ try {
1041
+ storedUserMessage = await createMessageOp(storageCtx, {
1042
+ conversationId: convId,
1043
+ role: "user",
1044
+ content,
1045
+ files: sanitizedFiles,
1046
+ model
1047
+ });
1048
+ } catch (err) {
1049
+ return {
1050
+ data: null,
1051
+ error: err instanceof Error ? err.message : "Failed to store user message"
1052
+ };
1053
+ }
1054
+ const startTime = Date.now();
1055
+ const result = await baseSendMessage({
1056
+ messages: messagesToSend,
1057
+ model,
1058
+ onData: perRequestOnData,
1059
+ onThinking: perRequestOnThinking,
1060
+ // Responses API options
1061
+ store,
1062
+ previousResponseId,
1063
+ conversation: serverConversation,
1064
+ temperature,
1065
+ maxOutputTokens,
1066
+ tools,
1067
+ toolChoice,
1068
+ reasoning,
1069
+ thinking
1070
+ });
1071
+ const responseDuration = (Date.now() - startTime) / 1e3;
1072
+ if (result.error || !result.data) {
1073
+ const abortedResult = result;
1074
+ if (abortedResult.error === "Request aborted") {
1075
+ const assistantContent2 = abortedResult.data?.output?.[0]?.content?.map((part) => part.text || "").join("") || "";
1076
+ const responseModel = abortedResult.data?.model || model || "";
1077
+ let storedAssistantMessage2;
1078
+ try {
1079
+ storedAssistantMessage2 = await createMessageOp(storageCtx, {
1080
+ conversationId: convId,
1081
+ role: "assistant",
1082
+ content: assistantContent2,
1083
+ model: responseModel,
1084
+ usage: convertUsageToStored(abortedResult.data?.usage),
1085
+ responseDuration,
1086
+ wasStopped: true,
1087
+ sources,
1088
+ thoughtProcess: finalizeThoughtProcess(thoughtProcess)
1089
+ });
1090
+ const responseData2 = abortedResult.data || {
1091
+ id: `aborted-${Date.now()}`,
1092
+ model: responseModel,
1093
+ object: "response",
1094
+ output: [{
1095
+ type: "message",
1096
+ role: "assistant",
1097
+ content: [{ type: "output_text", text: assistantContent2 }],
1098
+ status: "completed"
1099
+ }],
1100
+ usage: void 0
1101
+ };
1102
+ return {
1103
+ data: responseData2,
1104
+ error: null,
1105
+ // Treat as success to the caller
1106
+ userMessage: storedUserMessage,
1107
+ assistantMessage: storedAssistantMessage2
1108
+ };
1109
+ } catch {
1110
+ return {
1111
+ data: null,
1112
+ error: "Request aborted",
1113
+ userMessage: storedUserMessage
1114
+ };
1115
+ }
1116
+ }
1117
+ const errorMessage = result.error || "No response data received";
1118
+ try {
1119
+ await updateMessageErrorOp(
1120
+ storageCtx,
1121
+ storedUserMessage.uniqueId,
1122
+ errorMessage
1123
+ );
1124
+ await createMessageOp(storageCtx, {
1125
+ conversationId: convId,
1126
+ role: "assistant",
1127
+ content: "",
1128
+ model: model || "",
1129
+ responseDuration,
1130
+ sources,
1131
+ thoughtProcess: finalizeThoughtProcess(thoughtProcess),
1132
+ error: errorMessage
1133
+ });
1134
+ } catch {
1135
+ }
1136
+ return {
1137
+ data: null,
1138
+ error: errorMessage,
1139
+ userMessage: { ...storedUserMessage, error: errorMessage }
1140
+ };
1141
+ }
1142
+ const responseData = result.data;
1143
+ const messageOutput = responseData.output?.find(
1144
+ (item) => item.type === "message"
1145
+ );
1146
+ const assistantContent = messageOutput?.content?.map((part) => part.text || "").join("") || "";
1147
+ const reasoningOutput = responseData.output?.find(
1148
+ (item) => item.type === "reasoning"
1149
+ );
1150
+ const thinkingContent = reasoningOutput?.content?.map((part) => part.text || "").join("") || void 0;
1151
+ const combinedSources = extractSourcesFromAssistantMessage({
1152
+ content: assistantContent,
1153
+ sources
1154
+ });
1155
+ let storedAssistantMessage;
1156
+ try {
1157
+ storedAssistantMessage = await createMessageOp(storageCtx, {
1158
+ conversationId: convId,
1159
+ role: "assistant",
1160
+ content: assistantContent,
1161
+ model: responseData.model || model,
1162
+ usage: convertUsageToStored(responseData.usage),
1163
+ responseDuration,
1164
+ sources: combinedSources,
1165
+ thoughtProcess: finalizeThoughtProcess(thoughtProcess),
1166
+ thinking: thinkingContent
1167
+ });
1168
+ } catch (err) {
1169
+ return {
1170
+ data: null,
1171
+ error: err instanceof Error ? err.message : "Failed to store assistant message",
1172
+ userMessage: storedUserMessage
1173
+ };
1174
+ }
1175
+ return {
1176
+ data: responseData,
1177
+ error: null,
1178
+ userMessage: storedUserMessage,
1179
+ assistantMessage: storedAssistantMessage
1180
+ };
1181
+ },
1182
+ [ensureConversation, getMessages, storageCtx, baseSendMessage]
1183
+ );
1184
+ return {
1185
+ isLoading,
1186
+ sendMessage,
1187
+ stop,
1188
+ conversationId: currentConversationId,
1189
+ setConversationId: setCurrentConversationId,
1190
+ createConversation,
1191
+ getConversation,
1192
+ getConversations,
1193
+ updateConversationTitle,
1194
+ deleteConversation,
1195
+ getMessages,
1196
+ getMessageCount,
1197
+ clearMessages,
1198
+ extractSourcesFromAssistantMessage,
1199
+ updateMessage
1200
+ };
1201
+ }
1202
+
1203
+ // src/react/useImageGeneration.ts
1204
+ var import_react3 = require("react");
1205
+
1206
+ // src/client/core/bodySerializer.gen.ts
1207
+ var jsonBodySerializer = {
1208
+ bodySerializer: (body) => JSON.stringify(
1209
+ body,
1210
+ (_key, value) => typeof value === "bigint" ? value.toString() : value
1211
+ )
1212
+ };
1213
+
1214
+ // src/client/core/params.gen.ts
1215
+ var extraPrefixesMap = {
1216
+ $body_: "body",
1217
+ $headers_: "headers",
1218
+ $path_: "path",
1219
+ $query_: "query"
1220
+ };
1221
+ var extraPrefixes = Object.entries(extraPrefixesMap);
1222
+
1223
+ // src/client/core/serverSentEvents.gen.ts
1224
+ var createSseClient = ({
1225
+ onRequest,
1226
+ onSseError,
1227
+ onSseEvent,
1228
+ responseTransformer,
1229
+ responseValidator,
1230
+ sseDefaultRetryDelay,
1231
+ sseMaxRetryAttempts,
1232
+ sseMaxRetryDelay,
1233
+ sseSleepFn,
1234
+ url,
1235
+ ...options
1236
+ }) => {
1237
+ let lastEventId;
1238
+ const sleep = sseSleepFn ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
1239
+ const createStream = async function* () {
1240
+ let retryDelay = sseDefaultRetryDelay ?? 3e3;
1241
+ let attempt = 0;
1242
+ const signal = options.signal ?? new AbortController().signal;
1243
+ while (true) {
1244
+ if (signal.aborted) break;
1245
+ attempt++;
1246
+ const headers = options.headers instanceof Headers ? options.headers : new Headers(options.headers);
1247
+ if (lastEventId !== void 0) {
1248
+ headers.set("Last-Event-ID", lastEventId);
1249
+ }
1250
+ try {
1251
+ const requestInit = {
1252
+ redirect: "follow",
1253
+ ...options,
1254
+ body: options.serializedBody,
1255
+ headers,
1256
+ signal
1257
+ };
1258
+ let request = new Request(url, requestInit);
1259
+ if (onRequest) {
1260
+ request = await onRequest(url, requestInit);
1261
+ }
1262
+ const _fetch = options.fetch ?? globalThis.fetch;
1263
+ const response = await _fetch(request);
1264
+ if (!response.ok)
1265
+ throw new Error(
1266
+ `SSE failed: ${response.status} ${response.statusText}`
1267
+ );
1268
+ if (!response.body) throw new Error("No body in SSE response");
1269
+ const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
1270
+ let buffer = "";
1271
+ const abortHandler = () => {
1272
+ try {
1273
+ reader.cancel();
1274
+ } catch {
1275
+ }
1276
+ };
1277
+ signal.addEventListener("abort", abortHandler);
1278
+ try {
1279
+ while (true) {
1280
+ const { done, value } = await reader.read();
1281
+ if (done) break;
1282
+ buffer += value;
1283
+ const chunks = buffer.split("\n\n");
1284
+ buffer = chunks.pop() ?? "";
1285
+ for (const chunk of chunks) {
1286
+ const lines = chunk.split("\n");
1287
+ const dataLines = [];
1288
+ let eventName;
1289
+ for (const line of lines) {
1290
+ if (line.startsWith("data:")) {
1291
+ dataLines.push(line.replace(/^data:\s*/, ""));
1292
+ } else if (line.startsWith("event:")) {
1293
+ eventName = line.replace(/^event:\s*/, "");
1294
+ } else if (line.startsWith("id:")) {
1295
+ lastEventId = line.replace(/^id:\s*/, "");
1296
+ } else if (line.startsWith("retry:")) {
1297
+ const parsed = Number.parseInt(
1298
+ line.replace(/^retry:\s*/, ""),
1299
+ 10
1300
+ );
1301
+ if (!Number.isNaN(parsed)) {
1302
+ retryDelay = parsed;
1303
+ }
1304
+ }
1305
+ }
1306
+ let data;
1307
+ let parsedJson = false;
1308
+ if (dataLines.length) {
1309
+ const rawData = dataLines.join("\n");
1310
+ try {
1311
+ data = JSON.parse(rawData);
1312
+ parsedJson = true;
1313
+ } catch {
1314
+ data = rawData;
1315
+ }
1316
+ }
1317
+ if (parsedJson) {
1318
+ if (responseValidator) {
1319
+ await responseValidator(data);
1320
+ }
1321
+ if (responseTransformer) {
1322
+ data = await responseTransformer(data);
1323
+ }
1324
+ }
1325
+ onSseEvent?.({
1326
+ data,
1327
+ event: eventName,
1328
+ id: lastEventId,
1329
+ retry: retryDelay
1330
+ });
1331
+ if (dataLines.length) {
1332
+ yield data;
1333
+ }
1334
+ }
1335
+ }
1336
+ } finally {
1337
+ signal.removeEventListener("abort", abortHandler);
1338
+ reader.releaseLock();
1339
+ }
1340
+ break;
1341
+ } catch (error) {
1342
+ onSseError?.(error);
1343
+ if (sseMaxRetryAttempts !== void 0 && attempt >= sseMaxRetryAttempts) {
1344
+ break;
1345
+ }
1346
+ const backoff = Math.min(
1347
+ retryDelay * 2 ** (attempt - 1),
1348
+ sseMaxRetryDelay ?? 3e4
1349
+ );
1350
+ await sleep(backoff);
1351
+ }
1352
+ }
1353
+ };
1354
+ const stream = createStream();
1355
+ return { stream };
1356
+ };
1357
+
1358
+ // src/client/core/pathSerializer.gen.ts
1359
+ var separatorArrayExplode = (style) => {
1360
+ switch (style) {
1361
+ case "label":
1362
+ return ".";
1363
+ case "matrix":
1364
+ return ";";
1365
+ case "simple":
1366
+ return ",";
1367
+ default:
1368
+ return "&";
1369
+ }
1370
+ };
1371
+ var separatorArrayNoExplode = (style) => {
1372
+ switch (style) {
1373
+ case "form":
1374
+ return ",";
1375
+ case "pipeDelimited":
1376
+ return "|";
1377
+ case "spaceDelimited":
1378
+ return "%20";
1379
+ default:
1380
+ return ",";
1381
+ }
1382
+ };
1383
+ var separatorObjectExplode = (style) => {
1384
+ switch (style) {
1385
+ case "label":
1386
+ return ".";
1387
+ case "matrix":
1388
+ return ";";
1389
+ case "simple":
1390
+ return ",";
1391
+ default:
1392
+ return "&";
1393
+ }
1394
+ };
1395
+ var serializeArrayParam = ({
1396
+ allowReserved,
1397
+ explode,
1398
+ name,
1399
+ style,
1400
+ value
1401
+ }) => {
1402
+ if (!explode) {
1403
+ const joinedValues2 = (allowReserved ? value : value.map((v) => encodeURIComponent(v))).join(separatorArrayNoExplode(style));
1404
+ switch (style) {
1405
+ case "label":
1406
+ return `.${joinedValues2}`;
1407
+ case "matrix":
1408
+ return `;${name}=${joinedValues2}`;
1409
+ case "simple":
1410
+ return joinedValues2;
1411
+ default:
1412
+ return `${name}=${joinedValues2}`;
1413
+ }
1414
+ }
1415
+ const separator = separatorArrayExplode(style);
1416
+ const joinedValues = value.map((v) => {
1417
+ if (style === "label" || style === "simple") {
1418
+ return allowReserved ? v : encodeURIComponent(v);
1419
+ }
1420
+ return serializePrimitiveParam({
1421
+ allowReserved,
1422
+ name,
1423
+ value: v
1424
+ });
1425
+ }).join(separator);
1426
+ return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
1427
+ };
1428
+ var serializePrimitiveParam = ({
1429
+ allowReserved,
1430
+ name,
1431
+ value
1432
+ }) => {
1433
+ if (value === void 0 || value === null) {
1434
+ return "";
1435
+ }
1436
+ if (typeof value === "object") {
1437
+ throw new Error(
1438
+ "Deeply-nested arrays/objects aren\u2019t supported. Provide your own `querySerializer()` to handle these."
1439
+ );
1440
+ }
1441
+ return `${name}=${allowReserved ? value : encodeURIComponent(value)}`;
1442
+ };
1443
+ var serializeObjectParam = ({
1444
+ allowReserved,
1445
+ explode,
1446
+ name,
1447
+ style,
1448
+ value,
1449
+ valueOnly
1450
+ }) => {
1451
+ if (value instanceof Date) {
1452
+ return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`;
1453
+ }
1454
+ if (style !== "deepObject" && !explode) {
1455
+ let values = [];
1456
+ Object.entries(value).forEach(([key, v]) => {
1457
+ values = [
1458
+ ...values,
1459
+ key,
1460
+ allowReserved ? v : encodeURIComponent(v)
1461
+ ];
1462
+ });
1463
+ const joinedValues2 = values.join(",");
1464
+ switch (style) {
1465
+ case "form":
1466
+ return `${name}=${joinedValues2}`;
1467
+ case "label":
1468
+ return `.${joinedValues2}`;
1469
+ case "matrix":
1470
+ return `;${name}=${joinedValues2}`;
1471
+ default:
1472
+ return joinedValues2;
1473
+ }
1474
+ }
1475
+ const separator = separatorObjectExplode(style);
1476
+ const joinedValues = Object.entries(value).map(
1477
+ ([key, v]) => serializePrimitiveParam({
1478
+ allowReserved,
1479
+ name: style === "deepObject" ? `${name}[${key}]` : key,
1480
+ value: v
1481
+ })
1482
+ ).join(separator);
1483
+ return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
1484
+ };
1485
+
1486
+ // src/client/core/utils.gen.ts
1487
+ function getValidRequestBody(options) {
1488
+ const hasBody = options.body !== void 0;
1489
+ const isSerializedBody = hasBody && options.bodySerializer;
1490
+ if (isSerializedBody) {
1491
+ if ("serializedBody" in options) {
1492
+ const hasSerializedBody = options.serializedBody !== void 0 && options.serializedBody !== "";
1493
+ return hasSerializedBody ? options.serializedBody : null;
1494
+ }
1495
+ return options.body !== "" ? options.body : null;
1496
+ }
1497
+ if (hasBody) {
1498
+ return options.body;
1499
+ }
1500
+ return void 0;
1501
+ }
1502
+
1503
+ // src/client/core/auth.gen.ts
1504
+ var getAuthToken = async (auth, callback) => {
1505
+ const token = typeof callback === "function" ? await callback(auth) : callback;
1506
+ if (!token) {
1507
+ return;
1508
+ }
1509
+ if (auth.scheme === "bearer") {
1510
+ return `Bearer ${token}`;
1511
+ }
1512
+ if (auth.scheme === "basic") {
1513
+ return `Basic ${btoa(token)}`;
1514
+ }
1515
+ return token;
1516
+ };
1517
+
1518
+ // src/client/client/utils.gen.ts
1519
+ var PATH_PARAM_RE = /\{[^{}]+\}/g;
1520
+ var defaultPathSerializer = ({ path, url: _url }) => {
1521
+ let url = _url;
1522
+ const matches = _url.match(PATH_PARAM_RE);
1523
+ if (matches) {
1524
+ for (const match of matches) {
1525
+ let explode = false;
1526
+ let name = match.substring(1, match.length - 1);
1527
+ let style = "simple";
1528
+ if (name.endsWith("*")) {
1529
+ explode = true;
1530
+ name = name.substring(0, name.length - 1);
1531
+ }
1532
+ if (name.startsWith(".")) {
1533
+ name = name.substring(1);
1534
+ style = "label";
1535
+ } else if (name.startsWith(";")) {
1536
+ name = name.substring(1);
1537
+ style = "matrix";
1538
+ }
1539
+ const value = path[name];
1540
+ if (value === void 0 || value === null) {
1541
+ continue;
1542
+ }
1543
+ if (Array.isArray(value)) {
1544
+ url = url.replace(
1545
+ match,
1546
+ serializeArrayParam({ explode, name, style, value })
1547
+ );
1548
+ continue;
1549
+ }
1550
+ if (typeof value === "object") {
1551
+ url = url.replace(
1552
+ match,
1553
+ serializeObjectParam({
1554
+ explode,
1555
+ name,
1556
+ style,
1557
+ value,
1558
+ valueOnly: true
1559
+ })
1560
+ );
1561
+ continue;
1562
+ }
1563
+ if (style === "matrix") {
1564
+ url = url.replace(
1565
+ match,
1566
+ `;${serializePrimitiveParam({
1567
+ name,
1568
+ value
1569
+ })}`
1570
+ );
1571
+ continue;
1572
+ }
1573
+ const replaceValue = encodeURIComponent(
1574
+ style === "label" ? `.${value}` : value
1575
+ );
1576
+ url = url.replace(match, replaceValue);
1577
+ }
1578
+ }
1579
+ return url;
1580
+ };
1581
+ var createQuerySerializer = ({
1582
+ parameters = {},
1583
+ ...args
1584
+ } = {}) => {
1585
+ const querySerializer = (queryParams) => {
1586
+ const search = [];
1587
+ if (queryParams && typeof queryParams === "object") {
1588
+ for (const name in queryParams) {
1589
+ const value = queryParams[name];
1590
+ if (value === void 0 || value === null) {
1591
+ continue;
1592
+ }
1593
+ const options = parameters[name] || args;
1594
+ if (Array.isArray(value)) {
1595
+ const serializedArray = serializeArrayParam({
1596
+ allowReserved: options.allowReserved,
1597
+ explode: true,
1598
+ name,
1599
+ style: "form",
1600
+ value,
1601
+ ...options.array
1602
+ });
1603
+ if (serializedArray) search.push(serializedArray);
1604
+ } else if (typeof value === "object") {
1605
+ const serializedObject = serializeObjectParam({
1606
+ allowReserved: options.allowReserved,
1607
+ explode: true,
1608
+ name,
1609
+ style: "deepObject",
1610
+ value,
1611
+ ...options.object
1612
+ });
1613
+ if (serializedObject) search.push(serializedObject);
1614
+ } else {
1615
+ const serializedPrimitive = serializePrimitiveParam({
1616
+ allowReserved: options.allowReserved,
1617
+ name,
1618
+ value
1619
+ });
1620
+ if (serializedPrimitive) search.push(serializedPrimitive);
1621
+ }
1622
+ }
1623
+ }
1624
+ return search.join("&");
1625
+ };
1626
+ return querySerializer;
1627
+ };
1628
+ var getParseAs = (contentType) => {
1629
+ if (!contentType) {
1630
+ return "stream";
1631
+ }
1632
+ const cleanContent = contentType.split(";")[0]?.trim();
1633
+ if (!cleanContent) {
1634
+ return;
1635
+ }
1636
+ if (cleanContent.startsWith("application/json") || cleanContent.endsWith("+json")) {
1637
+ return "json";
1638
+ }
1639
+ if (cleanContent === "multipart/form-data") {
1640
+ return "formData";
1641
+ }
1642
+ if (["application/", "audio/", "image/", "video/"].some(
1643
+ (type) => cleanContent.startsWith(type)
1644
+ )) {
1645
+ return "blob";
1646
+ }
1647
+ if (cleanContent.startsWith("text/")) {
1648
+ return "text";
1649
+ }
1650
+ return;
1651
+ };
1652
+ var checkForExistence = (options, name) => {
1653
+ if (!name) {
1654
+ return false;
1655
+ }
1656
+ if (options.headers.has(name) || options.query?.[name] || options.headers.get("Cookie")?.includes(`${name}=`)) {
1657
+ return true;
1658
+ }
1659
+ return false;
1660
+ };
1661
+ var setAuthParams = async ({
1662
+ security,
1663
+ ...options
1664
+ }) => {
1665
+ for (const auth of security) {
1666
+ if (checkForExistence(options, auth.name)) {
1667
+ continue;
1668
+ }
1669
+ const token = await getAuthToken(auth, options.auth);
1670
+ if (!token) {
1671
+ continue;
1672
+ }
1673
+ const name = auth.name ?? "Authorization";
1674
+ switch (auth.in) {
1675
+ case "query":
1676
+ if (!options.query) {
1677
+ options.query = {};
1678
+ }
1679
+ options.query[name] = token;
1680
+ break;
1681
+ case "cookie":
1682
+ options.headers.append("Cookie", `${name}=${token}`);
1683
+ break;
1684
+ case "header":
1685
+ default:
1686
+ options.headers.set(name, token);
1687
+ break;
1688
+ }
1689
+ }
1690
+ };
1691
+ var buildUrl = (options) => {
1692
+ const url = getUrl({
1693
+ baseUrl: options.baseUrl,
1694
+ path: options.path,
1695
+ query: options.query,
1696
+ querySerializer: typeof options.querySerializer === "function" ? options.querySerializer : createQuerySerializer(options.querySerializer),
1697
+ url: options.url
1698
+ });
1699
+ return url;
1700
+ };
1701
+ var getUrl = ({
1702
+ baseUrl,
1703
+ path,
1704
+ query,
1705
+ querySerializer,
1706
+ url: _url
1707
+ }) => {
1708
+ const pathUrl = _url.startsWith("/") ? _url : `/${_url}`;
1709
+ let url = (baseUrl ?? "") + pathUrl;
1710
+ if (path) {
1711
+ url = defaultPathSerializer({ path, url });
1712
+ }
1713
+ let search = query ? querySerializer(query) : "";
1714
+ if (search.startsWith("?")) {
1715
+ search = search.substring(1);
1716
+ }
1717
+ if (search) {
1718
+ url += `?${search}`;
1719
+ }
1720
+ return url;
1721
+ };
1722
+ var mergeConfigs = (a, b) => {
1723
+ const config = { ...a, ...b };
1724
+ if (config.baseUrl?.endsWith("/")) {
1725
+ config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1);
1726
+ }
1727
+ config.headers = mergeHeaders(a.headers, b.headers);
1728
+ return config;
1729
+ };
1730
+ var headersEntries = (headers) => {
1731
+ const entries = [];
1732
+ headers.forEach((value, key) => {
1733
+ entries.push([key, value]);
1734
+ });
1735
+ return entries;
1736
+ };
1737
+ var mergeHeaders = (...headers) => {
1738
+ const mergedHeaders = new Headers();
1739
+ for (const header of headers) {
1740
+ if (!header || typeof header !== "object") {
1741
+ continue;
1742
+ }
1743
+ const iterator = header instanceof Headers ? headersEntries(header) : Object.entries(header);
1744
+ for (const [key, value] of iterator) {
1745
+ if (value === null) {
1746
+ mergedHeaders.delete(key);
1747
+ } else if (Array.isArray(value)) {
1748
+ for (const v of value) {
1749
+ mergedHeaders.append(key, v);
1750
+ }
1751
+ } else if (value !== void 0) {
1752
+ mergedHeaders.set(
1753
+ key,
1754
+ typeof value === "object" ? JSON.stringify(value) : value
1755
+ );
1756
+ }
1757
+ }
1758
+ }
1759
+ return mergedHeaders;
1760
+ };
1761
+ var Interceptors = class {
1762
+ constructor() {
1763
+ this.fns = [];
1764
+ }
1765
+ clear() {
1766
+ this.fns = [];
1767
+ }
1768
+ eject(id) {
1769
+ const index = this.getInterceptorIndex(id);
1770
+ if (this.fns[index]) {
1771
+ this.fns[index] = null;
1772
+ }
1773
+ }
1774
+ exists(id) {
1775
+ const index = this.getInterceptorIndex(id);
1776
+ return Boolean(this.fns[index]);
1777
+ }
1778
+ getInterceptorIndex(id) {
1779
+ if (typeof id === "number") {
1780
+ return this.fns[id] ? id : -1;
1781
+ }
1782
+ return this.fns.indexOf(id);
1783
+ }
1784
+ update(id, fn) {
1785
+ const index = this.getInterceptorIndex(id);
1786
+ if (this.fns[index]) {
1787
+ this.fns[index] = fn;
1788
+ return id;
1789
+ }
1790
+ return false;
1791
+ }
1792
+ use(fn) {
1793
+ this.fns.push(fn);
1794
+ return this.fns.length - 1;
1795
+ }
1796
+ };
1797
+ var createInterceptors = () => ({
1798
+ error: new Interceptors(),
1799
+ request: new Interceptors(),
1800
+ response: new Interceptors()
1801
+ });
1802
+ var defaultQuerySerializer = createQuerySerializer({
1803
+ allowReserved: false,
1804
+ array: {
1805
+ explode: true,
1806
+ style: "form"
1807
+ },
1808
+ object: {
1809
+ explode: true,
1810
+ style: "deepObject"
1811
+ }
1812
+ });
1813
+ var defaultHeaders = {
1814
+ "Content-Type": "application/json"
1815
+ };
1816
+ var createConfig = (override = {}) => ({
1817
+ ...jsonBodySerializer,
1818
+ headers: defaultHeaders,
1819
+ parseAs: "auto",
1820
+ querySerializer: defaultQuerySerializer,
1821
+ ...override
1822
+ });
1823
+
1824
+ // src/client/client/client.gen.ts
1825
+ var createClient = (config = {}) => {
1826
+ let _config = mergeConfigs(createConfig(), config);
1827
+ const getConfig = () => ({ ..._config });
1828
+ const setConfig = (config2) => {
1829
+ _config = mergeConfigs(_config, config2);
1830
+ return getConfig();
1831
+ };
1832
+ const interceptors = createInterceptors();
1833
+ const beforeRequest = async (options) => {
1834
+ const opts = {
1835
+ ..._config,
1836
+ ...options,
1837
+ fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,
1838
+ headers: mergeHeaders(_config.headers, options.headers),
1839
+ serializedBody: void 0
1840
+ };
1841
+ if (opts.security) {
1842
+ await setAuthParams({
1843
+ ...opts,
1844
+ security: opts.security
1845
+ });
1846
+ }
1847
+ if (opts.requestValidator) {
1848
+ await opts.requestValidator(opts);
1849
+ }
1850
+ if (opts.body !== void 0 && opts.bodySerializer) {
1851
+ opts.serializedBody = opts.bodySerializer(opts.body);
1852
+ }
1853
+ if (opts.body === void 0 || opts.serializedBody === "") {
1854
+ opts.headers.delete("Content-Type");
1855
+ }
1856
+ const url = buildUrl(opts);
1857
+ return { opts, url };
1858
+ };
1859
+ const request = async (options) => {
1860
+ const { opts, url } = await beforeRequest(options);
1861
+ for (const fn of interceptors.request.fns) {
1862
+ if (fn) {
1863
+ await fn(opts);
1864
+ }
1865
+ }
1866
+ const _fetch = opts.fetch;
1867
+ const requestInit = {
1868
+ ...opts,
1869
+ body: getValidRequestBody(opts)
1870
+ };
1871
+ let response = await _fetch(url, requestInit);
1872
+ for (const fn of interceptors.response.fns) {
1873
+ if (fn) {
1874
+ response = await fn(response, opts);
1875
+ }
1876
+ }
1877
+ const result = {
1878
+ response
1879
+ };
1880
+ if (response.ok) {
1881
+ const parseAs = (opts.parseAs === "auto" ? getParseAs(response.headers.get("Content-Type")) : opts.parseAs) ?? "json";
1882
+ if (response.status === 204 || response.headers.get("Content-Length") === "0") {
1883
+ let emptyData;
1884
+ switch (parseAs) {
1885
+ case "arrayBuffer":
1886
+ case "blob":
1887
+ case "text":
1888
+ emptyData = await response[parseAs]();
1889
+ break;
1890
+ case "formData":
1891
+ emptyData = new FormData();
1892
+ break;
1893
+ case "stream":
1894
+ emptyData = response.body;
1895
+ break;
1896
+ case "json":
1897
+ default:
1898
+ emptyData = {};
1899
+ break;
1900
+ }
1901
+ return {
1902
+ data: emptyData,
1903
+ ...result
1904
+ };
1905
+ }
1906
+ let data;
1907
+ switch (parseAs) {
1908
+ case "arrayBuffer":
1909
+ case "blob":
1910
+ case "formData":
1911
+ case "json":
1912
+ case "text":
1913
+ data = await response[parseAs]();
1914
+ break;
1915
+ case "stream":
1916
+ return {
1917
+ data: response.body,
1918
+ ...result
1919
+ };
1920
+ }
1921
+ if (parseAs === "json") {
1922
+ if (opts.responseValidator) {
1923
+ await opts.responseValidator(data);
1924
+ }
1925
+ if (opts.responseTransformer) {
1926
+ data = await opts.responseTransformer(data);
1927
+ }
1928
+ }
1929
+ return {
1930
+ data,
1931
+ ...result
1932
+ };
1933
+ }
1934
+ const textError = await response.text();
1935
+ let jsonError;
1936
+ try {
1937
+ jsonError = JSON.parse(textError);
1938
+ } catch {
1939
+ }
1940
+ const error = jsonError ?? textError;
1941
+ let finalError = error;
1942
+ for (const fn of interceptors.error.fns) {
1943
+ if (fn) {
1944
+ finalError = await fn(error, response, opts);
1945
+ }
1946
+ }
1947
+ finalError = finalError || {};
1948
+ if (opts.throwOnError) {
1949
+ throw finalError;
1950
+ }
1951
+ return {
1952
+ error: finalError,
1953
+ ...result
1954
+ };
1955
+ };
1956
+ const makeMethodFn = (method) => (options) => request({ ...options, method });
1957
+ const makeSseFn = (method) => async (options) => {
1958
+ const { opts, url } = await beforeRequest(options);
1959
+ return createSseClient({
1960
+ ...opts,
1961
+ body: opts.body,
1962
+ headers: opts.headers,
1963
+ method,
1964
+ onRequest: async (url2, init) => {
1965
+ let request2 = new Request(url2, init);
1966
+ const requestInit = {
1967
+ ...init,
1968
+ method: init.method,
1969
+ url: url2
1970
+ };
1971
+ for (const fn of interceptors.request.fns) {
1972
+ if (fn) {
1973
+ await fn(requestInit);
1974
+ request2 = new Request(requestInit.url, requestInit);
1975
+ }
1976
+ }
1977
+ return request2;
1978
+ },
1979
+ url
1980
+ });
1981
+ };
1982
+ return {
1983
+ buildUrl,
1984
+ connect: makeMethodFn("CONNECT"),
1985
+ delete: makeMethodFn("DELETE"),
1986
+ get: makeMethodFn("GET"),
1987
+ getConfig,
1988
+ head: makeMethodFn("HEAD"),
1989
+ interceptors,
1990
+ options: makeMethodFn("OPTIONS"),
1991
+ patch: makeMethodFn("PATCH"),
1992
+ post: makeMethodFn("POST"),
1993
+ put: makeMethodFn("PUT"),
1994
+ request,
1995
+ setConfig,
1996
+ sse: {
1997
+ connect: makeSseFn("CONNECT"),
1998
+ delete: makeSseFn("DELETE"),
1999
+ get: makeSseFn("GET"),
2000
+ head: makeSseFn("HEAD"),
2001
+ options: makeSseFn("OPTIONS"),
2002
+ patch: makeSseFn("PATCH"),
2003
+ post: makeSseFn("POST"),
2004
+ put: makeSseFn("PUT"),
2005
+ trace: makeSseFn("TRACE")
2006
+ },
2007
+ trace: makeMethodFn("TRACE")
2008
+ };
2009
+ };
2010
+
2011
+ // src/client/client.gen.ts
2012
+ var client = createClient(createClientConfig(createConfig()));
2013
+
2014
+ // src/client/sdk.gen.ts
2015
+ var postApiV1ImagesGenerations = (options) => {
2016
+ return (options.client ?? client).post({
2017
+ url: "/api/v1/images/generations",
2018
+ ...options,
2019
+ headers: {
2020
+ "Content-Type": "application/json",
2021
+ ...options.headers
2022
+ }
2023
+ });
2024
+ };
2025
+ var getApiV1Models = (options) => {
2026
+ return (options?.client ?? client).get({
2027
+ url: "/api/v1/models",
2028
+ ...options
2029
+ });
2030
+ };
2031
+
2032
+ // src/react/useImageGeneration.ts
2033
+ function useImageGeneration(options = {}) {
2034
+ const { getToken, baseUrl = BASE_URL, onFinish, onError } = options;
2035
+ const [isLoading, setIsLoading] = (0, import_react3.useState)(false);
2036
+ const abortControllerRef = (0, import_react3.useRef)(null);
2037
+ (0, import_react3.useEffect)(() => {
2038
+ return () => {
2039
+ if (abortControllerRef.current) {
2040
+ abortControllerRef.current.abort();
2041
+ abortControllerRef.current = null;
2042
+ }
2043
+ };
2044
+ }, []);
2045
+ const stop = (0, import_react3.useCallback)(() => {
2046
+ if (abortControllerRef.current) {
2047
+ abortControllerRef.current.abort();
2048
+ abortControllerRef.current = null;
2049
+ }
2050
+ }, []);
2051
+ const generateImage = (0, import_react3.useCallback)(
2052
+ async (args) => {
2053
+ if (abortControllerRef.current) {
2054
+ abortControllerRef.current.abort();
2055
+ }
2056
+ const abortController = new AbortController();
2057
+ abortControllerRef.current = abortController;
2058
+ setIsLoading(true);
2059
+ try {
2060
+ if (!getToken) {
2061
+ throw new Error("Token getter function is required.");
2062
+ }
2063
+ const token = await getToken();
2064
+ if (!token) {
2065
+ throw new Error("No access token available.");
2066
+ }
2067
+ const response = await postApiV1ImagesGenerations({
2068
+ baseUrl,
2069
+ body: args,
2070
+ headers: {
2071
+ Authorization: `Bearer ${token}`
2072
+ },
2073
+ signal: abortController.signal
2074
+ });
2075
+ if (response.error) {
2076
+ const errorMsg = response.error.error || "Failed to generate image";
2077
+ throw new Error(errorMsg);
2078
+ }
2079
+ if (!response.data) {
2080
+ throw new Error("No data received from image generation API");
2081
+ }
2082
+ const result = response.data;
2083
+ if (onFinish) {
2084
+ onFinish(result);
2085
+ }
2086
+ return { data: result, error: null };
2087
+ } catch (err) {
2088
+ if (err instanceof Error && err.name === "AbortError") {
2089
+ return { data: null, error: "Request aborted" };
2090
+ }
2091
+ const errorMsg = err instanceof Error ? err.message : "Failed to generate image.";
2092
+ const errorObj = err instanceof Error ? err : new Error(errorMsg);
2093
+ if (onError) {
2094
+ onError(errorObj);
2095
+ }
2096
+ return { data: null, error: errorMsg };
2097
+ } finally {
2098
+ if (abortControllerRef.current === abortController) {
2099
+ setIsLoading(false);
2100
+ abortControllerRef.current = null;
2101
+ }
2102
+ }
2103
+ },
2104
+ [getToken, baseUrl, onFinish, onError]
2105
+ );
2106
+ return {
2107
+ isLoading,
2108
+ generateImage,
2109
+ stop
2110
+ };
2111
+ }
2112
+
2113
+ // src/react/useModels.ts
2114
+ var import_react4 = require("react");
2115
+ function useModels(options = {}) {
2116
+ const { getToken, baseUrl = BASE_URL, provider, autoFetch = true } = options;
2117
+ const [models, setModels] = (0, import_react4.useState)([]);
2118
+ const [isLoading, setIsLoading] = (0, import_react4.useState)(false);
2119
+ const [error, setError] = (0, import_react4.useState)(null);
2120
+ const getTokenRef = (0, import_react4.useRef)(getToken);
2121
+ const baseUrlRef = (0, import_react4.useRef)(baseUrl);
2122
+ const providerRef = (0, import_react4.useRef)(provider);
2123
+ const abortControllerRef = (0, import_react4.useRef)(null);
2124
+ (0, import_react4.useEffect)(() => {
2125
+ getTokenRef.current = getToken;
2126
+ baseUrlRef.current = baseUrl;
2127
+ providerRef.current = provider;
2128
+ });
2129
+ (0, import_react4.useEffect)(() => {
2130
+ return () => {
2131
+ if (abortControllerRef.current) {
2132
+ abortControllerRef.current.abort();
2133
+ abortControllerRef.current = null;
2134
+ }
2135
+ };
2136
+ }, []);
2137
+ const fetchModels = (0, import_react4.useCallback)(async () => {
2138
+ if (abortControllerRef.current) {
2139
+ abortControllerRef.current.abort();
2140
+ }
2141
+ const abortController = new AbortController();
2142
+ abortControllerRef.current = abortController;
2143
+ const signal = abortController.signal;
2144
+ setIsLoading(true);
2145
+ setError(null);
2146
+ try {
2147
+ let token;
2148
+ if (getTokenRef.current) {
2149
+ token = await getTokenRef.current() ?? void 0;
2150
+ }
2151
+ if (signal.aborted) return;
2152
+ const headers = {};
2153
+ if (token) {
2154
+ headers["Authorization"] = `Bearer ${token}`;
2155
+ }
2156
+ let allModels = [];
2157
+ let nextPageToken;
2158
+ do {
2159
+ if (signal.aborted) return;
2160
+ const response = await getApiV1Models({
2161
+ baseUrl: baseUrlRef.current,
2162
+ headers,
2163
+ query: {
2164
+ provider: providerRef.current,
2165
+ page_token: nextPageToken
2166
+ },
2167
+ signal
2168
+ });
2169
+ if (response.error) {
2170
+ const errorMsg = response.error.error ?? "Failed to fetch models";
2171
+ throw new Error(errorMsg);
2172
+ }
2173
+ if (response.data) {
2174
+ const newModels = response.data.data || [];
2175
+ allModels = [...allModels, ...newModels];
2176
+ nextPageToken = response.data.next_page_token;
2177
+ }
2178
+ } while (nextPageToken);
2179
+ if (signal.aborted) return;
2180
+ setModels(allModels);
2181
+ } catch (err) {
2182
+ if (err instanceof Error && err.name === "AbortError") {
2183
+ return;
2184
+ }
2185
+ setError(err instanceof Error ? err : new Error(String(err)));
2186
+ } finally {
2187
+ if (!signal.aborted) {
2188
+ setIsLoading(false);
2189
+ }
2190
+ if (abortControllerRef.current === abortController) {
2191
+ abortControllerRef.current = null;
2192
+ }
2193
+ }
2194
+ }, []);
2195
+ const refetch = (0, import_react4.useCallback)(async () => {
2196
+ setModels([]);
2197
+ await fetchModels();
2198
+ }, [fetchModels]);
2199
+ const hasFetchedRef = (0, import_react4.useRef)(false);
2200
+ (0, import_react4.useEffect)(() => {
2201
+ if (autoFetch && !hasFetchedRef.current) {
2202
+ hasFetchedRef.current = true;
2203
+ fetchModels();
2204
+ }
2205
+ if (!autoFetch) {
2206
+ hasFetchedRef.current = false;
2207
+ }
2208
+ }, [autoFetch, fetchModels]);
2209
+ return {
2210
+ models,
2211
+ isLoading,
2212
+ error,
2213
+ refetch
2214
+ };
2215
+ }
2216
+
2217
+ // src/expo/useMemoryStorage.ts
2218
+ var import_react5 = require("react");
2219
+ var import_client4 = require("@reverbia/sdk");
2220
+
2221
+ // src/lib/db/memory/schema.ts
2222
+ var import_watermelondb4 = require("@nozbe/watermelondb");
2223
+ var memoryStorageSchema = (0, import_watermelondb4.appSchema)({
2224
+ version: 1,
2225
+ tables: [
2226
+ (0, import_watermelondb4.tableSchema)({
2227
+ name: "memories",
2228
+ columns: [
2229
+ { name: "type", type: "string", isIndexed: true },
2230
+ { name: "namespace", type: "string", isIndexed: true },
2231
+ { name: "key", type: "string", isIndexed: true },
2232
+ { name: "value", type: "string" },
2233
+ { name: "raw_evidence", type: "string" },
2234
+ { name: "confidence", type: "number" },
2235
+ { name: "pii", type: "boolean", isIndexed: true },
2236
+ { name: "composite_key", type: "string", isIndexed: true },
2237
+ { name: "unique_key", type: "string", isIndexed: true },
2238
+ { name: "created_at", type: "number", isIndexed: true },
2239
+ { name: "updated_at", type: "number" },
2240
+ { name: "embedding", type: "string", isOptional: true },
2241
+ { name: "embedding_model", type: "string", isOptional: true },
2242
+ { name: "is_deleted", type: "boolean", isIndexed: true }
2243
+ ]
2244
+ })
2245
+ ]
2246
+ });
2247
+
2248
+ // src/lib/db/memory/models.ts
2249
+ var import_watermelondb5 = require("@nozbe/watermelondb");
2250
+ var import_decorators2 = require("@nozbe/watermelondb/decorators");
2251
+ var Memory = class extends import_watermelondb5.Model {
2252
+ };
2253
+ Memory.table = "memories";
2254
+ __decorateClass([
2255
+ (0, import_decorators2.text)("type")
2256
+ ], Memory.prototype, "type", 2);
2257
+ __decorateClass([
2258
+ (0, import_decorators2.text)("namespace")
2259
+ ], Memory.prototype, "namespace", 2);
2260
+ __decorateClass([
2261
+ (0, import_decorators2.text)("key")
2262
+ ], Memory.prototype, "key", 2);
2263
+ __decorateClass([
2264
+ (0, import_decorators2.text)("value")
2265
+ ], Memory.prototype, "value", 2);
2266
+ __decorateClass([
2267
+ (0, import_decorators2.text)("raw_evidence")
2268
+ ], Memory.prototype, "rawEvidence", 2);
2269
+ __decorateClass([
2270
+ (0, import_decorators2.field)("confidence")
2271
+ ], Memory.prototype, "confidence", 2);
2272
+ __decorateClass([
2273
+ (0, import_decorators2.field)("pii")
2274
+ ], Memory.prototype, "pii", 2);
2275
+ __decorateClass([
2276
+ (0, import_decorators2.text)("composite_key")
2277
+ ], Memory.prototype, "compositeKey", 2);
2278
+ __decorateClass([
2279
+ (0, import_decorators2.text)("unique_key")
2280
+ ], Memory.prototype, "uniqueKey", 2);
2281
+ __decorateClass([
2282
+ (0, import_decorators2.date)("created_at")
2283
+ ], Memory.prototype, "createdAt", 2);
2284
+ __decorateClass([
2285
+ (0, import_decorators2.date)("updated_at")
2286
+ ], Memory.prototype, "updatedAt", 2);
2287
+ __decorateClass([
2288
+ (0, import_decorators2.json)("embedding", (json3) => json3)
2289
+ ], Memory.prototype, "embedding", 2);
2290
+ __decorateClass([
2291
+ (0, import_decorators2.text)("embedding_model")
2292
+ ], Memory.prototype, "embeddingModel", 2);
2293
+ __decorateClass([
2294
+ (0, import_decorators2.field)("is_deleted")
2295
+ ], Memory.prototype, "isDeleted", 2);
2296
+
2297
+ // src/lib/db/memory/types.ts
2298
+ function generateCompositeKey(namespace, key) {
2299
+ return `${namespace}:${key}`;
2300
+ }
2301
+ function generateUniqueKey(namespace, key, value) {
2302
+ return `${namespace}:${key}:${value}`;
2303
+ }
2304
+ function cosineSimilarity(a, b) {
2305
+ if (a.length !== b.length) {
2306
+ throw new Error("Vectors must have the same length");
2307
+ }
2308
+ let dotProduct = 0;
2309
+ let normA = 0;
2310
+ let normB = 0;
2311
+ for (let i = 0; i < a.length; i++) {
2312
+ dotProduct += a[i] * b[i];
2313
+ normA += a[i] * a[i];
2314
+ normB += b[i] * b[i];
2315
+ }
2316
+ const denominator = Math.sqrt(normA) * Math.sqrt(normB);
2317
+ if (denominator === 0) {
2318
+ return 0;
2319
+ }
2320
+ return dotProduct / denominator;
2321
+ }
2322
+
2323
+ // src/lib/db/memory/operations.ts
2324
+ var import_watermelondb6 = require("@nozbe/watermelondb");
2325
+ function memoryToStored(memory) {
2326
+ return {
2327
+ uniqueId: memory.id,
2328
+ type: memory.type,
2329
+ namespace: memory.namespace,
2330
+ key: memory.key,
2331
+ value: memory.value,
2332
+ rawEvidence: memory.rawEvidence,
2333
+ confidence: memory.confidence,
2334
+ pii: memory.pii,
2335
+ compositeKey: memory.compositeKey,
2336
+ uniqueKey: memory.uniqueKey,
2337
+ createdAt: memory.createdAt,
2338
+ updatedAt: memory.updatedAt,
2339
+ embedding: memory.embedding,
2340
+ embeddingModel: memory.embeddingModel,
2341
+ isDeleted: memory.isDeleted
2342
+ };
2343
+ }
2344
+ async function getAllMemoriesOp(ctx) {
2345
+ const results = await ctx.memoriesCollection.query(import_watermelondb6.Q.where("is_deleted", false), import_watermelondb6.Q.sortBy("created_at", import_watermelondb6.Q.desc)).fetch();
2346
+ return results.map(memoryToStored);
2347
+ }
2348
+ async function getMemoryByIdOp(ctx, id) {
2349
+ try {
2350
+ const memory = await ctx.memoriesCollection.find(id);
2351
+ if (memory.isDeleted) return null;
2352
+ return memoryToStored(memory);
2353
+ } catch {
2354
+ return null;
2355
+ }
2356
+ }
2357
+ async function getMemoriesByNamespaceOp(ctx, namespace) {
2358
+ const results = await ctx.memoriesCollection.query(
2359
+ import_watermelondb6.Q.where("namespace", namespace),
2360
+ import_watermelondb6.Q.where("is_deleted", false),
2361
+ import_watermelondb6.Q.sortBy("created_at", import_watermelondb6.Q.desc)
2362
+ ).fetch();
2363
+ return results.map(memoryToStored);
2364
+ }
2365
+ async function getMemoriesByKeyOp(ctx, namespace, key) {
2366
+ const compositeKey = generateCompositeKey(namespace, key);
2367
+ const results = await ctx.memoriesCollection.query(
2368
+ import_watermelondb6.Q.where("composite_key", compositeKey),
2369
+ import_watermelondb6.Q.where("is_deleted", false),
2370
+ import_watermelondb6.Q.sortBy("created_at", import_watermelondb6.Q.desc)
2371
+ ).fetch();
2372
+ return results.map(memoryToStored);
2373
+ }
2374
+ async function saveMemoryOp(ctx, opts) {
2375
+ if (!opts.namespace || typeof opts.namespace !== "string") {
2376
+ throw new Error("Namespace is required and must be a string");
2377
+ }
2378
+ if (!opts.key || typeof opts.key !== "string") {
2379
+ throw new Error("Key is required and must be a string");
2380
+ }
2381
+ if (!opts.value || typeof opts.value !== "string") {
2382
+ throw new Error("Value is required and must be a string");
2383
+ }
2384
+ if (!opts.type || typeof opts.type !== "string") {
2385
+ throw new Error("Type is required and must be a string");
2386
+ }
2387
+ if (typeof opts.confidence !== "number" || opts.confidence < 0 || opts.confidence > 1) {
2388
+ throw new Error("Confidence must be a number between 0 and 1");
2389
+ }
2390
+ if (typeof opts.pii !== "boolean") {
2391
+ throw new Error("PII must be a boolean");
2392
+ }
2393
+ const compositeKey = generateCompositeKey(opts.namespace, opts.key);
2394
+ const uniqueKey = generateUniqueKey(opts.namespace, opts.key, opts.value);
2395
+ const result = await ctx.database.write(async () => {
2396
+ const existing = await ctx.memoriesCollection.query(import_watermelondb6.Q.where("unique_key", uniqueKey)).fetch();
2397
+ if (existing.length > 0) {
2398
+ const existingMemory = existing[0];
2399
+ const shouldPreserveEmbedding = existingMemory.value === opts.value && existingMemory.rawEvidence === opts.rawEvidence && existingMemory.type === opts.type && existingMemory.namespace === opts.namespace && existingMemory.key === opts.key && existingMemory.embedding !== void 0 && existingMemory.embedding.length > 0 && !opts.embedding;
2400
+ await existingMemory.update((mem) => {
2401
+ mem._setRaw("type", opts.type);
2402
+ mem._setRaw("namespace", opts.namespace);
2403
+ mem._setRaw("key", opts.key);
2404
+ mem._setRaw("value", opts.value);
2405
+ mem._setRaw("raw_evidence", opts.rawEvidence);
2406
+ mem._setRaw("confidence", opts.confidence);
2407
+ mem._setRaw("pii", opts.pii);
2408
+ mem._setRaw("composite_key", compositeKey);
2409
+ mem._setRaw("unique_key", uniqueKey);
2410
+ mem._setRaw("is_deleted", false);
2411
+ if (shouldPreserveEmbedding) {
2412
+ } else if (opts.embedding) {
2413
+ mem._setRaw("embedding", JSON.stringify(opts.embedding));
2414
+ if (opts.embeddingModel) {
2415
+ mem._setRaw("embedding_model", opts.embeddingModel);
2416
+ }
2417
+ } else {
2418
+ mem._setRaw("embedding", null);
2419
+ mem._setRaw("embedding_model", null);
2420
+ }
2421
+ });
2422
+ return existingMemory;
2423
+ }
2424
+ return await ctx.memoriesCollection.create((mem) => {
2425
+ mem._setRaw("type", opts.type);
2426
+ mem._setRaw("namespace", opts.namespace);
2427
+ mem._setRaw("key", opts.key);
2428
+ mem._setRaw("value", opts.value);
2429
+ mem._setRaw("raw_evidence", opts.rawEvidence);
2430
+ mem._setRaw("confidence", opts.confidence);
2431
+ mem._setRaw("pii", opts.pii);
2432
+ mem._setRaw("composite_key", compositeKey);
2433
+ mem._setRaw("unique_key", uniqueKey);
2434
+ mem._setRaw("is_deleted", false);
2435
+ if (opts.embedding) {
2436
+ mem._setRaw("embedding", JSON.stringify(opts.embedding));
2437
+ if (opts.embeddingModel) {
2438
+ mem._setRaw("embedding_model", opts.embeddingModel);
2439
+ }
2440
+ }
2441
+ });
2442
+ });
2443
+ return memoryToStored(result);
2444
+ }
2445
+ async function saveMemoriesOp(ctx, memories) {
2446
+ const results = [];
2447
+ for (const memory of memories) {
2448
+ const saved = await saveMemoryOp(ctx, memory);
2449
+ results.push(saved);
2450
+ }
2451
+ return results;
2452
+ }
2453
+ async function updateMemoryOp(ctx, id, updates) {
2454
+ let memory;
2455
+ try {
2456
+ memory = await ctx.memoriesCollection.find(id);
2457
+ } catch {
2458
+ return { ok: false, reason: "not_found" };
2459
+ }
2460
+ if (memory.isDeleted) {
2461
+ return { ok: false, reason: "not_found" };
2462
+ }
2463
+ const newNamespace = updates.namespace ?? memory.namespace;
2464
+ const newKey = updates.key ?? memory.key;
2465
+ const newValue = updates.value ?? memory.value;
2466
+ const newCompositeKey = generateCompositeKey(newNamespace, newKey);
2467
+ const newUniqueKey = generateUniqueKey(newNamespace, newKey, newValue);
2468
+ if (newUniqueKey !== memory.uniqueKey) {
2469
+ const existing = await ctx.memoriesCollection.query(import_watermelondb6.Q.where("unique_key", newUniqueKey), import_watermelondb6.Q.where("is_deleted", false)).fetch();
2470
+ if (existing.length > 0) {
2471
+ return { ok: false, reason: "conflict", conflictingKey: newUniqueKey };
2472
+ }
2473
+ }
2474
+ try {
2475
+ const updated = await ctx.database.write(async () => {
2476
+ await memory.update((mem) => {
2477
+ if (updates.type !== void 0) mem._setRaw("type", updates.type);
2478
+ if (updates.namespace !== void 0)
2479
+ mem._setRaw("namespace", updates.namespace);
2480
+ if (updates.key !== void 0) mem._setRaw("key", updates.key);
2481
+ if (updates.value !== void 0) mem._setRaw("value", updates.value);
2482
+ if (updates.rawEvidence !== void 0)
2483
+ mem._setRaw("raw_evidence", updates.rawEvidence);
2484
+ if (updates.confidence !== void 0)
2485
+ mem._setRaw("confidence", updates.confidence);
2486
+ if (updates.pii !== void 0) mem._setRaw("pii", updates.pii);
2487
+ if (updates.namespace !== void 0 || updates.key !== void 0 || updates.value !== void 0) {
2488
+ mem._setRaw("composite_key", newCompositeKey);
2489
+ mem._setRaw("unique_key", newUniqueKey);
2490
+ }
2491
+ if (updates.embedding !== void 0) {
2492
+ mem._setRaw(
2493
+ "embedding",
2494
+ updates.embedding ? JSON.stringify(updates.embedding) : null
2495
+ );
2496
+ }
2497
+ if (updates.embeddingModel !== void 0) {
2498
+ mem._setRaw("embedding_model", updates.embeddingModel || null);
2499
+ }
2500
+ });
2501
+ return memory;
2502
+ });
2503
+ return { ok: true, memory: memoryToStored(updated) };
2504
+ } catch (err) {
2505
+ return {
2506
+ ok: false,
2507
+ reason: "error",
2508
+ error: err instanceof Error ? err : new Error(String(err))
2509
+ };
2510
+ }
2511
+ }
2512
+ async function deleteMemoryByIdOp(ctx, id) {
2513
+ try {
2514
+ const memory = await ctx.memoriesCollection.find(id);
2515
+ await ctx.database.write(async () => {
2516
+ await memory.update((mem) => {
2517
+ mem._setRaw("is_deleted", true);
2518
+ });
2519
+ });
2520
+ } catch {
2521
+ }
2522
+ }
2523
+ async function deleteMemoryOp(ctx, namespace, key, value) {
2524
+ const uniqueKey = generateUniqueKey(namespace, key, value);
2525
+ const results = await ctx.memoriesCollection.query(import_watermelondb6.Q.where("unique_key", uniqueKey)).fetch();
2526
+ if (results.length > 0) {
2527
+ await ctx.database.write(async () => {
2528
+ await results[0].update((mem) => {
2529
+ mem._setRaw("is_deleted", true);
2530
+ });
2531
+ });
2532
+ }
2533
+ }
2534
+ async function deleteMemoriesByKeyOp(ctx, namespace, key) {
2535
+ const compositeKey = generateCompositeKey(namespace, key);
2536
+ const results = await ctx.memoriesCollection.query(import_watermelondb6.Q.where("composite_key", compositeKey), import_watermelondb6.Q.where("is_deleted", false)).fetch();
2537
+ await ctx.database.write(async () => {
2538
+ for (const memory of results) {
2539
+ await memory.update((mem) => {
2540
+ mem._setRaw("is_deleted", true);
2541
+ });
2542
+ }
2543
+ });
2544
+ }
2545
+ async function clearAllMemoriesOp(ctx) {
2546
+ const results = await ctx.memoriesCollection.query(import_watermelondb6.Q.where("is_deleted", false)).fetch();
2547
+ await ctx.database.write(async () => {
2548
+ for (const memory of results) {
2549
+ await memory.update((mem) => {
2550
+ mem._setRaw("is_deleted", true);
2551
+ });
2552
+ }
2553
+ });
2554
+ }
2555
+ async function searchSimilarMemoriesOp(ctx, queryEmbedding, limit = 10, minSimilarity = 0.6) {
2556
+ const allMemories = await ctx.memoriesCollection.query(import_watermelondb6.Q.where("is_deleted", false)).fetch();
2557
+ const memoriesWithEmbeddings = allMemories.filter(
2558
+ (m) => m.embedding && m.embedding.length > 0
2559
+ );
2560
+ if (memoriesWithEmbeddings.length === 0) {
2561
+ return [];
2562
+ }
2563
+ const results = memoriesWithEmbeddings.map((memory) => {
2564
+ const similarity = cosineSimilarity(queryEmbedding, memory.embedding);
2565
+ return {
2566
+ ...memoryToStored(memory),
2567
+ similarity
2568
+ };
2569
+ }).filter((result) => result.similarity >= minSimilarity).sort((a, b) => b.similarity - a.similarity).slice(0, limit);
2570
+ return results;
2571
+ }
2572
+ async function updateMemoryEmbeddingOp(ctx, id, embedding, embeddingModel) {
2573
+ try {
2574
+ const memory = await ctx.memoriesCollection.find(id);
2575
+ await ctx.database.write(async () => {
2576
+ await memory.update((mem) => {
2577
+ mem._setRaw("embedding", JSON.stringify(embedding));
2578
+ mem._setRaw("embedding_model", embeddingModel);
2579
+ });
2580
+ });
2581
+ } catch {
2582
+ }
2583
+ }
2584
+
2585
+ // src/lib/memory/service.ts
2586
+ var FACT_EXTRACTION_PROMPT = `You are a memory extraction system. Extract durable user memories from chat messages.
2587
+
2588
+ CRITICAL: You MUST respond with ONLY valid JSON. No explanations, no markdown, no code blocks, just pure JSON.
2589
+
2590
+ Only store clear, factual statements that might be relevant for future context or reference. Extract facts that will be useful in future conversations, such as identity, stable preferences, ongoing projects, skills, locations, favorites, and constraints.
2591
+
2592
+ Do not extract sensitive attributes, temporary things, or single-use instructions.
2593
+
2594
+ You must also extract stable personal preferences, including food likes/dislikes, hobbies, favorite items, favorite genres, or other enduring tastes.
2595
+
2596
+ If there are no memories to extract, return: {"items": []}
2597
+
2598
+ Response format (JSON only, no other text):
2599
+
2600
+ {
2601
+ "items": [
2602
+ {
2603
+ "type": "identity",
2604
+ "namespace": "identity",
2605
+ "key": "name",
2606
+ "value": "Charlie",
2607
+ "rawEvidence": "I'm Charlie",
2608
+ "confidence": 0.98,
2609
+ "pii": true
2610
+ },
2611
+ {
2612
+ "type": "identity",
2613
+ "namespace": "work",
2614
+ "key": "company",
2615
+ "value": "ZetaChain",
2616
+ "rawEvidence": "called ZetaChain",
2617
+ "confidence": 0.99,
2618
+ "pii": false
2619
+ },
2620
+ {
2621
+ "type": "identity",
2622
+ "namespace": "location",
2623
+ "key": "city",
2624
+ "value": "San Francisco",
2625
+ "rawEvidence": "I live in San Francisco",
2626
+ "confidence": 0.99,
2627
+ "pii": false
2628
+ },
2629
+ {
2630
+ "type": "preference",
2631
+ "namespace": "location",
2632
+ "key": "country",
2633
+ "value": "Japan",
2634
+ "rawEvidence": "I like to travel to the Japan",
2635
+ "confidence": 0.94,
2636
+ "pii": false
2637
+ },
2638
+ {
2639
+ "type": "preference",
2640
+ "namespace": "answer_style",
2641
+ "key": "verbosity",
2642
+ "value": "concise_direct",
2643
+ "rawEvidence": "I prefer concise, direct answers",
2644
+ "confidence": 0.96,
2645
+ "pii": false
2646
+ },
2647
+ {
2648
+ "type": "identity",
2649
+ "namespace": "timezone",
2650
+ "key": "tz",
2651
+ "value": "America/Los_Angeles",
2652
+ "rawEvidence": "I'm in PST",
2653
+ "confidence": 0.9,
2654
+ "pii": false
2655
+ },
2656
+ {
2657
+ "type": "preference",
2658
+ "namespace": "food",
2659
+ "key": "likes_ice_cream",
2660
+ "value": "ice cream",
2661
+ "rawEvidence": "I like ice cream",
2662
+ "confidence": 0.95,
2663
+ "pii": false
2664
+ }
2665
+ ]
2666
+ }`;
2667
+ var preprocessMemories = (items, minConfidence = 0.6) => {
2668
+ if (!items || !Array.isArray(items)) {
2669
+ return [];
2670
+ }
2671
+ const validItems = items.filter((item) => {
2672
+ if (item.namespace == null || item.key == null || item.value == null) {
2673
+ console.warn(
2674
+ "Dropping memory item with null/undefined namespace, key, or value:",
2675
+ item
2676
+ );
2677
+ return false;
2678
+ }
2679
+ const namespace = String(item.namespace).trim();
2680
+ const key = String(item.key).trim();
2681
+ const value = String(item.value).trim();
2682
+ if (namespace === "" || key === "" || value === "") {
2683
+ console.warn(
2684
+ "Dropping memory item with empty namespace, key, or value after trimming:",
2685
+ item
2686
+ );
2687
+ return false;
2688
+ }
2689
+ if (typeof item.confidence !== "number" || item.confidence < minConfidence) {
2690
+ console.warn(
2691
+ `Dropping memory item with confidence ${item.confidence} below threshold ${minConfidence}:`,
2692
+ item
2693
+ );
2694
+ return false;
2695
+ }
2696
+ return true;
2697
+ });
2698
+ const deduplicatedMap = /* @__PURE__ */ new Map();
2699
+ for (const item of validItems) {
2700
+ const uniqueKey = `${item.namespace}:${item.key}:${item.value}`;
2701
+ const existing = deduplicatedMap.get(uniqueKey);
2702
+ if (!existing || item.confidence > existing.confidence) {
2703
+ deduplicatedMap.set(uniqueKey, item);
2704
+ } else {
2705
+ console.debug(
2706
+ `Deduplicating memory item: keeping entry with higher confidence (${existing.confidence} > ${item.confidence})`,
2707
+ { namespace: item.namespace, key: item.key, value: item.value }
2708
+ );
2709
+ }
2710
+ }
2711
+ return Array.from(deduplicatedMap.values());
2712
+ };
2713
+
2714
+ // src/lib/memory/constants.ts
2715
+ var DEFAULT_API_EMBEDDING_MODEL = "openai/text-embedding-3-small";
2716
+ var DEFAULT_COMPLETION_MODEL = "openai/gpt-4o";
2717
+
2718
+ // src/expo/useMemoryStorage.ts
2719
+ var import_client5 = require("@reverbia/sdk");
2720
+ async function generateEmbeddingForTextApi(text4, options) {
2721
+ const token = options.getToken ? await options.getToken() : null;
2722
+ if (!token) {
2723
+ throw new Error("No auth token available for embedding generation");
2724
+ }
2725
+ const response = await (0, import_client5.postApiV1Embeddings)({
2726
+ baseUrl: options.baseUrl,
2727
+ body: {
2728
+ input: text4,
2729
+ model: options.model
2730
+ },
2731
+ headers: {
2732
+ Authorization: `Bearer ${token}`
2733
+ }
2734
+ });
2735
+ if (!response.data || typeof response.data === "string") {
2736
+ throw new Error("Failed to generate embedding");
2737
+ }
2738
+ const embedding = response.data.data?.[0]?.embedding;
2739
+ if (!embedding) {
2740
+ throw new Error("No embedding in response");
2741
+ }
2742
+ return embedding;
2743
+ }
2744
+ async function generateEmbeddingForMemoryApi(memory, options) {
2745
+ const text4 = `${memory.type}: ${memory.namespace}/${memory.key} = ${memory.value}. Evidence: ${memory.rawEvidence}`;
2746
+ return generateEmbeddingForTextApi(text4, options);
2747
+ }
2748
+ function useMemoryStorage(options) {
2749
+ const {
2750
+ database,
2751
+ completionsModel = DEFAULT_COMPLETION_MODEL,
2752
+ embeddingModel: userEmbeddingModel,
2753
+ generateEmbeddings = true,
2754
+ onFactsExtracted,
2755
+ getToken,
2756
+ baseUrl = BASE_URL
2757
+ } = options;
2758
+ const embeddingModel = userEmbeddingModel === void 0 ? DEFAULT_API_EMBEDDING_MODEL : userEmbeddingModel;
2759
+ const [memories, setMemories] = (0, import_react5.useState)([]);
2760
+ const extractionInProgressRef = (0, import_react5.useRef)(false);
2761
+ const memoriesCollection = (0, import_react5.useMemo)(
2762
+ () => database.get("memories"),
2763
+ [database]
2764
+ );
2765
+ const storageCtx = (0, import_react5.useMemo)(
2766
+ () => ({
2767
+ database,
2768
+ memoriesCollection
2769
+ }),
2770
+ [database, memoriesCollection]
2771
+ );
2772
+ const embeddingOptions = (0, import_react5.useMemo)(
2773
+ () => ({
2774
+ model: embeddingModel ?? DEFAULT_API_EMBEDDING_MODEL,
2775
+ getToken: getToken || void 0,
2776
+ baseUrl
2777
+ }),
2778
+ [embeddingModel, getToken, baseUrl]
2779
+ );
2780
+ const refreshMemories = (0, import_react5.useCallback)(async () => {
2781
+ const storedMemories = await getAllMemoriesOp(storageCtx);
2782
+ setMemories(storedMemories);
2783
+ }, [storageCtx]);
2784
+ const extractMemoriesFromMessage = (0, import_react5.useCallback)(
2785
+ async (opts) => {
2786
+ const { messages, model } = opts;
2787
+ if (!getToken || extractionInProgressRef.current) {
2788
+ return null;
2789
+ }
2790
+ extractionInProgressRef.current = true;
2791
+ try {
2792
+ const token = await getToken();
2793
+ if (!token) {
2794
+ console.error("No access token available for memory extraction");
2795
+ return null;
2796
+ }
2797
+ const completion = await (0, import_client4.postApiV1ChatCompletions)({
2798
+ baseUrl,
2799
+ body: {
2800
+ messages: [
2801
+ {
2802
+ role: "system",
2803
+ content: [{ type: "text", text: FACT_EXTRACTION_PROMPT }]
2804
+ },
2805
+ ...messages.map((m) => ({
2806
+ role: m.role,
2807
+ content: [{ type: "text", text: m.content }]
2808
+ }))
2809
+ ],
2810
+ model: model || completionsModel
2811
+ },
2812
+ headers: {
2813
+ Authorization: `Bearer ${token}`
2814
+ }
2815
+ });
2816
+ if (!completion.data) {
2817
+ console.error(
2818
+ "Memory extraction failed:",
2819
+ completion.error?.error ?? "API did not return a response"
2820
+ );
2821
+ return null;
2822
+ }
2823
+ if (typeof completion.data === "string") {
2824
+ console.error(
2825
+ "Memory extraction failed: API returned a string response"
2826
+ );
2827
+ return null;
2828
+ }
2829
+ const messageContent = completion.data.choices?.[0]?.message?.content;
2830
+ let content = "";
2831
+ if (Array.isArray(messageContent)) {
2832
+ content = messageContent.map((p) => p.text || "").join("").trim();
2833
+ } else if (typeof messageContent === "string") {
2834
+ content = messageContent.trim();
2835
+ }
2836
+ if (!content) {
2837
+ console.error("No content in memory extraction response");
2838
+ return null;
2839
+ }
2840
+ let jsonContent = content;
2841
+ jsonContent = jsonContent.replace(/^data:\s*/gm, "").trim();
2842
+ if (jsonContent.startsWith("{")) {
2843
+ let braceCount = 0;
2844
+ let jsonStart = -1;
2845
+ let jsonEnd = -1;
2846
+ for (let i = 0; i < jsonContent.length; i++) {
2847
+ if (jsonContent[i] === "{") {
2848
+ if (jsonStart === -1) jsonStart = i;
2849
+ braceCount++;
2850
+ } else if (jsonContent[i] === "}") {
2851
+ braceCount--;
2852
+ if (braceCount === 0 && jsonStart !== -1) {
2853
+ jsonEnd = i + 1;
2854
+ break;
2855
+ }
2856
+ }
2857
+ }
2858
+ if (jsonStart !== -1 && jsonEnd !== -1) {
2859
+ jsonContent = jsonContent.substring(jsonStart, jsonEnd);
2860
+ }
2861
+ } else {
2862
+ const jsonMatch = jsonContent.match(
2863
+ /```(?:json)?\s*(\{[\s\S]*?\})\s*```/
2864
+ );
2865
+ if (jsonMatch && jsonMatch[1]) {
2866
+ jsonContent = jsonMatch[1].trim();
2867
+ } else {
2868
+ const jsonObjectMatch = jsonContent.match(/\{[\s\S]*\}/);
2869
+ if (jsonObjectMatch && jsonObjectMatch[0]) {
2870
+ jsonContent = jsonObjectMatch[0];
2871
+ } else {
2872
+ console.warn("Memory extraction returned non-JSON response.");
2873
+ return { items: [] };
2874
+ }
2875
+ }
2876
+ }
2877
+ const trimmedJson = jsonContent.trim();
2878
+ if (!trimmedJson.startsWith("{") || !trimmedJson.includes("items")) {
2879
+ console.warn("Memory extraction response doesn't appear to be valid JSON.");
2880
+ return { items: [] };
2881
+ }
2882
+ let result;
2883
+ try {
2884
+ result = JSON.parse(jsonContent);
2885
+ if (!result || typeof result !== "object") {
2886
+ throw new Error("Invalid JSON structure: not an object");
2887
+ }
2888
+ if (!Array.isArray(result.items)) {
2889
+ console.warn("Memory extraction result missing 'items' array.");
2890
+ return { items: [] };
2891
+ }
2892
+ } catch (parseError) {
2893
+ console.error(
2894
+ "Failed to parse memory extraction JSON:",
2895
+ parseError instanceof Error ? parseError.message : "Unknown error"
2896
+ );
2897
+ return { items: [] };
2898
+ }
2899
+ if (result.items && Array.isArray(result.items)) {
2900
+ result.items = preprocessMemories(result.items);
2901
+ }
2902
+ if (result.items && result.items.length > 0) {
2903
+ try {
2904
+ const createOptions = result.items.map(
2905
+ (item) => ({
2906
+ type: item.type,
2907
+ namespace: item.namespace,
2908
+ key: item.key,
2909
+ value: item.value,
2910
+ rawEvidence: item.rawEvidence,
2911
+ confidence: item.confidence,
2912
+ pii: item.pii
2913
+ })
2914
+ );
2915
+ const savedMemories = await saveMemoriesOp(storageCtx, createOptions);
2916
+ console.log(`Saved ${savedMemories.length} memories to WatermelonDB`);
2917
+ if (generateEmbeddings && embeddingModel) {
2918
+ try {
2919
+ for (const saved of savedMemories) {
2920
+ const memoryItem = {
2921
+ type: saved.type,
2922
+ namespace: saved.namespace,
2923
+ key: saved.key,
2924
+ value: saved.value,
2925
+ rawEvidence: saved.rawEvidence,
2926
+ confidence: saved.confidence,
2927
+ pii: saved.pii
2928
+ };
2929
+ const embedding = await generateEmbeddingForMemoryApi(
2930
+ memoryItem,
2931
+ embeddingOptions
2932
+ );
2933
+ await updateMemoryEmbeddingOp(
2934
+ storageCtx,
2935
+ saved.uniqueId,
2936
+ embedding,
2937
+ embeddingOptions.model
2938
+ );
2939
+ }
2940
+ console.log(`Generated embeddings for ${savedMemories.length} memories`);
2941
+ } catch (error) {
2942
+ console.error("Failed to generate embeddings:", error);
2943
+ }
2944
+ }
2945
+ await refreshMemories();
2946
+ } catch (error) {
2947
+ console.error("Failed to save memories to WatermelonDB:", error);
2948
+ }
2949
+ }
2950
+ if (onFactsExtracted) {
2951
+ onFactsExtracted(result);
2952
+ }
2953
+ return result;
2954
+ } catch (error) {
2955
+ console.error("Failed to extract facts:", error);
2956
+ return null;
2957
+ } finally {
2958
+ extractionInProgressRef.current = false;
2959
+ }
2960
+ },
2961
+ [
2962
+ completionsModel,
2963
+ embeddingModel,
2964
+ embeddingOptions,
2965
+ generateEmbeddings,
2966
+ getToken,
2967
+ onFactsExtracted,
2968
+ baseUrl,
2969
+ storageCtx,
2970
+ refreshMemories
2971
+ ]
2972
+ );
2973
+ const searchMemories = (0, import_react5.useCallback)(
2974
+ async (query, limit = 10, minSimilarity = 0.6) => {
2975
+ if (!embeddingModel) {
2976
+ console.warn("Cannot search memories: embeddingModel not provided");
2977
+ return [];
2978
+ }
2979
+ try {
2980
+ const queryEmbedding = await generateEmbeddingForTextApi(
2981
+ query,
2982
+ embeddingOptions
2983
+ );
2984
+ const results = await searchSimilarMemoriesOp(
2985
+ storageCtx,
2986
+ queryEmbedding,
2987
+ limit,
2988
+ minSimilarity
2989
+ );
2990
+ if (results.length === 0) {
2991
+ console.warn(
2992
+ `[Memory Search] No memories found above similarity threshold ${minSimilarity}.`
2993
+ );
2994
+ } else {
2995
+ console.log(
2996
+ `[Memory Search] Found ${results.length} memories. Similarity scores: ${results.map((r) => r.similarity.toFixed(3)).join(", ")}`
2997
+ );
2998
+ }
2999
+ return results;
3000
+ } catch {
3001
+ return [];
3002
+ }
3003
+ },
3004
+ [embeddingModel, embeddingOptions, storageCtx]
3005
+ );
3006
+ const fetchAllMemories = (0, import_react5.useCallback)(async () => {
3007
+ try {
3008
+ return await getAllMemoriesOp(storageCtx);
3009
+ } catch (error) {
3010
+ throw new Error(
3011
+ "Failed to fetch all memories: " + (error instanceof Error ? error.message : String(error))
3012
+ );
3013
+ }
3014
+ }, [storageCtx]);
3015
+ const fetchMemoriesByNamespace = (0, import_react5.useCallback)(
3016
+ async (namespace) => {
3017
+ if (!namespace) {
3018
+ throw new Error("Missing required field: namespace");
3019
+ }
3020
+ try {
3021
+ return await getMemoriesByNamespaceOp(storageCtx, namespace);
3022
+ } catch (error) {
3023
+ throw new Error(
3024
+ `Failed to fetch memories for namespace "${namespace}": ` + (error instanceof Error ? error.message : String(error))
3025
+ );
3026
+ }
3027
+ },
3028
+ [storageCtx]
3029
+ );
3030
+ const fetchMemoriesByKey = (0, import_react5.useCallback)(
3031
+ async (namespace, key) => {
3032
+ if (!namespace || !key) {
3033
+ throw new Error("Missing required fields: namespace, key");
3034
+ }
3035
+ try {
3036
+ return await getMemoriesByKeyOp(storageCtx, namespace, key);
3037
+ } catch (error) {
3038
+ throw new Error(
3039
+ `Failed to fetch memories for "${namespace}:${key}": ` + (error instanceof Error ? error.message : String(error))
3040
+ );
3041
+ }
3042
+ },
3043
+ [storageCtx]
3044
+ );
3045
+ const getMemoryById = (0, import_react5.useCallback)(
3046
+ async (id) => {
3047
+ try {
3048
+ return await getMemoryByIdOp(storageCtx, id);
3049
+ } catch (error) {
3050
+ throw new Error(
3051
+ `Failed to get memory ${id}: ` + (error instanceof Error ? error.message : String(error))
3052
+ );
3053
+ }
3054
+ },
3055
+ [storageCtx]
3056
+ );
3057
+ const saveMemory = (0, import_react5.useCallback)(
3058
+ async (memory) => {
3059
+ try {
3060
+ const saved = await saveMemoryOp(storageCtx, memory);
3061
+ if (generateEmbeddings && embeddingModel && !memory.embedding) {
3062
+ try {
3063
+ const memoryItem = {
3064
+ type: memory.type,
3065
+ namespace: memory.namespace,
3066
+ key: memory.key,
3067
+ value: memory.value,
3068
+ rawEvidence: memory.rawEvidence,
3069
+ confidence: memory.confidence,
3070
+ pii: memory.pii
3071
+ };
3072
+ const embedding = await generateEmbeddingForMemoryApi(
3073
+ memoryItem,
3074
+ embeddingOptions
3075
+ );
3076
+ await updateMemoryEmbeddingOp(
3077
+ storageCtx,
3078
+ saved.uniqueId,
3079
+ embedding,
3080
+ embeddingOptions.model
3081
+ );
3082
+ } catch (error) {
3083
+ console.error("Failed to generate embedding:", error);
3084
+ }
3085
+ }
3086
+ setMemories((prev) => {
3087
+ const existing = prev.find((m) => m.uniqueId === saved.uniqueId);
3088
+ if (existing) {
3089
+ return prev.map((m) => m.uniqueId === saved.uniqueId ? saved : m);
3090
+ }
3091
+ return [saved, ...prev];
3092
+ });
3093
+ return saved;
3094
+ } catch (error) {
3095
+ throw new Error(
3096
+ "Failed to save memory: " + (error instanceof Error ? error.message : String(error))
3097
+ );
3098
+ }
3099
+ },
3100
+ [storageCtx, generateEmbeddings, embeddingModel, embeddingOptions]
3101
+ );
3102
+ const saveMemories = (0, import_react5.useCallback)(
3103
+ async (memoriesToSave) => {
3104
+ try {
3105
+ const saved = await saveMemoriesOp(storageCtx, memoriesToSave);
3106
+ if (generateEmbeddings && embeddingModel) {
3107
+ for (let i = 0; i < saved.length; i++) {
3108
+ const memory = memoriesToSave[i];
3109
+ if (!memory.embedding) {
3110
+ try {
3111
+ const memoryItem = {
3112
+ type: memory.type,
3113
+ namespace: memory.namespace,
3114
+ key: memory.key,
3115
+ value: memory.value,
3116
+ rawEvidence: memory.rawEvidence,
3117
+ confidence: memory.confidence,
3118
+ pii: memory.pii
3119
+ };
3120
+ const embedding = await generateEmbeddingForMemoryApi(
3121
+ memoryItem,
3122
+ embeddingOptions
3123
+ );
3124
+ await updateMemoryEmbeddingOp(
3125
+ storageCtx,
3126
+ saved[i].uniqueId,
3127
+ embedding,
3128
+ embeddingOptions.model
3129
+ );
3130
+ } catch (error) {
3131
+ console.error("Failed to generate embedding:", error);
3132
+ }
3133
+ }
3134
+ }
3135
+ }
3136
+ await refreshMemories();
3137
+ return saved;
3138
+ } catch (error) {
3139
+ throw new Error(
3140
+ "Failed to save memories: " + (error instanceof Error ? error.message : String(error))
3141
+ );
3142
+ }
3143
+ },
3144
+ [storageCtx, generateEmbeddings, embeddingModel, embeddingOptions, refreshMemories]
3145
+ );
3146
+ const updateMemory = (0, import_react5.useCallback)(
3147
+ async (id, updates) => {
3148
+ const result = await updateMemoryOp(storageCtx, id, updates);
3149
+ if (!result.ok) {
3150
+ if (result.reason === "not_found") {
3151
+ return null;
3152
+ }
3153
+ if (result.reason === "conflict") {
3154
+ throw new Error(
3155
+ `Cannot update memory: a memory with key "${result.conflictingKey}" already exists`
3156
+ );
3157
+ }
3158
+ throw new Error(
3159
+ `Failed to update memory ${id}: ${result.error.message}`
3160
+ );
3161
+ }
3162
+ const updated = result.memory;
3163
+ const contentChanged = updates.value !== void 0 || updates.rawEvidence !== void 0 || updates.type !== void 0 || updates.namespace !== void 0 || updates.key !== void 0;
3164
+ if (contentChanged && generateEmbeddings && embeddingModel && !updates.embedding) {
3165
+ try {
3166
+ const memoryItem = {
3167
+ type: updated.type,
3168
+ namespace: updated.namespace,
3169
+ key: updated.key,
3170
+ value: updated.value,
3171
+ rawEvidence: updated.rawEvidence,
3172
+ confidence: updated.confidence,
3173
+ pii: updated.pii
3174
+ };
3175
+ const embedding = await generateEmbeddingForMemoryApi(
3176
+ memoryItem,
3177
+ embeddingOptions
3178
+ );
3179
+ await updateMemoryEmbeddingOp(storageCtx, id, embedding, embeddingOptions.model);
3180
+ } catch (error) {
3181
+ console.error("Failed to regenerate embedding:", error);
3182
+ }
3183
+ }
3184
+ setMemories((prev) => prev.map((m) => m.uniqueId === id ? updated : m));
3185
+ return updated;
3186
+ },
3187
+ [storageCtx, generateEmbeddings, embeddingModel, embeddingOptions]
3188
+ );
3189
+ const removeMemory = (0, import_react5.useCallback)(
3190
+ async (namespace, key, value) => {
3191
+ if (!namespace || !key || !value) {
3192
+ throw new Error("Missing required fields: namespace, key, value");
3193
+ }
3194
+ try {
3195
+ await deleteMemoryOp(storageCtx, namespace, key, value);
3196
+ setMemories(
3197
+ (prev) => prev.filter(
3198
+ (m) => !(m.namespace === namespace && m.key === key && m.value === value)
3199
+ )
3200
+ );
3201
+ } catch (error) {
3202
+ throw new Error(
3203
+ `Failed to delete memory "${namespace}:${key}:${value}": ` + (error instanceof Error ? error.message : String(error))
3204
+ );
3205
+ }
3206
+ },
3207
+ [storageCtx]
3208
+ );
3209
+ const removeMemoryById = (0, import_react5.useCallback)(
3210
+ async (id) => {
3211
+ try {
3212
+ await deleteMemoryByIdOp(storageCtx, id);
3213
+ setMemories((prev) => prev.filter((m) => m.uniqueId !== id));
3214
+ } catch (error) {
3215
+ throw new Error(
3216
+ `Failed to delete memory with id ${id}: ` + (error instanceof Error ? error.message : String(error))
3217
+ );
3218
+ }
3219
+ },
3220
+ [storageCtx]
3221
+ );
3222
+ const removeMemories = (0, import_react5.useCallback)(
3223
+ async (namespace, key) => {
3224
+ if (!namespace || !key) {
3225
+ throw new Error("Missing required fields: namespace, key");
3226
+ }
3227
+ try {
3228
+ await deleteMemoriesByKeyOp(storageCtx, namespace, key);
3229
+ setMemories(
3230
+ (prev) => prev.filter((m) => !(m.namespace === namespace && m.key === key))
3231
+ );
3232
+ } catch (error) {
3233
+ throw new Error(
3234
+ `Failed to delete memories for "${namespace}:${key}": ` + (error instanceof Error ? error.message : String(error))
3235
+ );
3236
+ }
3237
+ },
3238
+ [storageCtx]
3239
+ );
3240
+ const clearMemories = (0, import_react5.useCallback)(async () => {
3241
+ try {
3242
+ await clearAllMemoriesOp(storageCtx);
3243
+ setMemories([]);
3244
+ } catch (error) {
3245
+ throw new Error(
3246
+ "Failed to clear all memories: " + (error instanceof Error ? error.message : String(error))
3247
+ );
3248
+ }
3249
+ }, [storageCtx]);
3250
+ return {
3251
+ memories,
3252
+ refreshMemories,
3253
+ extractMemoriesFromMessage,
3254
+ searchMemories,
3255
+ fetchAllMemories,
3256
+ fetchMemoriesByNamespace,
3257
+ fetchMemoriesByKey,
3258
+ getMemoryById,
3259
+ saveMemory,
3260
+ saveMemories,
3261
+ updateMemory,
3262
+ removeMemory,
3263
+ removeMemoryById,
3264
+ removeMemories,
3265
+ clearMemories
3266
+ };
3267
+ }
3268
+
3269
+ // src/lib/db/schema.ts
3270
+ var import_watermelondb8 = require("@nozbe/watermelondb");
3271
+ var import_migrations2 = require("@nozbe/watermelondb/Schema/migrations");
3272
+
3273
+ // src/lib/db/settings/models.ts
3274
+ var import_watermelondb7 = require("@nozbe/watermelondb");
3275
+ var import_decorators3 = require("@nozbe/watermelondb/decorators");
3276
+ var ModelPreference = class extends import_watermelondb7.Model {
3277
+ };
3278
+ ModelPreference.table = "modelPreferences";
3279
+ __decorateClass([
3280
+ (0, import_decorators3.text)("wallet_address")
3281
+ ], ModelPreference.prototype, "walletAddress", 2);
3282
+ __decorateClass([
3283
+ (0, import_decorators3.text)("models")
3284
+ ], ModelPreference.prototype, "models", 2);
3285
+
3286
+ // src/lib/db/schema.ts
3287
+ var SDK_SCHEMA_VERSION = 6;
3288
+ var sdkSchema = (0, import_watermelondb8.appSchema)({
3289
+ version: SDK_SCHEMA_VERSION,
3290
+ tables: [
3291
+ // Chat storage tables
3292
+ (0, import_watermelondb8.tableSchema)({
3293
+ name: "history",
3294
+ columns: [
3295
+ { name: "message_id", type: "number" },
3296
+ { name: "conversation_id", type: "string", isIndexed: true },
3297
+ { name: "role", type: "string", isIndexed: true },
3298
+ { name: "content", type: "string" },
3299
+ { name: "model", type: "string", isOptional: true },
3300
+ { name: "files", type: "string", isOptional: true },
3301
+ { name: "created_at", type: "number", isIndexed: true },
3302
+ { name: "updated_at", type: "number" },
3303
+ { name: "vector", type: "string", isOptional: true },
3304
+ { name: "embedding_model", type: "string", isOptional: true },
3305
+ { name: "usage", type: "string", isOptional: true },
3306
+ { name: "sources", type: "string", isOptional: true },
3307
+ { name: "response_duration", type: "number", isOptional: true },
3308
+ { name: "was_stopped", type: "boolean", isOptional: true },
3309
+ { name: "error", type: "string", isOptional: true },
3310
+ { name: "thought_process", type: "string", isOptional: true }
3311
+ // JSON stringified ActivityPhase[]
3312
+ ]
3313
+ }),
3314
+ (0, import_watermelondb8.tableSchema)({
3315
+ name: "conversations",
3316
+ columns: [
3317
+ { name: "conversation_id", type: "string", isIndexed: true },
3318
+ { name: "title", type: "string" },
3319
+ { name: "created_at", type: "number" },
3320
+ { name: "updated_at", type: "number" },
3321
+ { name: "is_deleted", type: "boolean", isIndexed: true }
3322
+ ]
3323
+ }),
3324
+ // Memory storage tables
3325
+ (0, import_watermelondb8.tableSchema)({
3326
+ name: "memories",
3327
+ columns: [
3328
+ { name: "type", type: "string", isIndexed: true },
3329
+ { name: "namespace", type: "string", isIndexed: true },
3330
+ { name: "key", type: "string", isIndexed: true },
3331
+ { name: "value", type: "string" },
3332
+ { name: "raw_evidence", type: "string" },
3333
+ { name: "confidence", type: "number" },
3334
+ { name: "pii", type: "boolean", isIndexed: true },
3335
+ { name: "composite_key", type: "string", isIndexed: true },
3336
+ { name: "unique_key", type: "string", isIndexed: true },
3337
+ { name: "created_at", type: "number", isIndexed: true },
3338
+ { name: "updated_at", type: "number" },
3339
+ { name: "embedding", type: "string", isOptional: true },
3340
+ { name: "embedding_model", type: "string", isOptional: true },
3341
+ { name: "is_deleted", type: "boolean", isIndexed: true }
3342
+ ]
3343
+ }),
3344
+ // Settings storage tables
3345
+ (0, import_watermelondb8.tableSchema)({
3346
+ name: "modelPreferences",
3347
+ columns: [
3348
+ { name: "wallet_address", type: "string", isIndexed: true },
3349
+ { name: "models", type: "string", isOptional: true }
3350
+ ]
3351
+ })
3352
+ ]
3353
+ });
3354
+ var sdkMigrations = (0, import_migrations2.schemaMigrations)({
3355
+ migrations: [
3356
+ // v2 -> v3: Added was_stopped column to history
3357
+ {
3358
+ toVersion: 3,
3359
+ steps: [
3360
+ (0, import_migrations2.addColumns)({
3361
+ table: "history",
3362
+ columns: [{ name: "was_stopped", type: "boolean", isOptional: true }]
3363
+ })
3364
+ ]
3365
+ },
3366
+ // v3 -> v4: Added settings storage (modelPreferences table)
3367
+ {
3368
+ toVersion: 4,
3369
+ steps: [
3370
+ (0, import_migrations2.createTable)({
3371
+ name: "modelPreferences",
3372
+ columns: [
3373
+ { name: "wallet_address", type: "string", isIndexed: true },
3374
+ { name: "models", type: "string", isOptional: true }
3375
+ ]
3376
+ })
3377
+ ]
3378
+ },
3379
+ // v4 -> v5: Added error column to history for error persistence
3380
+ {
3381
+ toVersion: 5,
3382
+ steps: [
3383
+ (0, import_migrations2.addColumns)({
3384
+ table: "history",
3385
+ columns: [{ name: "error", type: "string", isOptional: true }]
3386
+ })
3387
+ ]
3388
+ },
3389
+ // v5 -> v6: Added thought_process column to history table
3390
+ {
3391
+ toVersion: 6,
3392
+ steps: [
3393
+ (0, import_migrations2.addColumns)({
3394
+ table: "history",
3395
+ columns: [
3396
+ { name: "thought_process", type: "string", isOptional: true }
3397
+ ]
3398
+ })
3399
+ ]
3400
+ }
3401
+ ]
3402
+ });
3403
+ var sdkModelClasses = [
3404
+ Message,
3405
+ Conversation,
3406
+ Memory,
3407
+ ModelPreference
3408
+ ];
3409
+ // Annotate the CommonJS export names for ESM import in node:
3410
+ 0 && (module.exports = {
3411
+ ChatConversation,
3412
+ ChatMessage,
3413
+ StoredMemoryModel,
3414
+ chatStorageMigrations,
3415
+ chatStorageSchema,
3416
+ generateCompositeKey,
3417
+ generateConversationId,
3418
+ generateUniqueKey,
3419
+ memoryStorageSchema,
3420
+ sdkMigrations,
3421
+ sdkModelClasses,
3422
+ sdkSchema,
3423
+ useChat,
3424
+ useChatStorage,
3425
+ useImageGeneration,
3426
+ useMemoryStorage,
3427
+ useModels
3428
+ });