toon-memory 1.6.3 → 1.6.4

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/mcp/server.js CHANGED
@@ -27793,7 +27793,7 @@ server.registerTool(
27793
27793
  },
27794
27794
  async ({ category, key, content, file: file2, tags }) => {
27795
27795
  const data = readMemory();
27796
- const id = generateId();
27796
+ const newId = generateId();
27797
27797
  const date5 = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
27798
27798
  const lines = data.split("\n");
27799
27799
  let headerIdx = lines.findIndex((l) => l.startsWith("entries[") || /^\[\d+\|]/.test(l));
@@ -27802,6 +27802,7 @@ server.registerTool(
27802
27802
  headerIdx = lines.length - 1;
27803
27803
  }
27804
27804
  let existingIdx = -1;
27805
+ let existingId = newId;
27805
27806
  for (let i = headerIdx + 1; i < lines.length; i++) {
27806
27807
  const line = lines[i];
27807
27808
  if (!line.startsWith(" ") || !line.includes("|")) continue;
@@ -27809,10 +27810,12 @@ server.registerTool(
27809
27810
  const parts = line.trim().split("|");
27810
27811
  if (parts[2] === key) {
27811
27812
  existingIdx = i;
27813
+ existingId = parts[0];
27812
27814
  break;
27813
27815
  }
27814
27816
  }
27815
- const newEntry = `${id}|${category}|${key}|${content}|${file2 || ""}|${tags || ""}|${date5}`;
27817
+ const entryId = existingIdx !== -1 ? existingId : newId;
27818
+ const newEntry = `${entryId}|${category}|${key}|${content}|${file2 || ""}|${tags || ""}|${date5}`;
27816
27819
  let action = "Guardado";
27817
27820
  if (existingIdx !== -1) {
27818
27821
  lines[existingIdx] = ` ${newEntry}`;
@@ -27825,7 +27828,7 @@ server.registerTool(
27825
27828
  }
27826
27829
  writeMemory(lines.join("\n"));
27827
27830
  return {
27828
- content: [{ type: "text", text: `\u{1F9E0} ${action}: ${category}/${key} (${id})
27831
+ content: [{ type: "text", text: `\u{1F9E0} ${action}: ${category}/${key} (${entryId})
27829
27832
  ${content}` }]
27830
27833
  };
27831
27834
  }
@@ -27845,7 +27848,8 @@ server.registerTool(
27845
27848
  async ({ query, category, from_date, to_date }) => {
27846
27849
  const data = readMemory();
27847
27850
  const lines = data.split("\n").filter((l) => l.startsWith(" ") && l.includes("|") && !l.startsWith("summaries:"));
27848
- const queryLower = query.toLowerCase();
27851
+ const normalize = (s) => s.toLowerCase().replace(/[-_]/g, " ").replace(/\s+/g, " ").trim();
27852
+ const queryTokens = normalize(query).split(" ").filter(Boolean);
27849
27853
  const results = lines.map((line) => {
27850
27854
  const trimmed = line.trim();
27851
27855
  const parts = trimmed.split("|");
@@ -27854,8 +27858,8 @@ server.registerTool(
27854
27858
  if (category && cat !== category) return null;
27855
27859
  if (from_date && date5 < from_date) return null;
27856
27860
  if (to_date && date5 > to_date) return null;
27857
- const searchStr = `${id} ${cat} ${key} ${content} ${file2} ${tags}`.toLowerCase();
27858
- if (!searchStr.includes(queryLower)) return null;
27861
+ const searchStr = normalize(`${id} ${cat} ${key} ${content} ${file2} ${tags}`);
27862
+ if (!queryTokens.every((token) => searchStr.includes(token))) return null;
27859
27863
  return { id, cat, key, content, file: file2, tags, date: date5 };
27860
27864
  }).filter(Boolean);
27861
27865
  if (results.length === 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toon-memory",
3
- "version": "1.6.3",
3
+ "version": "1.6.4",
4
4
  "description": "Persistent memory system for AI coding agents using TOON format (40% fewer tokens than JSON)",
5
5
  "type": "module",
6
6
  "bin": {
package/src/mcp/server.ts CHANGED
@@ -306,7 +306,7 @@ server.registerTool(
306
306
  },
307
307
  async ({ category, key, content, file, tags }) => {
308
308
  const data = readMemory()
309
- const id = generateId()
309
+ const newId = generateId()
310
310
  const date = new Date().toISOString().split("T")[0]
311
311
  const lines = data.split("\n")
312
312
 
@@ -318,6 +318,7 @@ server.registerTool(
318
318
 
319
319
  // Find existing entry with same key (upsert)
320
320
  let existingIdx = -1
321
+ let existingId = newId
321
322
  for (let i = headerIdx + 1; i < lines.length; i++) {
322
323
  const line = lines[i]
323
324
  if (!line.startsWith(" ") || !line.includes("|")) continue
@@ -325,11 +326,13 @@ server.registerTool(
325
326
  const parts = line.trim().split("|")
326
327
  if (parts[2] === key) {
327
328
  existingIdx = i
329
+ existingId = parts[0] // Preserve original ID
328
330
  break
329
331
  }
330
332
  }
331
333
 
332
- const newEntry = `${id}|${category}|${key}|${content}|${file || ""}|${tags || ""}|${date}`
334
+ const entryId = existingIdx !== -1 ? existingId : newId
335
+ const newEntry = `${entryId}|${category}|${key}|${content}|${file || ""}|${tags || ""}|${date}`
333
336
  let action = "Guardado"
334
337
 
335
338
  if (existingIdx !== -1) {
@@ -346,7 +349,7 @@ server.registerTool(
346
349
 
347
350
  writeMemory(lines.join("\n"))
348
351
  return {
349
- content: [{ type: "text" as const, text: `🧠 ${action}: ${category}/${key} (${id})\n${content}` }],
352
+ content: [{ type: "text" as const, text: `🧠 ${action}: ${category}/${key} (${entryId})\n${content}` }],
350
353
  }
351
354
  }
352
355
  )
@@ -377,7 +380,10 @@ server.registerTool(
377
380
  async ({ query, category, from_date, to_date }) => {
378
381
  const data = readMemory()
379
382
  const lines = data.split("\n").filter((l) => l.startsWith(" ") && l.includes("|") && !l.startsWith("summaries:"))
380
- const queryLower = query.toLowerCase()
383
+
384
+ // Normalize for fuzzy matching: hyphens/underscores → spaces, collapse whitespace
385
+ const normalize = (s: string) => s.toLowerCase().replace(/[-_]/g, " ").replace(/\s+/g, " ").trim()
386
+ const queryTokens = normalize(query).split(" ").filter(Boolean)
381
387
 
382
388
  const results = lines
383
389
  .map((line) => {
@@ -388,8 +394,9 @@ server.registerTool(
388
394
  if (category && cat !== category) return null
389
395
  if (from_date && date < from_date) return null
390
396
  if (to_date && date > to_date) return null
391
- const searchStr = `${id} ${cat} ${key} ${content} ${file} ${tags}`.toLowerCase()
392
- if (!searchStr.includes(queryLower)) return null
397
+ const searchStr = normalize(`${id} ${cat} ${key} ${content} ${file} ${tags}`)
398
+ // All query tokens must match (AND logic)
399
+ if (!queryTokens.every((token) => searchStr.includes(token))) return null
393
400
  return { id, cat, key, content, file, tags, date }
394
401
  })
395
402
  .filter(Boolean)