mem0ai 3.0.2 → 3.0.3

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.js CHANGED
@@ -893,9 +893,9 @@ var _MemoryVectorStore = class _MemoryVectorStore {
893
893
  if (row) {
894
894
  return row.user_id;
895
895
  }
896
- const randomUserId = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
897
- this.db.prepare(`INSERT INTO memory_migrations (user_id) VALUES (?)`).run(randomUserId);
898
- return randomUserId;
896
+ const randomUserId2 = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
897
+ this.db.prepare(`INSERT INTO memory_migrations (user_id) VALUES (?)`).run(randomUserId2);
898
+ return randomUserId2;
899
899
  }
900
900
  async setUserId(userId) {
901
901
  this.db.prepare(`DELETE FROM memory_migrations`).run();
@@ -1182,17 +1182,17 @@ var Qdrant = class {
1182
1182
  if (result.points.length > 0) {
1183
1183
  return (_a2 = result.points[0].payload) == null ? void 0 : _a2.user_id;
1184
1184
  }
1185
- const randomUserId = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
1185
+ const randomUserId2 = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
1186
1186
  await this.client.upsert("memory_migrations", {
1187
1187
  points: [
1188
1188
  {
1189
1189
  id: this.generateUUID(),
1190
1190
  vector: [0],
1191
- payload: { user_id: randomUserId }
1191
+ payload: { user_id: randomUserId2 }
1192
1192
  }
1193
1193
  ]
1194
1194
  });
1195
- return randomUserId;
1195
+ return randomUserId2;
1196
1196
  } catch (error) {
1197
1197
  console.error("Error getting user ID:", error);
1198
1198
  throw error;
@@ -1496,11 +1496,11 @@ var VectorizeDB = class {
1496
1496
  if (result.matches.length > 0) {
1497
1497
  return result.matches[0].metadata.userId;
1498
1498
  }
1499
- const randomUserId = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
1499
+ const randomUserId2 = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
1500
1500
  const data = {
1501
1501
  id: this.generateUUID(),
1502
1502
  values: [0],
1503
- metadata: { userId: randomUserId }
1503
+ metadata: { userId: randomUserId2 }
1504
1504
  };
1505
1505
  await fetch(
1506
1506
  `https://api.cloudflare.com/client/v4/accounts/${this.accountId}/vectorize/v2/indexes/memory_migrations/upsert`,
@@ -1514,7 +1514,7 @@ var VectorizeDB = class {
1514
1514
  // ndjson format
1515
1515
  }
1516
1516
  );
1517
- return randomUserId;
1517
+ return randomUserId2;
1518
1518
  } catch (error) {
1519
1519
  console.error("Error getting user ID:", error);
1520
1520
  throw new Error(
@@ -2129,9 +2129,9 @@ var RedisDB = class {
2129
2129
  if (userId) {
2130
2130
  return userId;
2131
2131
  }
2132
- const randomUserId = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
2133
- await this.client.set("memory_migrations:1", randomUserId);
2134
- return randomUserId;
2132
+ const randomUserId2 = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
2133
+ await this.client.set("memory_migrations:1", randomUserId2);
2134
+ return randomUserId2;
2135
2135
  } catch (error) {
2136
2136
  console.error("Error getting user ID:", error);
2137
2137
  throw error;
@@ -2507,18 +2507,18 @@ See the SQL migration instructions in the code comments.`
2507
2507
  try {
2508
2508
  const { data: tableExists } = await this.client.from("memory_migrations").select("user_id").limit(1);
2509
2509
  if (!tableExists || tableExists.length === 0) {
2510
- const randomUserId = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
2511
- const { error: insertError } = await this.client.from("memory_migrations").insert({ user_id: randomUserId });
2510
+ const randomUserId2 = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
2511
+ const { error: insertError } = await this.client.from("memory_migrations").insert({ user_id: randomUserId2 });
2512
2512
  if (insertError) throw insertError;
2513
- return randomUserId;
2513
+ return randomUserId2;
2514
2514
  }
2515
2515
  const { data, error } = await this.client.from("memory_migrations").select("user_id").limit(1);
2516
2516
  if (error) throw error;
2517
2517
  if (!data || data.length === 0) {
2518
- const randomUserId = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
2519
- const { error: insertError } = await this.client.from("memory_migrations").insert({ user_id: randomUserId });
2518
+ const randomUserId2 = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
2519
+ const { error: insertError } = await this.client.from("memory_migrations").insert({ user_id: randomUserId2 });
2520
2520
  if (insertError) throw insertError;
2521
- return randomUserId;
2521
+ return randomUserId2;
2522
2522
  }
2523
2523
  return data[0].user_id;
2524
2524
  } catch (error) {
@@ -4390,14 +4390,14 @@ var AzureAISearch = class {
4390
4390
  return userId;
4391
4391
  }
4392
4392
  }
4393
- const randomUserId = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
4393
+ const randomUserId2 = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
4394
4394
  await this.searchClient.uploadDocuments([
4395
4395
  {
4396
4396
  id: this.generateUUID(),
4397
- user_id: randomUserId
4397
+ user_id: randomUserId2
4398
4398
  }
4399
4399
  ]);
4400
- return randomUserId;
4400
+ return randomUserId2;
4401
4401
  } catch (error) {
4402
4402
  console.error("Error getting user ID:", error);
4403
4403
  throw error;
@@ -4445,13 +4445,33 @@ var AzureAISearch = class {
4445
4445
 
4446
4446
  // src/oss/src/vector_stores/pgvector.ts
4447
4447
  var import_pg = __toESM(require("pg"));
4448
- var { Client } = import_pg.default;
4448
+ var { Client, escapeIdentifier } = import_pg.default;
4449
+ var SAFE_IDENTIFIER_RE = /^[a-zA-Z_][a-zA-Z0-9_]{0,127}$/;
4450
+ function validateIdentifier(name, label = "identifier") {
4451
+ if (!SAFE_IDENTIFIER_RE.test(name)) {
4452
+ throw new Error(
4453
+ `Invalid ${label} '${name}': only letters, digits, and underscores are allowed, must start with a letter or underscore, and be at most 128 characters.`
4454
+ );
4455
+ }
4456
+ return name;
4457
+ }
4458
+ function escapeFilterKey(key) {
4459
+ if (!SAFE_IDENTIFIER_RE.test(key)) {
4460
+ throw new Error(
4461
+ `Invalid filter key '${key}': only letters, digits, and underscores are allowed.`
4462
+ );
4463
+ }
4464
+ return key;
4465
+ }
4449
4466
  var PGVector = class {
4450
4467
  constructor(config) {
4451
- this.collectionName = config.collectionName || "memories";
4468
+ this.collectionName = validateIdentifier(
4469
+ config.collectionName || "memories",
4470
+ "collectionName"
4471
+ );
4452
4472
  this.useDiskann = config.diskann || false;
4453
4473
  this.useHnsw = config.hnsw || false;
4454
- this.dbName = config.dbname || "vector_store";
4474
+ this.dbName = validateIdentifier(config.dbname || "vector_store", "dbname");
4455
4475
  this.config = config;
4456
4476
  this.client = new Client({
4457
4477
  database: "postgres",
@@ -4463,6 +4483,9 @@ var PGVector = class {
4463
4483
  });
4464
4484
  this.initialize().catch(console.error);
4465
4485
  }
4486
+ col() {
4487
+ return escapeIdentifier(this.collectionName);
4488
+ }
4466
4489
  async initialize() {
4467
4490
  if (!this._initPromise) {
4468
4491
  this._initPromise = this._doInitialize();
@@ -4509,13 +4532,14 @@ var PGVector = class {
4509
4532
  return result.rows.length > 0;
4510
4533
  }
4511
4534
  async createDatabase(dbName) {
4512
- await this.client.query(`CREATE DATABASE ${dbName}`);
4535
+ await this.client.query(`CREATE DATABASE ${escapeIdentifier(dbName)}`);
4513
4536
  }
4514
4537
  async createCol(embeddingModelDims) {
4538
+ const dims = Math.floor(embeddingModelDims);
4515
4539
  await this.client.query(`
4516
- CREATE TABLE IF NOT EXISTS ${this.collectionName} (
4540
+ CREATE TABLE IF NOT EXISTS ${this.col()} (
4517
4541
  id UUID PRIMARY KEY,
4518
- vector vector(${embeddingModelDims}),
4542
+ vector vector(${dims}),
4519
4543
  payload JSONB
4520
4544
  );
4521
4545
  `);
@@ -4526,8 +4550,8 @@ var PGVector = class {
4526
4550
  );
4527
4551
  if (result.rows.length > 0) {
4528
4552
  await this.client.query(`
4529
- CREATE INDEX IF NOT EXISTS ${this.collectionName}_diskann_idx
4530
- ON ${this.collectionName}
4553
+ CREATE INDEX IF NOT EXISTS ${escapeIdentifier(this.collectionName + "_diskann_idx")}
4554
+ ON ${this.col()}
4531
4555
  USING diskann (vector);
4532
4556
  `);
4533
4557
  }
@@ -4537,8 +4561,8 @@ var PGVector = class {
4537
4561
  } else if (this.useHnsw) {
4538
4562
  try {
4539
4563
  await this.client.query(`
4540
- CREATE INDEX IF NOT EXISTS ${this.collectionName}_hnsw_idx
4541
- ON ${this.collectionName}
4564
+ CREATE INDEX IF NOT EXISTS ${escapeIdentifier(this.collectionName + "_hnsw_idx")}
4565
+ ON ${this.col()}
4542
4566
  USING hnsw (vector vector_cosine_ops);
4543
4567
  `);
4544
4568
  } catch (error) {
@@ -4550,11 +4574,10 @@ var PGVector = class {
4550
4574
  const values = vectors.map((vector, i) => ({
4551
4575
  id: ids[i],
4552
4576
  vector: `[${vector.join(",")}]`,
4553
- // Format vector as string with square brackets
4554
4577
  payload: payloads[i]
4555
4578
  }));
4556
4579
  const query = `
4557
- INSERT INTO ${this.collectionName} (id, vector, payload)
4580
+ INSERT INTO ${this.col()} (id, vector, payload)
4558
4581
  VALUES ($1, $2::vector, $3::jsonb)
4559
4582
  `;
4560
4583
  await Promise.all(
@@ -4570,7 +4593,8 @@ var PGVector = class {
4570
4593
  let filterIndex = 3;
4571
4594
  if (filters) {
4572
4595
  for (const [key, value] of Object.entries(filters)) {
4573
- filterConditions.push(`payload->>'${key}' = $${filterIndex}`);
4596
+ const safeKey = escapeFilterKey(key);
4597
+ filterConditions.push(`payload->>'${safeKey}' = $${filterIndex}`);
4574
4598
  filterValues.push(value);
4575
4599
  filterIndex++;
4576
4600
  }
@@ -4578,7 +4602,7 @@ var PGVector = class {
4578
4602
  const filterClause = filterConditions.length > 0 ? "AND " + filterConditions.join(" AND ") : "";
4579
4603
  const searchQuery = `
4580
4604
  SELECT id, ts_rank_cd(to_tsvector('simple', payload->>'textLemmatized'), plainto_tsquery('simple', $1)) AS score, payload
4581
- FROM ${this.collectionName}
4605
+ FROM ${this.col()}
4582
4606
  WHERE to_tsvector('simple', payload->>'textLemmatized') @@ plainto_tsquery('simple', $1)
4583
4607
  ${filterClause}
4584
4608
  ORDER BY score DESC
@@ -4602,7 +4626,8 @@ var PGVector = class {
4602
4626
  let filterIndex = 3;
4603
4627
  if (filters) {
4604
4628
  for (const [key, value] of Object.entries(filters)) {
4605
- filterConditions.push(`payload->>'${key}' = $${filterIndex}`);
4629
+ const safeKey = escapeFilterKey(key);
4630
+ filterConditions.push(`payload->>'${safeKey}' = $${filterIndex}`);
4606
4631
  filterValues.push(value);
4607
4632
  filterIndex++;
4608
4633
  }
@@ -4610,7 +4635,7 @@ var PGVector = class {
4610
4635
  const filterClause = filterConditions.length > 0 ? "WHERE " + filterConditions.join(" AND ") : "";
4611
4636
  const searchQuery = `
4612
4637
  SELECT id, vector <=> $1::vector AS distance, payload
4613
- FROM ${this.collectionName}
4638
+ FROM ${this.col()}
4614
4639
  ${filterClause}
4615
4640
  ORDER BY distance
4616
4641
  LIMIT $2
@@ -4619,12 +4644,12 @@ var PGVector = class {
4619
4644
  return result.rows.map((row) => ({
4620
4645
  id: row.id,
4621
4646
  payload: row.payload,
4622
- score: row.distance
4647
+ score: Math.max(0, Math.min(1, 1 - Number(row.distance)))
4623
4648
  }));
4624
4649
  }
4625
4650
  async get(vectorId) {
4626
4651
  const result = await this.client.query(
4627
- `SELECT id, payload FROM ${this.collectionName} WHERE id = $1`,
4652
+ `SELECT id, payload FROM ${this.col()} WHERE id = $1`,
4628
4653
  [vectorId]
4629
4654
  );
4630
4655
  if (result.rows.length === 0) return null;
@@ -4637,7 +4662,7 @@ var PGVector = class {
4637
4662
  const vectorStr = `[${vector.join(",")}]`;
4638
4663
  await this.client.query(
4639
4664
  `
4640
- UPDATE ${this.collectionName}
4665
+ UPDATE ${this.col()}
4641
4666
  SET vector = $1::vector, payload = $2::jsonb
4642
4667
  WHERE id = $3
4643
4668
  `,
@@ -4645,13 +4670,12 @@ var PGVector = class {
4645
4670
  );
4646
4671
  }
4647
4672
  async delete(vectorId) {
4648
- await this.client.query(
4649
- `DELETE FROM ${this.collectionName} WHERE id = $1`,
4650
- [vectorId]
4651
- );
4673
+ await this.client.query(`DELETE FROM ${this.col()} WHERE id = $1`, [
4674
+ vectorId
4675
+ ]);
4652
4676
  }
4653
4677
  async deleteCol() {
4654
- await this.client.query(`DROP TABLE IF EXISTS ${this.collectionName}`);
4678
+ await this.client.query(`DROP TABLE IF EXISTS ${this.col()}`);
4655
4679
  }
4656
4680
  async listCols() {
4657
4681
  const result = await this.client.query(`
@@ -4667,7 +4691,8 @@ var PGVector = class {
4667
4691
  let paramIndex = 1;
4668
4692
  if (filters) {
4669
4693
  for (const [key, value] of Object.entries(filters)) {
4670
- filterConditions.push(`payload->>'${key}' = $${paramIndex}`);
4694
+ const safeKey = escapeFilterKey(key);
4695
+ filterConditions.push(`payload->>'${safeKey}' = $${paramIndex}`);
4671
4696
  filterValues.push(value);
4672
4697
  paramIndex++;
4673
4698
  }
@@ -4675,13 +4700,13 @@ var PGVector = class {
4675
4700
  const filterClause = filterConditions.length > 0 ? "WHERE " + filterConditions.join(" AND ") : "";
4676
4701
  const listQuery = `
4677
4702
  SELECT id, payload
4678
- FROM ${this.collectionName}
4703
+ FROM ${this.col()}
4679
4704
  ${filterClause}
4680
4705
  LIMIT $${paramIndex}
4681
4706
  `;
4682
4707
  const countQuery = `
4683
4708
  SELECT COUNT(*)
4684
- FROM ${this.collectionName}
4709
+ FROM ${this.col()}
4685
4710
  ${filterClause}
4686
4711
  `;
4687
4712
  filterValues.push(topK);
@@ -4706,12 +4731,12 @@ var PGVector = class {
4706
4731
  if (result.rows.length > 0) {
4707
4732
  return result.rows[0].user_id;
4708
4733
  }
4709
- const randomUserId = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
4734
+ const randomUserId2 = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
4710
4735
  await this.client.query(
4711
4736
  "INSERT INTO memory_migrations (user_id) VALUES ($1)",
4712
- [randomUserId]
4737
+ [randomUserId2]
4713
4738
  );
4714
- return randomUserId;
4739
+ return randomUserId2;
4715
4740
  }
4716
4741
  async setUserId(userId) {
4717
4742
  await this.client.query("DELETE FROM memory_migrations");
@@ -5012,7 +5037,7 @@ var parse_vision_messages = async (messages) => {
5012
5037
  };
5013
5038
 
5014
5039
  // src/oss/src/utils/telemetry.ts
5015
- var version = true ? "3.0.2" : "dev";
5040
+ var version = true ? "3.0.3" : "dev";
5016
5041
  var MEM0_TELEMETRY = true;
5017
5042
  var _a;
5018
5043
  try {
@@ -5914,6 +5939,69 @@ function scoreAndRank(semanticResults, bm25Scores, entityBoosts, threshold, topK
5914
5939
  return scored.slice(0, topK);
5915
5940
  }
5916
5941
 
5942
+ // src/client/config.ts
5943
+ async function getNodeFs() {
5944
+ var _a2, _b, _c, _d, _e;
5945
+ if (typeof process === "undefined" || !((_a2 = process.versions) == null ? void 0 : _a2.node)) return null;
5946
+ try {
5947
+ const [fs4, path3, os2, crypto] = await Promise.all([
5948
+ import("fs"),
5949
+ import("path"),
5950
+ import("os"),
5951
+ import("crypto")
5952
+ ]);
5953
+ const fsMod = (_b = fs4.default) != null ? _b : fs4;
5954
+ const pathMod = (_c = path3.default) != null ? _c : path3;
5955
+ const osMod = (_d = os2.default) != null ? _d : os2;
5956
+ const cryptoMod = (_e = crypto.default) != null ? _e : crypto;
5957
+ const dir = process.env.MEM0_DIR || pathMod.join(osMod.homedir(), ".mem0");
5958
+ return {
5959
+ fs: fsMod,
5960
+ path: pathMod,
5961
+ crypto: cryptoMod,
5962
+ configPath: pathMod.join(dir, "config.json")
5963
+ };
5964
+ } catch (e) {
5965
+ return null;
5966
+ }
5967
+ }
5968
+ function loadConfig(node) {
5969
+ try {
5970
+ if (!node.fs.existsSync(node.configPath)) return null;
5971
+ const parsed = JSON.parse(node.fs.readFileSync(node.configPath, "utf8"));
5972
+ return parsed && typeof parsed === "object" ? parsed : null;
5973
+ } catch (e) {
5974
+ return null;
5975
+ }
5976
+ }
5977
+ function writeConfig(node, config) {
5978
+ node.fs.mkdirSync(node.path.dirname(node.configPath), { recursive: true });
5979
+ node.fs.writeFileSync(node.configPath, JSON.stringify(config, null, 4));
5980
+ }
5981
+ function randomUserId(node) {
5982
+ if (typeof node.crypto.randomUUID === "function") {
5983
+ return node.crypto.randomUUID();
5984
+ }
5985
+ return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
5986
+ }
5987
+ async function getOrCreateMem0UserId() {
5988
+ var _a2;
5989
+ const node = await getNodeFs();
5990
+ if (!node) return null;
5991
+ try {
5992
+ const config = (_a2 = loadConfig(node)) != null ? _a2 : {};
5993
+ if (typeof config.user_id === "string" && config.user_id) {
5994
+ return config.user_id;
5995
+ }
5996
+ const userId = randomUserId(node);
5997
+ config.user_id = userId;
5998
+ writeConfig(node, config);
5999
+ return userId;
6000
+ } catch (e) {
6001
+ return null;
6002
+ }
6003
+ }
6004
+
5917
6005
  // src/oss/src/memory/index.ts
5918
6006
  var ENTITY_PARAMS = [
5919
6007
  "user_id",
@@ -6220,7 +6308,11 @@ var Memory = class _Memory {
6220
6308
  async _getTelemetryId() {
6221
6309
  try {
6222
6310
  if (!this.telemetryId || this.telemetryId === "anonymous" || this.telemetryId === "anonymous-supabase") {
6223
- this.telemetryId = await this.vectorStore.getUserId();
6311
+ this.telemetryId = await getOrCreateMem0UserId() || await this.vectorStore.getUserId();
6312
+ try {
6313
+ await this.vectorStore.setUserId(this.telemetryId);
6314
+ } catch (e) {
6315
+ }
6224
6316
  }
6225
6317
  return this.telemetryId;
6226
6318
  } catch (error) {