mem0ai 3.0.9 → 3.0.12

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.
@@ -339,7 +339,11 @@ var AnthropicLLM = class {
339
339
  if (!apiKey) {
340
340
  throw new Error("Anthropic API key is required");
341
341
  }
342
- this.client = new Anthropic({ apiKey });
342
+ const clientArgs = { apiKey };
343
+ if (config.baseURL) {
344
+ clientArgs.baseURL = config.baseURL;
345
+ }
346
+ this.client = new Anthropic(clientArgs);
343
347
  this.model = config.model || "claude-sonnet-4-6";
344
348
  this.maxTokens = (_a2 = config.maxTokens) != null ? _a2 : 2e3;
345
349
  this.temperature = (_b2 = config.temperature) != null ? _b2 : 0.1;
@@ -1832,13 +1836,15 @@ var RedisDB = class {
1832
1836
  }
1833
1837
  async insert(vectors, ids, payloads) {
1834
1838
  const data = vectors.map((vector, idx) => {
1839
+ var _a2, _b2;
1835
1840
  const payload = toSnakeCase(payloads[idx]);
1836
1841
  const id = ids[idx];
1842
+ const createdAt = payload.created_at ? new Date(payload.created_at).getTime() : 0;
1837
1843
  const entry = {
1838
1844
  memory_id: id,
1839
- hash: payload.hash,
1840
- memory: payload.data,
1841
- created_at: new Date(payload.created_at).getTime(),
1845
+ hash: (_a2 = payload.hash) != null ? _a2 : "",
1846
+ memory: (_b2 = payload.data) != null ? _b2 : "",
1847
+ created_at: createdAt,
1842
1848
  embedding: new Float32Array(vector).buffer
1843
1849
  };
1844
1850
  ["agent_id", "run_id", "user_id"].forEach((field) => {
@@ -2017,13 +2023,16 @@ var RedisDB = class {
2017
2023
  }
2018
2024
  }
2019
2025
  async update(vectorId, vector, payload) {
2026
+ var _a2, _b2;
2020
2027
  const snakePayload = toSnakeCase(payload);
2028
+ const createdAt = snakePayload.created_at ? new Date(snakePayload.created_at).getTime() : 0;
2029
+ const updatedAt = snakePayload.updated_at ? new Date(snakePayload.updated_at).getTime() : 0;
2021
2030
  const entry = {
2022
2031
  memory_id: vectorId,
2023
- hash: snakePayload.hash,
2024
- memory: snakePayload.data,
2025
- created_at: new Date(snakePayload.created_at).getTime(),
2026
- updated_at: new Date(snakePayload.updated_at).getTime(),
2032
+ hash: (_a2 = snakePayload.hash) != null ? _a2 : "",
2033
+ memory: (_b2 = snakePayload.data) != null ? _b2 : "",
2034
+ created_at: createdAt,
2035
+ updated_at: updatedAt,
2027
2036
  embedding: Buffer.from(new Float32Array(vector).buffer)
2028
2037
  };
2029
2038
  ["agent_id", "run_id", "user_id"].forEach((field) => {
@@ -2269,6 +2278,66 @@ var DeepSeekLLM = class extends OpenAILLM {
2269
2278
  }
2270
2279
  };
2271
2280
 
2281
+ // src/oss/src/llms/litellm.ts
2282
+ var LiteLLM = class extends OpenAILLM {
2283
+ constructor(config) {
2284
+ super({
2285
+ ...config,
2286
+ apiKey: config.apiKey || process.env.LITELLM_API_KEY || "sk-anything",
2287
+ baseURL: config.baseURL || process.env.LITELLM_API_BASE || "http://localhost:4000",
2288
+ model: config.model || "gpt-5-mini"
2289
+ });
2290
+ }
2291
+ async generateResponse(messages, responseFormat, tools) {
2292
+ try {
2293
+ return await super.generateResponse(messages, responseFormat, tools);
2294
+ } catch (err) {
2295
+ const message = err instanceof Error ? err.message : String(err);
2296
+ throw new Error(`LiteLLM failed: ${message}`);
2297
+ }
2298
+ }
2299
+ async generateChat(messages) {
2300
+ try {
2301
+ return await super.generateChat(messages);
2302
+ } catch (err) {
2303
+ const message = err instanceof Error ? err.message : String(err);
2304
+ throw new Error(`LiteLLM failed: ${message}`);
2305
+ }
2306
+ }
2307
+ };
2308
+
2309
+ // src/oss/src/llms/minimax.ts
2310
+ var MiniMaxLLM = class extends OpenAILLM {
2311
+ constructor(config) {
2312
+ const apiKey = config.apiKey || process.env.MINIMAX_API_KEY;
2313
+ if (!apiKey) {
2314
+ throw new Error("MiniMax API key is required");
2315
+ }
2316
+ super({
2317
+ ...config,
2318
+ apiKey,
2319
+ baseURL: config.baseURL || process.env.MINIMAX_API_BASE || "https://api.minimax.io/v1",
2320
+ model: config.model || "MiniMax-M2.7"
2321
+ });
2322
+ }
2323
+ async generateResponse(messages, responseFormat, tools) {
2324
+ try {
2325
+ return await super.generateResponse(messages, responseFormat, tools);
2326
+ } catch (err) {
2327
+ const message = err instanceof Error ? err.message : String(err);
2328
+ throw new Error(`MiniMax LLM failed: ${message}`);
2329
+ }
2330
+ }
2331
+ async generateChat(messages) {
2332
+ try {
2333
+ return await super.generateChat(messages);
2334
+ } catch (err) {
2335
+ const message = err instanceof Error ? err.message : String(err);
2336
+ throw new Error(`MiniMax LLM failed: ${message}`);
2337
+ }
2338
+ }
2339
+ };
2340
+
2272
2341
  // src/oss/src/vector_stores/supabase.ts
2273
2342
  import { createClient as createClient2 } from "@supabase/supabase-js";
2274
2343
  var SupabaseDB = class {
@@ -4550,24 +4619,59 @@ function buildFilterConditions(filters, startIndex) {
4550
4619
  }
4551
4620
  return { conditions, values, paramIndex };
4552
4621
  }
4622
+ function getConnectionString(config) {
4623
+ var _a2;
4624
+ return ((_a2 = config.connectionString) == null ? void 0 : _a2.trim()) || void 0;
4625
+ }
4626
+ function validateConnectionConfig(config) {
4627
+ if (getConnectionString(config)) {
4628
+ return;
4629
+ }
4630
+ const missingFields = ["user", "password", "host", "port"].filter((field) => {
4631
+ const v = config[field];
4632
+ return v === void 0 || v === null || v === "";
4633
+ });
4634
+ if (missingFields.length > 0) {
4635
+ throw new Error(
4636
+ `PGVector requires either connectionString or ${missingFields.join(", ")}`
4637
+ );
4638
+ }
4639
+ }
4640
+ function buildClientConfig(config, database) {
4641
+ const connectionString = getConnectionString(config);
4642
+ if (connectionString) {
4643
+ return {
4644
+ connectionString,
4645
+ ...config.ssl !== void 0 ? { ssl: config.ssl } : {}
4646
+ };
4647
+ }
4648
+ return {
4649
+ database,
4650
+ user: config.user,
4651
+ password: config.password,
4652
+ host: config.host,
4653
+ port: config.port,
4654
+ ...config.ssl !== void 0 ? { ssl: config.ssl } : {}
4655
+ };
4656
+ }
4553
4657
  var PGVector = class {
4554
4658
  constructor(config) {
4659
+ validateConnectionConfig(config);
4555
4660
  this.collectionName = validateIdentifier(
4556
4661
  config.collectionName || "memories",
4557
4662
  "collectionName"
4558
4663
  );
4559
4664
  this.useDiskann = config.diskann || false;
4560
4665
  this.useHnsw = config.hnsw || false;
4561
- this.dbName = validateIdentifier(config.dbname || "vector_store", "dbname");
4666
+ this.useDirectConnection = !!getConnectionString(config);
4667
+ this.dbName = this.useDirectConnection ? "" : validateIdentifier(config.dbname || "vector_store", "dbname");
4562
4668
  this.config = config;
4563
- this.client = new Client({
4564
- database: "postgres",
4565
- // Initially connect to default postgres database
4566
- user: config.user,
4567
- password: config.password,
4568
- host: config.host,
4569
- port: config.port
4570
- });
4669
+ this.client = new Client(
4670
+ buildClientConfig(
4671
+ config,
4672
+ this.useDirectConnection ? void 0 : "postgres"
4673
+ )
4674
+ );
4571
4675
  this.initialize().catch(console.error);
4572
4676
  }
4573
4677
  col() {
@@ -4582,19 +4686,15 @@ var PGVector = class {
4582
4686
  async _doInitialize() {
4583
4687
  try {
4584
4688
  await this.client.connect();
4585
- const dbExists = await this.checkDatabaseExists(this.dbName);
4586
- if (!dbExists) {
4587
- await this.createDatabase(this.dbName);
4588
- }
4589
- await this.client.end();
4590
- this.client = new Client({
4591
- database: this.dbName,
4592
- user: this.config.user,
4593
- password: this.config.password,
4594
- host: this.config.host,
4595
- port: this.config.port
4596
- });
4597
- await this.client.connect();
4689
+ if (!this.useDirectConnection) {
4690
+ const dbExists = await this.checkDatabaseExists(this.dbName);
4691
+ if (!dbExists) {
4692
+ await this.createDatabase(this.dbName);
4693
+ }
4694
+ await this.client.end();
4695
+ this.client = new Client(buildClientConfig(this.config, this.dbName));
4696
+ await this.client.connect();
4697
+ }
4598
4698
  await this.client.query("CREATE EXTENSION IF NOT EXISTS vector");
4599
4699
  await this.client.query(`
4600
4700
  CREATE TABLE IF NOT EXISTS memory_migrations (
@@ -4865,6 +4965,10 @@ var LLMFactory = class {
4865
4965
  return new LangchainLLM(config);
4866
4966
  case "deepseek":
4867
4967
  return new DeepSeekLLM(config);
4968
+ case "litellm":
4969
+ return new LiteLLM(config);
4970
+ case "minimax":
4971
+ return new MiniMaxLLM(config);
4868
4972
  default:
4869
4973
  throw new Error(`Unsupported LLM provider: ${provider}`);
4870
4974
  }
@@ -5094,6 +5198,7 @@ var get_image_description = async (image_url) => {
5094
5198
  return response;
5095
5199
  };
5096
5200
  var parse_vision_messages = async (messages) => {
5201
+ var _a2;
5097
5202
  const parsed_messages = [];
5098
5203
  for (const message of messages) {
5099
5204
  let new_message = {
@@ -5102,9 +5207,11 @@ var parse_vision_messages = async (messages) => {
5102
5207
  };
5103
5208
  if (message.role !== "system") {
5104
5209
  if (typeof message.content === "object" && message.content.type === "image_url") {
5105
- const description = await get_image_description(
5106
- message.content.image_url.url
5107
- );
5210
+ const imageUrl = (_a2 = message.content.image_url) == null ? void 0 : _a2.url;
5211
+ if (!imageUrl) {
5212
+ throw new Error("image_url content part is missing image_url.url");
5213
+ }
5214
+ const description = await get_image_description(imageUrl);
5108
5215
  new_message.content = typeof description === "string" ? description : JSON.stringify(description);
5109
5216
  parsed_messages.push(new_message);
5110
5217
  } else parsed_messages.push(message);
@@ -5114,7 +5221,7 @@ var parse_vision_messages = async (messages) => {
5114
5221
  };
5115
5222
 
5116
5223
  // src/oss/src/utils/telemetry.ts
5117
- var version = true ? "3.0.9" : "dev";
5224
+ var version = true ? "3.0.12" : "dev";
5118
5225
  var MEM0_TELEMETRY = true;
5119
5226
  var _a, _b;
5120
5227
  try {
@@ -6647,7 +6754,24 @@ var NON_SPECIFIC_ADJ = /* @__PURE__ */ new Set([
6647
6754
  "collaborative",
6648
6755
  "final",
6649
6756
  "initial",
6650
- "side"
6757
+ "side",
6758
+ "top"
6759
+ ]);
6760
+ var TOPIC_PREFIX_WORDS = /* @__PURE__ */ new Set([
6761
+ "a",
6762
+ "an",
6763
+ "the",
6764
+ "my",
6765
+ "your",
6766
+ "our",
6767
+ "their",
6768
+ "his",
6769
+ "her",
6770
+ "its",
6771
+ "this",
6772
+ "that",
6773
+ "these",
6774
+ "those"
6651
6775
  ]);
6652
6776
  var GENERIC_ENDINGS = /* @__PURE__ */ new Set([
6653
6777
  "work",
@@ -6714,6 +6838,23 @@ var GENERIC_CAPS = /* @__PURE__ */ new Set([
6714
6838
  "advantages",
6715
6839
  "disadvantages"
6716
6840
  ]);
6841
+ var GENERIC_SINGLE_ENTITY_TERMS = /* @__PURE__ */ new Set([
6842
+ "user",
6843
+ "assistant",
6844
+ "agent",
6845
+ "customer",
6846
+ "client",
6847
+ "person",
6848
+ "people",
6849
+ "human",
6850
+ "memory",
6851
+ "message",
6852
+ "conversation",
6853
+ "chat",
6854
+ "session",
6855
+ "system",
6856
+ "top"
6857
+ ]);
6717
6858
  var FORMATTING_MARKERS = /* @__PURE__ */ new Set([
6718
6859
  "*",
6719
6860
  "-",
@@ -6760,22 +6901,64 @@ function stripGenericEnding(words) {
6760
6901
  }
6761
6902
  return words;
6762
6903
  }
6763
- function isSentenceStart(tokens, idx, rawText) {
6764
- if (idx === 0) {
6765
- return true;
6904
+ function stripTopicPrefix(words) {
6905
+ let start = 0;
6906
+ while (start < words.length && TOPIC_PREFIX_WORDS.has(words[start].toLowerCase())) {
6907
+ start++;
6766
6908
  }
6767
- const prev = tokens[idx - 1];
6768
- if (/[.!?:]$/.test(prev)) {
6769
- return true;
6770
- }
6771
- if (FORMATTING_MARKERS.has(prev)) {
6772
- return true;
6773
- }
6774
- const tokenStart = rawText.indexOf(tokens[idx]);
6775
- if (tokenStart > 0 && rawText.charAt(tokenStart - 1) === "\n") {
6909
+ return words.slice(start);
6910
+ }
6911
+ function cleanToken(token) {
6912
+ return token.replace(/^[^\w.]+|[^\w.]+$/g, "");
6913
+ }
6914
+ function tokenize(text) {
6915
+ var _a2;
6916
+ return (_a2 = text.match(
6917
+ /[A-Za-z_][\w-]*(?:\.[A-Za-z_][\w-]*)*|\d[\d,]*(?:\.\d+)?|[,:;.!?&]/g
6918
+ )) != null ? _a2 : [];
6919
+ }
6920
+ function isCapitalized(token) {
6921
+ return /^[A-Z]/.test(token) && /[A-Za-z]/.test(token);
6922
+ }
6923
+ function hasInternalCapOrDigit(token) {
6924
+ return /\d/.test(token) || /[A-Z]/.test(token.slice(1)) || /^[A-Z]{2,}$/.test(token);
6925
+ }
6926
+ function isBadSingleNameToken(token) {
6927
+ const lower = token.toLowerCase();
6928
+ return GENERIC_SINGLE_ENTITY_TERMS.has(lower) || GENERIC_CAPS.has(lower);
6929
+ }
6930
+ function looksLikeMetricCount(token) {
6931
+ return /^\d[\d,]*(?:\.\d+)?$/.test(token);
6932
+ }
6933
+ function isMetricListContext(tokens, idx) {
6934
+ const prev = idx > 0 ? tokens[idx - 1] : "";
6935
+ const next = idx + 1 < tokens.length ? tokens[idx + 1] : "";
6936
+ return [":", ",", ";"].includes(prev) || [",", ";"].includes(next);
6937
+ }
6938
+ function isSentenceStart(tokens, idx) {
6939
+ if (idx === 0) return true;
6940
+ return [".", "!", "?", ":"].includes(tokens[idx - 1]) || FORMATTING_MARKERS.has(tokens[idx - 1]);
6941
+ }
6942
+ function isListItemNameToken(tokens, idx) {
6943
+ const token = cleanToken(tokens[idx]);
6944
+ if (!isCapitalized(token) || isBadSingleNameToken(token)) return false;
6945
+ const next = idx + 1 < tokens.length ? cleanToken(tokens[idx + 1]) : "";
6946
+ if (!looksLikeMetricCount(next)) return false;
6947
+ return isMetricListContext(tokens, idx) || isMetricListContext(tokens, idx + 1);
6948
+ }
6949
+ function isNameToken(tokens, idx) {
6950
+ const token = cleanToken(tokens[idx]);
6951
+ if (!token || !isCapitalized(token) || isBadSingleNameToken(token))
6952
+ return false;
6953
+ if (hasInternalCapOrDigit(token) || isListItemNameToken(tokens, idx))
6776
6954
  return true;
6777
- }
6778
- return false;
6955
+ return !isSentenceStart(tokens, idx);
6956
+ }
6957
+ function cleanEntityText(text) {
6958
+ return text.replace(/^\*+\s*|\s*\*+$/g, "").replace(/\s*:+$/g, "").replace(/^\d+\s*\.\s*/, "").replace(/\s+\d[\d,]*(?:\.\d+)?$/g, "").replace(/[.,;!?]+$/, "").trim().replace(/\s+/g, " ");
6959
+ }
6960
+ function isCoordinatedNameTopic(text) {
6961
+ return /\b[A-Z][\w-]+\s+and\s+[A-Z][\w-]+\b/.test(text);
6779
6962
  }
6780
6963
  function extractQuoted(text) {
6781
6964
  const entities = [];
@@ -6796,62 +6979,57 @@ function extractQuoted(text) {
6796
6979
  }
6797
6980
  return entities;
6798
6981
  }
6982
+ function extractIdentifiers(text) {
6983
+ const entities = [];
6984
+ const identifierRe = /\b[A-Za-z_][\w-]*(?:\.[A-Za-z_][\w-]*)+\b/g;
6985
+ let match;
6986
+ while ((match = identifierRe.exec(text)) !== null) {
6987
+ entities.push({ type: "IDENTIFIER", text: match[0] });
6988
+ }
6989
+ return entities;
6990
+ }
6799
6991
  function extractProper(text) {
6800
6992
  const entities = [];
6801
- const tokens = text.split(/\s+/).filter(Boolean);
6802
- const functionWords = /* @__PURE__ */ new Set([
6803
- "'s",
6804
- "of",
6805
- "the",
6806
- "in",
6807
- "and",
6808
- "for",
6809
- "at",
6810
- "is"
6811
- ]);
6993
+ const tokens = tokenize(text);
6994
+ const innerConnectors = /* @__PURE__ */ new Set(["of", "the", "in", "for", "at"]);
6812
6995
  let i = 0;
6813
6996
  while (i < tokens.length) {
6814
- const tok = tokens[i];
6815
- if (FORMATTING_MARKERS.has(tok)) {
6997
+ const token = cleanToken(tokens[i]);
6998
+ const next = i + 1 < tokens.length ? tokens[i + 1] : "";
6999
+ const afterNext = i + 2 < tokens.length ? cleanToken(tokens[i + 2]) : "";
7000
+ if (token && next === "&" && afterNext && isCapitalized(token) && isCapitalized(afterNext) && !isBadSingleNameToken(token) && !isBadSingleNameToken(afterNext)) {
7001
+ entities.push({
7002
+ type: "PROPER",
7003
+ text: cleanEntityText(`${token} & ${afterNext}`)
7004
+ });
7005
+ i += 3;
7006
+ continue;
7007
+ }
7008
+ if (!isNameToken(tokens, i)) {
6816
7009
  i++;
6817
7010
  continue;
6818
7011
  }
6819
- const isLabel = i + 1 < tokens.length && tokens[i + 1] === ":";
6820
- const isCap = tok.length > 0 && tok.charAt(0) === tok.charAt(0).toUpperCase() && /[A-Z]/.test(tok.charAt(0));
6821
- if (isCap && !isLabel) {
6822
- const seq = [
6823
- { token: tok, idx: i }
6824
- ];
6825
- let j = i + 1;
6826
- while (j < tokens.length) {
6827
- const t = tokens[j];
6828
- const tIsCap = t.length > 0 && t.charAt(0) === t.charAt(0).toUpperCase() && /[A-Z]/.test(t.charAt(0));
6829
- if (tIsCap || functionWords.has(t.toLowerCase())) {
6830
- seq.push({ token: t, idx: j });
6831
- j++;
6832
- } else {
6833
- break;
6834
- }
6835
- }
6836
- while (seq.length > 0 && functionWords.has(seq[seq.length - 1].token.toLowerCase())) {
6837
- seq.pop();
7012
+ const span = [cleanToken(tokens[i])];
7013
+ let j = i + 1;
7014
+ while (j < tokens.length) {
7015
+ const current = cleanToken(tokens[j]);
7016
+ if (isNameToken(tokens, j)) {
7017
+ span.push(current);
7018
+ j++;
7019
+ continue;
6838
7020
  }
6839
- if (seq.length > 0) {
6840
- const hasMidCap = seq.some(({ token, idx: tokenIdx }) => {
6841
- const isCapWord = /[A-Z]/.test(token.charAt(0)) && !functionWords.has(token.toLowerCase());
6842
- return isCapWord && !isSentenceStart(tokens, tokenIdx, text);
6843
- });
6844
- if (hasMidCap) {
6845
- const phrase = seq.map((s) => s.token).join(" ");
6846
- if (phrase.length > 2) {
6847
- entities.push({ type: "PROPER", text: phrase });
6848
- }
6849
- }
7021
+ if (innerConnectors.has(current.toLowerCase()) && j + 1 < tokens.length && isNameToken(tokens, j + 1)) {
7022
+ span.push(current, cleanToken(tokens[j + 1]));
7023
+ j += 2;
7024
+ continue;
6850
7025
  }
6851
- i = j;
6852
- } else {
6853
- i++;
7026
+ break;
6854
7027
  }
7028
+ const phrase = cleanEntityText(span.join(" "));
7029
+ if (phrase.length > 2) {
7030
+ entities.push({ type: "PROPER", text: phrase });
7031
+ }
7032
+ i = Math.max(j, i + 1);
6855
7033
  }
6856
7034
  return entities;
6857
7035
  }
@@ -6883,11 +7061,11 @@ function extractCompoundsWithNlp(text) {
6883
7061
  const filtered = words.filter(
6884
7062
  (w) => !NON_SPECIFIC_ADJ.has(w.toLowerCase())
6885
7063
  );
6886
- const cleaned = stripGenericEnding(filtered);
7064
+ const cleaned = stripGenericEnding(stripTopicPrefix(filtered));
6887
7065
  if (cleaned.length >= 2) {
6888
- const phrase = cleaned.join(" ");
7066
+ const phrase = cleanEntityText(cleaned.join(" "));
6889
7067
  if (phrase.length > 3) {
6890
- entities.push({ type: "COMPOUND", text: phrase });
7068
+ entities.push({ type: "TOPIC", text: phrase });
6891
7069
  }
6892
7070
  }
6893
7071
  }
@@ -6895,7 +7073,7 @@ function extractCompoundsWithNlp(text) {
6895
7073
  }
6896
7074
  function extractCompoundsRegex(text) {
6897
7075
  const entities = [];
6898
- const compoundRe = /\b([A-Z][a-z]+(?:\s+(?:of|and|the|for|in)\s+)?[A-Z][a-z]+(?:\s+[A-Z][a-z]+)*)\b/g;
7076
+ const compoundRe = /\b([A-Z][a-z]+(?:\s+(?:of|the|for|in)\s+)?[A-Z][a-z]+(?:\s+[A-Z][a-z]+)*)\b/g;
6899
7077
  let match;
6900
7078
  while ((match = compoundRe.exec(text)) !== null) {
6901
7079
  const phrase = match[1].trim();
@@ -6906,9 +7084,12 @@ function extractCompoundsRegex(text) {
6906
7084
  const filtered = words.filter(
6907
7085
  (w) => !NON_SPECIFIC_ADJ.has(w.toLowerCase())
6908
7086
  );
6909
- const cleaned = stripGenericEnding(filtered);
7087
+ const cleaned = stripGenericEnding(stripTopicPrefix(filtered));
6910
7088
  if (cleaned.length >= 2) {
6911
- entities.push({ type: "COMPOUND", text: cleaned.join(" ") });
7089
+ entities.push({
7090
+ type: "TOPIC",
7091
+ text: cleanEntityText(cleaned.join(" "))
7092
+ });
6912
7093
  }
6913
7094
  }
6914
7095
  }
@@ -6930,9 +7111,12 @@ function extractCompoundsRegex(text) {
6930
7111
  const filtered = words.filter(
6931
7112
  (w) => !NON_SPECIFIC_ADJ.has(w.toLowerCase())
6932
7113
  );
6933
- const cleaned = stripGenericEnding(filtered);
7114
+ const cleaned = stripGenericEnding(stripTopicPrefix(filtered));
6934
7115
  if (cleaned.length >= 2) {
6935
- entities.push({ type: "COMPOUND", text: cleaned.join(" ") });
7116
+ entities.push({
7117
+ type: "TOPIC",
7118
+ text: cleanEntityText(cleaned.join(" "))
7119
+ });
6936
7120
  }
6937
7121
  }
6938
7122
  }
@@ -6945,6 +7129,7 @@ function extractEntities(text) {
6945
7129
  const raw = [];
6946
7130
  raw.push(...extractQuoted(text));
6947
7131
  raw.push(...extractProper(text));
7132
+ raw.push(...extractIdentifiers(text));
6948
7133
  if (nlp) {
6949
7134
  raw.push(...extractCompoundsWithNlp(text));
6950
7135
  } else {
@@ -6962,13 +7147,13 @@ function extractEntities(text) {
6962
7147
  const cleaned = [];
6963
7148
  for (const entity of deduped) {
6964
7149
  let txt = entity.text.trim();
6965
- txt = txt.replace(/^\*+\s*|\s*\*+$/g, "");
6966
- txt = txt.replace(/\s*:+$/, "");
6967
- txt = txt.replace(/^\d+\s*\.\s*/, "");
6968
- txt = txt.replace(/[.,;!?]+$/, "").trim();
7150
+ txt = cleanEntityText(txt);
6969
7151
  if (!txt || txt.length <= 2 || hasArtifacts(txt)) {
6970
7152
  continue;
6971
7153
  }
7154
+ if (entity.type === "TOPIC" && (/^\d/.test(txt) || isCoordinatedNameTopic(txt))) {
7155
+ continue;
7156
+ }
6972
7157
  if (entity.type === "PROPER" && !txt.includes(" ") && GENERIC_CAPS.has(txt.toLowerCase())) {
6973
7158
  continue;
6974
7159
  }
@@ -6976,9 +7161,9 @@ function extractEntities(text) {
6976
7161
  }
6977
7162
  const typePriority = {
6978
7163
  PROPER: 0,
6979
- COMPOUND: 1,
7164
+ IDENTIFIER: 1,
6980
7165
  QUOTED: 2,
6981
- NOUN: 3
7166
+ TOPIC: 3
6982
7167
  };
6983
7168
  const best = /* @__PURE__ */ new Map();
6984
7169
  for (const entity of cleaned) {
@@ -6989,10 +7174,14 @@ function extractEntities(text) {
6989
7174
  }
6990
7175
  }
6991
7176
  const bestEntities = Array.from(best.values());
6992
- const allLower = bestEntities.map((e) => e.text.toLowerCase());
6993
7177
  return bestEntities.filter(
6994
- (entity) => !allLower.some(
6995
- (other) => entity.text.toLowerCase() !== other && other.includes(entity.text.toLowerCase())
7178
+ (entity) => !bestEntities.some(
7179
+ (other) => {
7180
+ var _a3, _b3;
7181
+ return entity.text.toLowerCase() !== other.text.toLowerCase() && ((_a3 = typePriority[entity.type]) != null ? _a3 : 99) >= ((_b3 = typePriority[other.type]) != null ? _b3 : 99) && new RegExp(
7182
+ `(^|\\s)${entity.text.toLowerCase().replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(\\s|$)`
7183
+ ).test(other.text.toLowerCase());
7184
+ }
6996
7185
  )
6997
7186
  );
6998
7187
  }
@@ -7284,6 +7473,32 @@ var Memory = class _Memory {
7284
7473
  if (payload.run_id) filters.run_id = payload.run_id;
7285
7474
  return filters;
7286
7475
  }
7476
+ _normalizeEntityText(value) {
7477
+ return value.trim().toLowerCase().replace(/\s+/g, " ");
7478
+ }
7479
+ async _existingEntitiesByText(entityStore, filters) {
7480
+ var _a2;
7481
+ const rowsByText = /* @__PURE__ */ new Map();
7482
+ let rows = [];
7483
+ try {
7484
+ const listed = await entityStore.list(filters, 1e4);
7485
+ rows = Array.isArray(listed) && Array.isArray(listed[0]) ? listed[0] : listed;
7486
+ } catch (e) {
7487
+ console.debug(
7488
+ `Exact entity lookup failed, falling back to semantic dedup: ${e}`
7489
+ );
7490
+ return rowsByText;
7491
+ }
7492
+ for (const row of rows) {
7493
+ const text = (_a2 = row.payload) == null ? void 0 : _a2.data;
7494
+ if (typeof text !== "string") continue;
7495
+ const key = this._normalizeEntityText(text);
7496
+ if (key && !rowsByText.has(key)) {
7497
+ rowsByText.set(key, row);
7498
+ }
7499
+ }
7500
+ return rowsByText;
7501
+ }
7287
7502
  /**
7288
7503
  * Remove `memoryId` from every entity record scoped to `filters`.
7289
7504
  * If an entity's `linkedMemoryIds` becomes empty after removal, the
@@ -7361,6 +7576,10 @@ var Memory = class _Memory {
7361
7576
  const entities = extractEntities(text);
7362
7577
  if (entities.length === 0) return;
7363
7578
  const entityStore = await this.getEntityStore();
7579
+ const exactMatches = await this._existingEntitiesByText(
7580
+ entityStore,
7581
+ filters
7582
+ );
7364
7583
  for (const entity of entities) {
7365
7584
  try {
7366
7585
  let entityVec;
@@ -7371,12 +7590,18 @@ var Memory = class _Memory {
7371
7590
  continue;
7372
7591
  }
7373
7592
  let matches = [];
7374
- try {
7375
- matches = await entityStore.search(entityVec, 1, filters);
7376
- } catch (e) {
7593
+ const exactMatch = exactMatches.get(
7594
+ this._normalizeEntityText(entity.text)
7595
+ );
7596
+ if (!exactMatch) {
7597
+ try {
7598
+ matches = await entityStore.search(entityVec, 1, filters);
7599
+ } catch (e) {
7600
+ }
7377
7601
  }
7378
- if (matches.length > 0 && ((_a2 = matches[0].score) != null ? _a2 : 0) >= 0.95) {
7379
- const match = matches[0];
7602
+ const semanticMatch = matches.length > 0 && ((_a2 = matches[0].score) != null ? _a2 : 0) >= 0.95 ? matches[0] : void 0;
7603
+ const match = exactMatch != null ? exactMatch : semanticMatch;
7604
+ if (match) {
7380
7605
  const payload = match.payload || {};
7381
7606
  const linked = new Set(
7382
7607
  Array.isArray(payload.linkedMemoryIds) ? payload.linkedMemoryIds : []
@@ -7538,6 +7763,25 @@ var Memory = class _Memory {
7538
7763
  "messages is required and cannot be undefined or null. Provide a string or array of messages."
7539
7764
  );
7540
7765
  }
7766
+ if (Array.isArray(messages)) {
7767
+ if (messages.length === 0) {
7768
+ throw new Error(
7769
+ "messages array cannot be empty. Provide at least one message with non-empty content."
7770
+ );
7771
+ }
7772
+ const allBlank = messages.every(
7773
+ (m) => typeof m.content === "string" && m.content.trim() === ""
7774
+ );
7775
+ if (allBlank) {
7776
+ throw new Error(
7777
+ "messages array cannot contain only blank content. Provide at least one message with non-empty content."
7778
+ );
7779
+ }
7780
+ } else if (messages.trim() === "") {
7781
+ throw new Error(
7782
+ "messages string cannot be empty. Provide non-empty content."
7783
+ );
7784
+ }
7541
7785
  const temporalUsageNotice = detectTemporalUsageFromMetadata(
7542
7786
  config == null ? void 0 : config.metadata
7543
7787
  );
@@ -7597,7 +7841,7 @@ var Memory = class _Memory {
7597
7841
  if (!infer) {
7598
7842
  const returnedMemories = [];
7599
7843
  for (const message of messages) {
7600
- if (message.content === "system") {
7844
+ if (message.role === "system") {
7601
7845
  continue;
7602
7846
  }
7603
7847
  const memoryId = await this.createMemory(
@@ -7621,7 +7865,7 @@ var Memory = class _Memory {
7621
7865
  } catch (e) {
7622
7866
  }
7623
7867
  }
7624
- const parsedMessages = messages.map((m) => m.content).join("\n");
7868
+ const parsedMessages = messages.map((m) => `${m.role}: ${m.content}`).join("\n");
7625
7869
  const queryEmbedding = await this.embedder.embed(parsedMessages);
7626
7870
  const existingResults = await this.vectorStore.search(
7627
7871
  queryEmbedding,
@@ -7874,6 +8118,10 @@ var Memory = class _Memory {
7874
8118
  }
7875
8119
  if (valid.length > 0) {
7876
8120
  const entityStore = await this.getEntityStore();
8121
+ const exactMatches = await this._existingEntitiesByText(
8122
+ entityStore,
8123
+ filters
8124
+ );
7877
8125
  const toInsertVectors = [];
7878
8126
  const toInsertIds = [];
7879
8127
  const toInsertPayloads = [];
@@ -7881,12 +8129,16 @@ var Memory = class _Memory {
7881
8129
  const { entityType, entityText, memoryIds } = globalEntities[key];
7882
8130
  const entityVec = entityEmbeddings[j];
7883
8131
  let matches = [];
7884
- try {
7885
- matches = await entityStore.search(entityVec, 1, filters);
7886
- } catch (e) {
8132
+ const exactMatch = exactMatches.get(key);
8133
+ if (!exactMatch) {
8134
+ try {
8135
+ matches = await entityStore.search(entityVec, 1, filters);
8136
+ } catch (e) {
8137
+ }
7887
8138
  }
7888
- if (matches.length > 0 && ((_f = matches[0].score) != null ? _f : 0) >= 0.95) {
7889
- const match = matches[0];
8139
+ const semanticMatch = matches.length > 0 && ((_f = matches[0].score) != null ? _f : 0) >= 0.95 ? matches[0] : void 0;
8140
+ const match = exactMatch != null ? exactMatch : semanticMatch;
8141
+ if (match) {
7890
8142
  const payload = match.payload || {};
7891
8143
  const linked = new Set((_g = payload.linkedMemoryIds) != null ? _g : []);
7892
8144
  for (const mid of memoryIds) linked.add(mid);
@@ -7980,7 +8232,13 @@ var Memory = class _Memory {
7980
8232
  memoryItem.metadata[key] = value;
7981
8233
  }
7982
8234
  }
7983
- const result = { ...memoryItem, ...filters };
8235
+ const result = {
8236
+ ...memoryItem,
8237
+ ...filters,
8238
+ ...memory.payload.attributedTo && {
8239
+ attributedTo: memory.payload.attributedTo
8240
+ }
8241
+ };
7984
8242
  await this._displayFirstRunNotice("get");
7985
8243
  return result;
7986
8244
  }
@@ -8178,6 +8436,7 @@ var Memory = class _Memory {
8178
8436
  ...payload.user_id && { user_id: payload.user_id },
8179
8437
  ...payload.agent_id && { agent_id: payload.agent_id },
8180
8438
  ...payload.run_id && { run_id: payload.run_id },
8439
+ ...payload.attributedTo && { attributedTo: payload.attributedTo },
8181
8440
  ...scored.scoreDetails && { score_details: scored.scoreDetails }
8182
8441
  };
8183
8442
  });
@@ -8251,7 +8510,9 @@ var Memory = class _Memory {
8251
8510
  has_agent_id: !!config.agentId,
8252
8511
  has_run_id: !!config.runId
8253
8512
  });
8254
- const { userId, agentId, runId } = config;
8513
+ const userId = validateAndTrimEntityId(config.userId, "userId");
8514
+ const agentId = validateAndTrimEntityId(config.agentId, "agentId");
8515
+ const runId = validateAndTrimEntityId(config.runId, "runId");
8255
8516
  const filters = {};
8256
8517
  if (userId) filters.user_id = userId;
8257
8518
  if (agentId) filters.agent_id = agentId;
@@ -8371,7 +8632,10 @@ var Memory = class _Memory {
8371
8632
  metadata: Object.entries(mem.payload).filter(([key]) => !excludedKeys.has(key)).reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}),
8372
8633
  ...mem.payload.user_id && { user_id: mem.payload.user_id },
8373
8634
  ...mem.payload.agent_id && { agent_id: mem.payload.agent_id },
8374
- ...mem.payload.run_id && { run_id: mem.payload.run_id }
8635
+ ...mem.payload.run_id && { run_id: mem.payload.run_id },
8636
+ ...mem.payload.attributedTo && {
8637
+ attributedTo: mem.payload.attributedTo
8638
+ }
8375
8639
  }));
8376
8640
  const result = { results };
8377
8641
  const scaleThresholdNotice = detectScaleThresholdFromTopK(topK);
@@ -8605,6 +8869,7 @@ export {
8605
8869
  LangchainEmbedder,
8606
8870
  LangchainLLM,
8607
8871
  LangchainVectorStore,
8872
+ LiteLLM,
8608
8873
  Memory,
8609
8874
  MemoryConfigSchema,
8610
8875
  MemoryVectorStore,