mem0ai 2.1.8 → 2.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/oss/index.d.mts +67 -2
- package/dist/oss/index.d.ts +67 -2
- package/dist/oss/index.js +571 -70
- package/dist/oss/index.js.map +1 -1
- package/dist/oss/index.mjs +568 -70
- package/dist/oss/index.mjs.map +1 -1
- package/package.json +17 -5
package/dist/oss/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/oss/src/memory/index.ts
|
|
2
|
-
import { v4 as
|
|
2
|
+
import { v4 as uuidv43 } from "uuid";
|
|
3
3
|
import { createHash } from "crypto";
|
|
4
4
|
|
|
5
5
|
// src/oss/src/types/index.ts
|
|
@@ -42,7 +42,12 @@ var MemoryConfigSchema = z.object({
|
|
|
42
42
|
config: z.record(z.string(), z.any())
|
|
43
43
|
}).optional(),
|
|
44
44
|
customPrompt: z.string().optional()
|
|
45
|
-
}).optional()
|
|
45
|
+
}).optional(),
|
|
46
|
+
historyStore: z.object({
|
|
47
|
+
provider: z.string(),
|
|
48
|
+
config: z.record(z.string(), z.any())
|
|
49
|
+
}).optional(),
|
|
50
|
+
disableHistory: z.boolean().optional()
|
|
46
51
|
});
|
|
47
52
|
|
|
48
53
|
// src/oss/src/embeddings/openai.ts
|
|
@@ -68,6 +73,60 @@ var OpenAIEmbedder = class {
|
|
|
68
73
|
}
|
|
69
74
|
};
|
|
70
75
|
|
|
76
|
+
// src/oss/src/embeddings/ollama.ts
|
|
77
|
+
import { Ollama } from "ollama";
|
|
78
|
+
|
|
79
|
+
// src/oss/src/utils/logger.ts
|
|
80
|
+
var logger = {
|
|
81
|
+
info: (message) => console.log(`[INFO] ${message}`),
|
|
82
|
+
error: (message) => console.error(`[ERROR] ${message}`),
|
|
83
|
+
debug: (message) => console.debug(`[DEBUG] ${message}`),
|
|
84
|
+
warn: (message) => console.warn(`[WARN] ${message}`)
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// src/oss/src/embeddings/ollama.ts
|
|
88
|
+
var OllamaEmbedder = class {
|
|
89
|
+
constructor(config) {
|
|
90
|
+
// Using this variable to avoid calling the Ollama server multiple times
|
|
91
|
+
this.initialized = false;
|
|
92
|
+
this.ollama = new Ollama({
|
|
93
|
+
host: config.url || "http://localhost:11434"
|
|
94
|
+
});
|
|
95
|
+
this.model = config.model || "nomic-embed-text:latest";
|
|
96
|
+
this.ensureModelExists().catch((err) => {
|
|
97
|
+
logger.error(`Error ensuring model exists: ${err}`);
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
async embed(text) {
|
|
101
|
+
try {
|
|
102
|
+
await this.ensureModelExists();
|
|
103
|
+
} catch (err) {
|
|
104
|
+
logger.error(`Error ensuring model exists: ${err}`);
|
|
105
|
+
}
|
|
106
|
+
const response = await this.ollama.embeddings({
|
|
107
|
+
model: this.model,
|
|
108
|
+
prompt: text
|
|
109
|
+
});
|
|
110
|
+
return response.embedding;
|
|
111
|
+
}
|
|
112
|
+
async embedBatch(texts) {
|
|
113
|
+
const response = await Promise.all(texts.map((text) => this.embed(text)));
|
|
114
|
+
return response;
|
|
115
|
+
}
|
|
116
|
+
async ensureModelExists() {
|
|
117
|
+
if (this.initialized) {
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
const local_models = await this.ollama.list();
|
|
121
|
+
if (!local_models.models.find((m) => m.name === this.model)) {
|
|
122
|
+
logger.info(`Pulling model ${this.model}...`);
|
|
123
|
+
await this.ollama.pull({ model: this.model });
|
|
124
|
+
}
|
|
125
|
+
this.initialized = true;
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
|
|
71
130
|
// src/oss/src/llms/openai.ts
|
|
72
131
|
import OpenAI2 from "openai";
|
|
73
132
|
var OpenAILLM = class {
|
|
@@ -1025,12 +1084,459 @@ var RedisDB = class {
|
|
|
1025
1084
|
}
|
|
1026
1085
|
};
|
|
1027
1086
|
|
|
1087
|
+
// src/oss/src/llms/ollama.ts
|
|
1088
|
+
import { Ollama as Ollama2 } from "ollama";
|
|
1089
|
+
var OllamaLLM = class {
|
|
1090
|
+
constructor(config) {
|
|
1091
|
+
// Using this variable to avoid calling the Ollama server multiple times
|
|
1092
|
+
this.initialized = false;
|
|
1093
|
+
var _a;
|
|
1094
|
+
this.ollama = new Ollama2({
|
|
1095
|
+
host: ((_a = config.config) == null ? void 0 : _a.url) || "http://localhost:11434"
|
|
1096
|
+
});
|
|
1097
|
+
this.model = config.model || "llama3.1:8b";
|
|
1098
|
+
this.ensureModelExists().catch((err) => {
|
|
1099
|
+
logger.error(`Error ensuring model exists: ${err}`);
|
|
1100
|
+
});
|
|
1101
|
+
}
|
|
1102
|
+
async generateResponse(messages, responseFormat, tools) {
|
|
1103
|
+
try {
|
|
1104
|
+
await this.ensureModelExists();
|
|
1105
|
+
} catch (err) {
|
|
1106
|
+
logger.error(`Error ensuring model exists: ${err}`);
|
|
1107
|
+
}
|
|
1108
|
+
const completion = await this.ollama.chat({
|
|
1109
|
+
model: this.model,
|
|
1110
|
+
messages: messages.map((msg) => {
|
|
1111
|
+
const role = msg.role;
|
|
1112
|
+
return {
|
|
1113
|
+
role,
|
|
1114
|
+
content: typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content)
|
|
1115
|
+
};
|
|
1116
|
+
}),
|
|
1117
|
+
...(responseFormat == null ? void 0 : responseFormat.type) === "json_object" && { format: "json" },
|
|
1118
|
+
...tools && { tools, tool_choice: "auto" }
|
|
1119
|
+
});
|
|
1120
|
+
const response = completion.message;
|
|
1121
|
+
if (response.tool_calls) {
|
|
1122
|
+
return {
|
|
1123
|
+
content: response.content || "",
|
|
1124
|
+
role: response.role,
|
|
1125
|
+
toolCalls: response.tool_calls.map((call) => ({
|
|
1126
|
+
name: call.function.name,
|
|
1127
|
+
arguments: JSON.stringify(call.function.arguments)
|
|
1128
|
+
}))
|
|
1129
|
+
};
|
|
1130
|
+
}
|
|
1131
|
+
return response.content || "";
|
|
1132
|
+
}
|
|
1133
|
+
async generateChat(messages) {
|
|
1134
|
+
try {
|
|
1135
|
+
await this.ensureModelExists();
|
|
1136
|
+
} catch (err) {
|
|
1137
|
+
logger.error(`Error ensuring model exists: ${err}`);
|
|
1138
|
+
}
|
|
1139
|
+
const completion = await this.ollama.chat({
|
|
1140
|
+
messages: messages.map((msg) => {
|
|
1141
|
+
const role = msg.role;
|
|
1142
|
+
return {
|
|
1143
|
+
role,
|
|
1144
|
+
content: typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content)
|
|
1145
|
+
};
|
|
1146
|
+
}),
|
|
1147
|
+
model: this.model
|
|
1148
|
+
});
|
|
1149
|
+
const response = completion.message;
|
|
1150
|
+
return {
|
|
1151
|
+
content: response.content || "",
|
|
1152
|
+
role: response.role
|
|
1153
|
+
};
|
|
1154
|
+
}
|
|
1155
|
+
async ensureModelExists() {
|
|
1156
|
+
if (this.initialized) {
|
|
1157
|
+
return true;
|
|
1158
|
+
}
|
|
1159
|
+
const local_models = await this.ollama.list();
|
|
1160
|
+
if (!local_models.models.find((m) => m.name === this.model)) {
|
|
1161
|
+
logger.info(`Pulling model ${this.model}...`);
|
|
1162
|
+
await this.ollama.pull({ model: this.model });
|
|
1163
|
+
}
|
|
1164
|
+
this.initialized = true;
|
|
1165
|
+
return true;
|
|
1166
|
+
}
|
|
1167
|
+
};
|
|
1168
|
+
|
|
1169
|
+
// src/oss/src/vector_stores/supabase.ts
|
|
1170
|
+
import { createClient as createClient2 } from "@supabase/supabase-js";
|
|
1171
|
+
var SupabaseDB = class {
|
|
1172
|
+
constructor(config) {
|
|
1173
|
+
this.client = createClient2(config.supabaseUrl, config.supabaseKey);
|
|
1174
|
+
this.tableName = config.tableName;
|
|
1175
|
+
this.embeddingColumnName = config.embeddingColumnName || "embedding";
|
|
1176
|
+
this.metadataColumnName = config.metadataColumnName || "metadata";
|
|
1177
|
+
this.initialize().catch((err) => {
|
|
1178
|
+
console.error("Failed to initialize Supabase:", err);
|
|
1179
|
+
throw err;
|
|
1180
|
+
});
|
|
1181
|
+
}
|
|
1182
|
+
async initialize() {
|
|
1183
|
+
try {
|
|
1184
|
+
const testVector = Array(1536).fill(0);
|
|
1185
|
+
try {
|
|
1186
|
+
await this.client.from(this.tableName).delete().eq("id", "test_vector");
|
|
1187
|
+
} catch (error) {
|
|
1188
|
+
console.warn("No test vector to delete, safe to ignore.");
|
|
1189
|
+
}
|
|
1190
|
+
const { error: testError } = await this.client.from(this.tableName).insert({
|
|
1191
|
+
id: "test_vector",
|
|
1192
|
+
[this.embeddingColumnName]: testVector,
|
|
1193
|
+
[this.metadataColumnName]: {}
|
|
1194
|
+
}).select();
|
|
1195
|
+
if (testError) {
|
|
1196
|
+
console.error("Test insert error:", testError);
|
|
1197
|
+
throw new Error(
|
|
1198
|
+
`Vector operations failed. Please ensure:
|
|
1199
|
+
1. The vector extension is enabled
|
|
1200
|
+
2. The table "${this.tableName}" exists with correct schema
|
|
1201
|
+
3. The match_vectors function is created
|
|
1202
|
+
|
|
1203
|
+
RUN THE FOLLOWING SQL IN YOUR SUPABASE SQL EDITOR:
|
|
1204
|
+
|
|
1205
|
+
-- Enable the vector extension
|
|
1206
|
+
create extension if not exists vector;
|
|
1207
|
+
|
|
1208
|
+
-- Create the memories table
|
|
1209
|
+
create table if not exists memories (
|
|
1210
|
+
id text primary key,
|
|
1211
|
+
embedding vector(1536),
|
|
1212
|
+
metadata jsonb,
|
|
1213
|
+
created_at timestamp with time zone default timezone('utc', now()),
|
|
1214
|
+
updated_at timestamp with time zone default timezone('utc', now())
|
|
1215
|
+
);
|
|
1216
|
+
|
|
1217
|
+
-- Create the vector similarity search function
|
|
1218
|
+
create or replace function match_vectors(
|
|
1219
|
+
query_embedding vector(1536),
|
|
1220
|
+
match_count int,
|
|
1221
|
+
filter jsonb default '{}'::jsonb
|
|
1222
|
+
)
|
|
1223
|
+
returns table (
|
|
1224
|
+
id text,
|
|
1225
|
+
similarity float,
|
|
1226
|
+
metadata jsonb
|
|
1227
|
+
)
|
|
1228
|
+
language plpgsql
|
|
1229
|
+
as $$
|
|
1230
|
+
begin
|
|
1231
|
+
return query
|
|
1232
|
+
select
|
|
1233
|
+
id,
|
|
1234
|
+
similarity,
|
|
1235
|
+
metadata
|
|
1236
|
+
from memories
|
|
1237
|
+
where case
|
|
1238
|
+
when filter::text = '{}'::text then true
|
|
1239
|
+
else metadata @> filter
|
|
1240
|
+
end
|
|
1241
|
+
order by embedding <=> query_embedding
|
|
1242
|
+
limit match_count;
|
|
1243
|
+
end;
|
|
1244
|
+
$$;
|
|
1245
|
+
|
|
1246
|
+
See the SQL migration instructions in the code comments.`
|
|
1247
|
+
);
|
|
1248
|
+
}
|
|
1249
|
+
await this.client.from(this.tableName).delete().eq("id", "test_vector");
|
|
1250
|
+
console.log("Connected to Supabase successfully");
|
|
1251
|
+
} catch (error) {
|
|
1252
|
+
console.error("Error during Supabase initialization:", error);
|
|
1253
|
+
throw error;
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
async insert(vectors, ids, payloads) {
|
|
1257
|
+
try {
|
|
1258
|
+
const data = vectors.map((vector, idx) => ({
|
|
1259
|
+
id: ids[idx],
|
|
1260
|
+
[this.embeddingColumnName]: vector,
|
|
1261
|
+
[this.metadataColumnName]: {
|
|
1262
|
+
...payloads[idx],
|
|
1263
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
1264
|
+
}
|
|
1265
|
+
}));
|
|
1266
|
+
const { error } = await this.client.from(this.tableName).insert(data);
|
|
1267
|
+
if (error) throw error;
|
|
1268
|
+
} catch (error) {
|
|
1269
|
+
console.error("Error during vector insert:", error);
|
|
1270
|
+
throw error;
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
async search(query, limit = 5, filters) {
|
|
1274
|
+
try {
|
|
1275
|
+
const rpcQuery = {
|
|
1276
|
+
query_embedding: query,
|
|
1277
|
+
match_count: limit
|
|
1278
|
+
};
|
|
1279
|
+
if (filters) {
|
|
1280
|
+
rpcQuery.filter = filters;
|
|
1281
|
+
}
|
|
1282
|
+
const { data, error } = await this.client.rpc("match_vectors", rpcQuery);
|
|
1283
|
+
if (error) throw error;
|
|
1284
|
+
if (!data) return [];
|
|
1285
|
+
const results = data;
|
|
1286
|
+
return results.map((result) => ({
|
|
1287
|
+
id: result.id,
|
|
1288
|
+
payload: result.metadata,
|
|
1289
|
+
score: result.similarity
|
|
1290
|
+
}));
|
|
1291
|
+
} catch (error) {
|
|
1292
|
+
console.error("Error during vector search:", error);
|
|
1293
|
+
throw error;
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
async get(vectorId) {
|
|
1297
|
+
try {
|
|
1298
|
+
const { data, error } = await this.client.from(this.tableName).select("*").eq("id", vectorId).single();
|
|
1299
|
+
if (error) throw error;
|
|
1300
|
+
if (!data) return null;
|
|
1301
|
+
return {
|
|
1302
|
+
id: data.id,
|
|
1303
|
+
payload: data[this.metadataColumnName]
|
|
1304
|
+
};
|
|
1305
|
+
} catch (error) {
|
|
1306
|
+
console.error("Error getting vector:", error);
|
|
1307
|
+
throw error;
|
|
1308
|
+
}
|
|
1309
|
+
}
|
|
1310
|
+
async update(vectorId, vector, payload) {
|
|
1311
|
+
try {
|
|
1312
|
+
const { error } = await this.client.from(this.tableName).update({
|
|
1313
|
+
[this.embeddingColumnName]: vector,
|
|
1314
|
+
[this.metadataColumnName]: {
|
|
1315
|
+
...payload,
|
|
1316
|
+
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
1317
|
+
}
|
|
1318
|
+
}).eq("id", vectorId);
|
|
1319
|
+
if (error) throw error;
|
|
1320
|
+
} catch (error) {
|
|
1321
|
+
console.error("Error during vector update:", error);
|
|
1322
|
+
throw error;
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
async delete(vectorId) {
|
|
1326
|
+
try {
|
|
1327
|
+
const { error } = await this.client.from(this.tableName).delete().eq("id", vectorId);
|
|
1328
|
+
if (error) throw error;
|
|
1329
|
+
} catch (error) {
|
|
1330
|
+
console.error("Error deleting vector:", error);
|
|
1331
|
+
throw error;
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
async deleteCol() {
|
|
1335
|
+
try {
|
|
1336
|
+
const { error } = await this.client.from(this.tableName).delete().neq("id", "");
|
|
1337
|
+
if (error) throw error;
|
|
1338
|
+
} catch (error) {
|
|
1339
|
+
console.error("Error deleting collection:", error);
|
|
1340
|
+
throw error;
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
async list(filters, limit = 100) {
|
|
1344
|
+
try {
|
|
1345
|
+
let query = this.client.from(this.tableName).select("*", { count: "exact" }).limit(limit);
|
|
1346
|
+
if (filters) {
|
|
1347
|
+
Object.entries(filters).forEach(([key, value]) => {
|
|
1348
|
+
query = query.eq(`${this.metadataColumnName}->>${key}`, value);
|
|
1349
|
+
});
|
|
1350
|
+
}
|
|
1351
|
+
const { data, error, count } = await query;
|
|
1352
|
+
if (error) throw error;
|
|
1353
|
+
const results = data.map((item) => ({
|
|
1354
|
+
id: item.id,
|
|
1355
|
+
payload: item[this.metadataColumnName]
|
|
1356
|
+
}));
|
|
1357
|
+
return [results, count || 0];
|
|
1358
|
+
} catch (error) {
|
|
1359
|
+
console.error("Error listing vectors:", error);
|
|
1360
|
+
throw error;
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
};
|
|
1364
|
+
|
|
1365
|
+
// src/oss/src/storage/SQLiteManager.ts
|
|
1366
|
+
import sqlite32 from "sqlite3";
|
|
1367
|
+
var SQLiteManager = class {
|
|
1368
|
+
constructor(dbPath) {
|
|
1369
|
+
this.db = new sqlite32.Database(dbPath);
|
|
1370
|
+
this.init().catch(console.error);
|
|
1371
|
+
}
|
|
1372
|
+
async init() {
|
|
1373
|
+
await this.run(`
|
|
1374
|
+
CREATE TABLE IF NOT EXISTS memory_history (
|
|
1375
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
1376
|
+
memory_id TEXT NOT NULL,
|
|
1377
|
+
previous_value TEXT,
|
|
1378
|
+
new_value TEXT,
|
|
1379
|
+
action TEXT NOT NULL,
|
|
1380
|
+
created_at TEXT,
|
|
1381
|
+
updated_at TEXT,
|
|
1382
|
+
is_deleted INTEGER DEFAULT 0
|
|
1383
|
+
)
|
|
1384
|
+
`);
|
|
1385
|
+
}
|
|
1386
|
+
async run(sql, params = []) {
|
|
1387
|
+
return new Promise((resolve, reject) => {
|
|
1388
|
+
this.db.run(sql, params, (err) => {
|
|
1389
|
+
if (err) reject(err);
|
|
1390
|
+
else resolve();
|
|
1391
|
+
});
|
|
1392
|
+
});
|
|
1393
|
+
}
|
|
1394
|
+
async all(sql, params = []) {
|
|
1395
|
+
return new Promise((resolve, reject) => {
|
|
1396
|
+
this.db.all(sql, params, (err, rows) => {
|
|
1397
|
+
if (err) reject(err);
|
|
1398
|
+
else resolve(rows);
|
|
1399
|
+
});
|
|
1400
|
+
});
|
|
1401
|
+
}
|
|
1402
|
+
async addHistory(memoryId, previousValue, newValue, action, createdAt, updatedAt, isDeleted = 0) {
|
|
1403
|
+
await this.run(
|
|
1404
|
+
`INSERT INTO memory_history
|
|
1405
|
+
(memory_id, previous_value, new_value, action, created_at, updated_at, is_deleted)
|
|
1406
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
|
1407
|
+
[
|
|
1408
|
+
memoryId,
|
|
1409
|
+
previousValue,
|
|
1410
|
+
newValue,
|
|
1411
|
+
action,
|
|
1412
|
+
createdAt,
|
|
1413
|
+
updatedAt,
|
|
1414
|
+
isDeleted
|
|
1415
|
+
]
|
|
1416
|
+
);
|
|
1417
|
+
}
|
|
1418
|
+
async getHistory(memoryId) {
|
|
1419
|
+
return this.all(
|
|
1420
|
+
"SELECT * FROM memory_history WHERE memory_id = ? ORDER BY id DESC",
|
|
1421
|
+
[memoryId]
|
|
1422
|
+
);
|
|
1423
|
+
}
|
|
1424
|
+
async reset() {
|
|
1425
|
+
await this.run("DROP TABLE IF EXISTS memory_history");
|
|
1426
|
+
await this.init();
|
|
1427
|
+
}
|
|
1428
|
+
close() {
|
|
1429
|
+
this.db.close();
|
|
1430
|
+
}
|
|
1431
|
+
};
|
|
1432
|
+
|
|
1433
|
+
// src/oss/src/storage/MemoryHistoryManager.ts
|
|
1434
|
+
import { v4 as uuidv4 } from "uuid";
|
|
1435
|
+
var MemoryHistoryManager = class {
|
|
1436
|
+
constructor() {
|
|
1437
|
+
this.memoryStore = /* @__PURE__ */ new Map();
|
|
1438
|
+
}
|
|
1439
|
+
async addHistory(memoryId, previousValue, newValue, action, createdAt, updatedAt, isDeleted = 0) {
|
|
1440
|
+
const historyEntry = {
|
|
1441
|
+
id: uuidv4(),
|
|
1442
|
+
memory_id: memoryId,
|
|
1443
|
+
previous_value: previousValue,
|
|
1444
|
+
new_value: newValue,
|
|
1445
|
+
action,
|
|
1446
|
+
created_at: createdAt || (/* @__PURE__ */ new Date()).toISOString(),
|
|
1447
|
+
updated_at: updatedAt || null,
|
|
1448
|
+
is_deleted: isDeleted
|
|
1449
|
+
};
|
|
1450
|
+
this.memoryStore.set(historyEntry.id, historyEntry);
|
|
1451
|
+
}
|
|
1452
|
+
async getHistory(memoryId) {
|
|
1453
|
+
return Array.from(this.memoryStore.values()).filter((entry) => entry.memory_id === memoryId).sort(
|
|
1454
|
+
(a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime()
|
|
1455
|
+
).slice(0, 100);
|
|
1456
|
+
}
|
|
1457
|
+
async reset() {
|
|
1458
|
+
this.memoryStore.clear();
|
|
1459
|
+
}
|
|
1460
|
+
close() {
|
|
1461
|
+
return;
|
|
1462
|
+
}
|
|
1463
|
+
};
|
|
1464
|
+
|
|
1465
|
+
// src/oss/src/storage/SupabaseHistoryManager.ts
|
|
1466
|
+
import { createClient as createClient3 } from "@supabase/supabase-js";
|
|
1467
|
+
import { v4 as uuidv42 } from "uuid";
|
|
1468
|
+
var SupabaseHistoryManager = class {
|
|
1469
|
+
constructor(config) {
|
|
1470
|
+
this.tableName = config.tableName || "memory_history";
|
|
1471
|
+
this.supabase = createClient3(config.supabaseUrl, config.supabaseKey);
|
|
1472
|
+
this.initializeSupabase().catch(console.error);
|
|
1473
|
+
}
|
|
1474
|
+
async initializeSupabase() {
|
|
1475
|
+
const { error } = await this.supabase.from(this.tableName).select("id").limit(1);
|
|
1476
|
+
if (error) {
|
|
1477
|
+
console.error(
|
|
1478
|
+
"Error: Table does not exist. Please run this SQL in your Supabase SQL Editor:"
|
|
1479
|
+
);
|
|
1480
|
+
console.error(`
|
|
1481
|
+
create table ${this.tableName} (
|
|
1482
|
+
id text primary key,
|
|
1483
|
+
memory_id text not null,
|
|
1484
|
+
previous_value text,
|
|
1485
|
+
new_value text,
|
|
1486
|
+
action text not null,
|
|
1487
|
+
created_at timestamp with time zone default timezone('utc', now()),
|
|
1488
|
+
updated_at timestamp with time zone,
|
|
1489
|
+
is_deleted integer default 0
|
|
1490
|
+
);
|
|
1491
|
+
`);
|
|
1492
|
+
throw error;
|
|
1493
|
+
}
|
|
1494
|
+
}
|
|
1495
|
+
async addHistory(memoryId, previousValue, newValue, action, createdAt, updatedAt, isDeleted = 0) {
|
|
1496
|
+
const historyEntry = {
|
|
1497
|
+
id: uuidv42(),
|
|
1498
|
+
memory_id: memoryId,
|
|
1499
|
+
previous_value: previousValue,
|
|
1500
|
+
new_value: newValue,
|
|
1501
|
+
action,
|
|
1502
|
+
created_at: createdAt || (/* @__PURE__ */ new Date()).toISOString(),
|
|
1503
|
+
updated_at: updatedAt || null,
|
|
1504
|
+
is_deleted: isDeleted
|
|
1505
|
+
};
|
|
1506
|
+
const { error } = await this.supabase.from(this.tableName).insert(historyEntry);
|
|
1507
|
+
if (error) {
|
|
1508
|
+
console.error("Error adding history to Supabase:", error);
|
|
1509
|
+
throw error;
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
1512
|
+
async getHistory(memoryId) {
|
|
1513
|
+
const { data, error } = await this.supabase.from(this.tableName).select("*").eq("memory_id", memoryId).order("created_at", { ascending: false }).limit(100);
|
|
1514
|
+
if (error) {
|
|
1515
|
+
console.error("Error getting history from Supabase:", error);
|
|
1516
|
+
throw error;
|
|
1517
|
+
}
|
|
1518
|
+
return data || [];
|
|
1519
|
+
}
|
|
1520
|
+
async reset() {
|
|
1521
|
+
const { error } = await this.supabase.from(this.tableName).delete().neq("id", "");
|
|
1522
|
+
if (error) {
|
|
1523
|
+
console.error("Error resetting Supabase history:", error);
|
|
1524
|
+
throw error;
|
|
1525
|
+
}
|
|
1526
|
+
}
|
|
1527
|
+
close() {
|
|
1528
|
+
return;
|
|
1529
|
+
}
|
|
1530
|
+
};
|
|
1531
|
+
|
|
1028
1532
|
// src/oss/src/utils/factory.ts
|
|
1029
1533
|
var EmbedderFactory = class {
|
|
1030
1534
|
static create(provider, config) {
|
|
1031
1535
|
switch (provider.toLowerCase()) {
|
|
1032
1536
|
case "openai":
|
|
1033
1537
|
return new OpenAIEmbedder(config);
|
|
1538
|
+
case "ollama":
|
|
1539
|
+
return new OllamaEmbedder(config);
|
|
1034
1540
|
default:
|
|
1035
1541
|
throw new Error(`Unsupported embedder provider: ${provider}`);
|
|
1036
1542
|
}
|
|
@@ -1047,6 +1553,8 @@ var LLMFactory = class {
|
|
|
1047
1553
|
return new AnthropicLLM(config);
|
|
1048
1554
|
case "groq":
|
|
1049
1555
|
return new GroqLLM(config);
|
|
1556
|
+
case "ollama":
|
|
1557
|
+
return new OllamaLLM(config);
|
|
1050
1558
|
default:
|
|
1051
1559
|
throw new Error(`Unsupported LLM provider: ${provider}`);
|
|
1052
1560
|
}
|
|
@@ -1063,11 +1571,32 @@ var VectorStoreFactory = class {
|
|
|
1063
1571
|
case "redis":
|
|
1064
1572
|
return new RedisDB(config);
|
|
1065
1573
|
// Type assertion needed as config is extended
|
|
1574
|
+
case "supabase":
|
|
1575
|
+
return new SupabaseDB(config);
|
|
1576
|
+
// Type assertion needed as config is extended
|
|
1066
1577
|
default:
|
|
1067
1578
|
throw new Error(`Unsupported vector store provider: ${provider}`);
|
|
1068
1579
|
}
|
|
1069
1580
|
}
|
|
1070
1581
|
};
|
|
1582
|
+
var HistoryManagerFactory = class {
|
|
1583
|
+
static create(provider, config) {
|
|
1584
|
+
switch (provider.toLowerCase()) {
|
|
1585
|
+
case "sqlite":
|
|
1586
|
+
return new SQLiteManager(config.config.historyDbPath || ":memory:");
|
|
1587
|
+
case "supabase":
|
|
1588
|
+
return new SupabaseHistoryManager({
|
|
1589
|
+
supabaseUrl: config.config.supabaseUrl || "",
|
|
1590
|
+
supabaseKey: config.config.supabaseKey || "",
|
|
1591
|
+
tableName: config.config.tableName || "memory_history"
|
|
1592
|
+
});
|
|
1593
|
+
case "memory":
|
|
1594
|
+
return new MemoryHistoryManager();
|
|
1595
|
+
default:
|
|
1596
|
+
throw new Error(`Unsupported history store provider: ${provider}`);
|
|
1597
|
+
}
|
|
1598
|
+
}
|
|
1599
|
+
};
|
|
1071
1600
|
|
|
1072
1601
|
// src/oss/src/prompts/index.ts
|
|
1073
1602
|
function getFactRetrievalMessages(parsedMessages) {
|
|
@@ -1300,76 +1829,27 @@ function removeCodeBlocks(text) {
|
|
|
1300
1829
|
return text.replace(/```[^`]*```/g, "");
|
|
1301
1830
|
}
|
|
1302
1831
|
|
|
1303
|
-
// src/oss/src/storage/
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
constructor(dbPath) {
|
|
1307
|
-
this.db = new sqlite32.Database(dbPath);
|
|
1308
|
-
this.init().catch(console.error);
|
|
1309
|
-
}
|
|
1310
|
-
async init() {
|
|
1311
|
-
await this.run(`
|
|
1312
|
-
CREATE TABLE IF NOT EXISTS memory_history (
|
|
1313
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
1314
|
-
memory_id TEXT NOT NULL,
|
|
1315
|
-
previous_value TEXT,
|
|
1316
|
-
new_value TEXT,
|
|
1317
|
-
action TEXT NOT NULL,
|
|
1318
|
-
created_at TEXT,
|
|
1319
|
-
updated_at TEXT,
|
|
1320
|
-
is_deleted INTEGER DEFAULT 0
|
|
1321
|
-
)
|
|
1322
|
-
`);
|
|
1323
|
-
}
|
|
1324
|
-
async run(sql, params = []) {
|
|
1325
|
-
return new Promise((resolve, reject) => {
|
|
1326
|
-
this.db.run(sql, params, (err) => {
|
|
1327
|
-
if (err) reject(err);
|
|
1328
|
-
else resolve();
|
|
1329
|
-
});
|
|
1330
|
-
});
|
|
1331
|
-
}
|
|
1332
|
-
async all(sql, params = []) {
|
|
1333
|
-
return new Promise((resolve, reject) => {
|
|
1334
|
-
this.db.all(sql, params, (err, rows) => {
|
|
1335
|
-
if (err) reject(err);
|
|
1336
|
-
else resolve(rows);
|
|
1337
|
-
});
|
|
1338
|
-
});
|
|
1832
|
+
// src/oss/src/storage/DummyHistoryManager.ts
|
|
1833
|
+
var DummyHistoryManager = class {
|
|
1834
|
+
constructor() {
|
|
1339
1835
|
}
|
|
1340
1836
|
async addHistory(memoryId, previousValue, newValue, action, createdAt, updatedAt, isDeleted = 0) {
|
|
1341
|
-
|
|
1342
|
-
`INSERT INTO memory_history
|
|
1343
|
-
(memory_id, previous_value, new_value, action, created_at, updated_at, is_deleted)
|
|
1344
|
-
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
|
1345
|
-
[
|
|
1346
|
-
memoryId,
|
|
1347
|
-
previousValue,
|
|
1348
|
-
newValue,
|
|
1349
|
-
action,
|
|
1350
|
-
createdAt,
|
|
1351
|
-
updatedAt,
|
|
1352
|
-
isDeleted
|
|
1353
|
-
]
|
|
1354
|
-
);
|
|
1837
|
+
return;
|
|
1355
1838
|
}
|
|
1356
1839
|
async getHistory(memoryId) {
|
|
1357
|
-
return
|
|
1358
|
-
"SELECT * FROM memory_history WHERE memory_id = ? ORDER BY id DESC",
|
|
1359
|
-
[memoryId]
|
|
1360
|
-
);
|
|
1840
|
+
return [];
|
|
1361
1841
|
}
|
|
1362
1842
|
async reset() {
|
|
1363
|
-
|
|
1364
|
-
await this.init();
|
|
1843
|
+
return;
|
|
1365
1844
|
}
|
|
1366
1845
|
close() {
|
|
1367
|
-
|
|
1846
|
+
return;
|
|
1368
1847
|
}
|
|
1369
1848
|
};
|
|
1370
1849
|
|
|
1371
1850
|
// src/oss/src/config/defaults.ts
|
|
1372
1851
|
var DEFAULT_MEMORY_CONFIG = {
|
|
1852
|
+
disableHistory: false,
|
|
1373
1853
|
version: "v1.1",
|
|
1374
1854
|
embedder: {
|
|
1375
1855
|
provider: "openai",
|
|
@@ -1407,7 +1887,12 @@ var DEFAULT_MEMORY_CONFIG = {
|
|
|
1407
1887
|
}
|
|
1408
1888
|
}
|
|
1409
1889
|
},
|
|
1410
|
-
|
|
1890
|
+
historyStore: {
|
|
1891
|
+
provider: "sqlite",
|
|
1892
|
+
config: {
|
|
1893
|
+
historyDbPath: "memory.db"
|
|
1894
|
+
}
|
|
1895
|
+
}
|
|
1411
1896
|
};
|
|
1412
1897
|
|
|
1413
1898
|
// src/oss/src/config/manager.ts
|
|
@@ -1444,6 +1929,11 @@ var ConfigManager = class {
|
|
|
1444
1929
|
...DEFAULT_MEMORY_CONFIG.graphStore,
|
|
1445
1930
|
...userConfig.graphStore
|
|
1446
1931
|
},
|
|
1932
|
+
historyStore: {
|
|
1933
|
+
...DEFAULT_MEMORY_CONFIG.historyStore,
|
|
1934
|
+
...userConfig.historyStore
|
|
1935
|
+
},
|
|
1936
|
+
disableHistory: userConfig.disableHistory || DEFAULT_MEMORY_CONFIG.disableHistory,
|
|
1447
1937
|
enableGraph: userConfig.enableGraph || DEFAULT_MEMORY_CONFIG.enableGraph
|
|
1448
1938
|
};
|
|
1449
1939
|
return MemoryConfigSchema.parse(mergedConfig);
|
|
@@ -1659,14 +2149,6 @@ function getDeleteMessages(existingMemoriesString, data, userId) {
|
|
|
1659
2149
|
];
|
|
1660
2150
|
}
|
|
1661
2151
|
|
|
1662
|
-
// src/oss/src/utils/logger.ts
|
|
1663
|
-
var logger = {
|
|
1664
|
-
info: (message) => console.log(`[INFO] ${message}`),
|
|
1665
|
-
error: (message) => console.error(`[ERROR] ${message}`),
|
|
1666
|
-
debug: (message) => console.debug(`[DEBUG] ${message}`),
|
|
1667
|
-
warn: (message) => console.warn(`[WARN] ${message}`)
|
|
1668
|
-
};
|
|
1669
|
-
|
|
1670
2152
|
// src/oss/src/memory/graph_memory.ts
|
|
1671
2153
|
var MemoryGraph = class {
|
|
1672
2154
|
constructor(config) {
|
|
@@ -2230,7 +2712,20 @@ var Memory = class _Memory {
|
|
|
2230
2712
|
this.config.llm.provider,
|
|
2231
2713
|
this.config.llm.config
|
|
2232
2714
|
);
|
|
2233
|
-
|
|
2715
|
+
if (this.config.disableHistory) {
|
|
2716
|
+
this.db = new DummyHistoryManager();
|
|
2717
|
+
} else {
|
|
2718
|
+
const defaultConfig = {
|
|
2719
|
+
provider: "sqlite",
|
|
2720
|
+
config: {
|
|
2721
|
+
historyDbPath: this.config.historyDbPath || ":memory:"
|
|
2722
|
+
}
|
|
2723
|
+
};
|
|
2724
|
+
this.db = this.config.historyStore && !this.config.disableHistory ? HistoryManagerFactory.create(
|
|
2725
|
+
this.config.historyStore.provider,
|
|
2726
|
+
this.config.historyStore
|
|
2727
|
+
) : HistoryManagerFactory.create("sqlite", defaultConfig);
|
|
2728
|
+
}
|
|
2234
2729
|
this.collectionName = this.config.vectorStore.config.collectionName;
|
|
2235
2730
|
this.apiVersion = this.config.version || "v1.0";
|
|
2236
2731
|
this.enableGraph = this.config.enableGraph || false;
|
|
@@ -2533,7 +3028,7 @@ ${parsedMessages}`] : getFactRetrievalMessages(parsedMessages);
|
|
|
2533
3028
|
return { results };
|
|
2534
3029
|
}
|
|
2535
3030
|
async createMemory(data, existingEmbeddings, metadata) {
|
|
2536
|
-
const memoryId =
|
|
3031
|
+
const memoryId = uuidv43();
|
|
2537
3032
|
const embedding = existingEmbeddings[data] || await this.embedder.embed(data);
|
|
2538
3033
|
const memoryMetadata = {
|
|
2539
3034
|
...metadata,
|
|
@@ -2608,10 +3103,13 @@ export {
|
|
|
2608
3103
|
AnthropicLLM,
|
|
2609
3104
|
EmbedderFactory,
|
|
2610
3105
|
GroqLLM,
|
|
3106
|
+
HistoryManagerFactory,
|
|
2611
3107
|
LLMFactory,
|
|
2612
3108
|
Memory,
|
|
2613
3109
|
MemoryConfigSchema,
|
|
2614
3110
|
MemoryVectorStore,
|
|
3111
|
+
OllamaEmbedder,
|
|
3112
|
+
OllamaLLM,
|
|
2615
3113
|
OpenAIEmbedder,
|
|
2616
3114
|
OpenAILLM,
|
|
2617
3115
|
OpenAIStructuredLLM,
|