toon-memory 1.6.1 → 1.6.2

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/cli/setup.js CHANGED
@@ -1,4 +1,4 @@
1
- import { existsSync, mkdirSync, readFileSync, writeFileSync, cpSync, unlinkSync, readdirSync, statSync } from "fs";
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync, readdirSync, statSync } from "fs";
2
2
  import { basename, dirname, join } from "path";
3
3
  import { fileURLToPath } from "url";
4
4
  import { execSync } from "child_process";
@@ -66,15 +66,11 @@ function detectAgents() {
66
66
  return agents2;
67
67
  }
68
68
  function installOpenCodeTools() {
69
- const toolsDir = join(projectRoot, ".opencode", "tools");
70
69
  const memoryDir = join(projectRoot, ".opencode", "memory");
71
70
  const memoryFile = join(memoryDir, "data.toon");
72
- if (!existsSync(toolsDir)) mkdirSync(toolsDir, { recursive: true });
73
71
  if (!existsSync(memoryDir)) mkdirSync(memoryDir, { recursive: true });
74
- cpSync(join(sourceDir, "memory.ts"), join(toolsDir, "memory.ts"));
75
- console.log(" Copied memory.ts to .opencode/tools/");
76
72
  if (!existsSync(memoryFile)) {
77
- writeFileSync(memoryFile, "version: 1\nentries[0|]{id|category|key|content|file|tags|date}:\n");
73
+ writeFileSync(memoryFile, "version: 1\n[0|]\n");
78
74
  console.log(" Created .opencode/memory/data.toon");
79
75
  }
80
76
  }
package/mcp/server.js CHANGED
@@ -27796,16 +27796,16 @@ server.registerTool(
27796
27796
  const id = generateId();
27797
27797
  const date5 = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
27798
27798
  const lines = data.split("\n");
27799
- let headerIdx = lines.findIndex((l) => l.startsWith("entries["));
27799
+ let headerIdx = lines.findIndex((l) => l.startsWith("entries[") || /^\[\d+\|]/.test(l));
27800
27800
  if (headerIdx === -1) {
27801
- lines.push(`entries[0|]{id|category|key|content|file|tags|date}:`);
27801
+ lines.push(`[0|]`);
27802
27802
  headerIdx = lines.length - 1;
27803
27803
  }
27804
- const match = lines[headerIdx].match(/entries\[(\d+)\|/);
27804
+ const match = lines[headerIdx].match(/\[(\d+)\|/);
27805
27805
  const count = match ? parseInt(match[1]) : 0;
27806
27806
  const newEntry = `${id}|${category}|${key}|${content}|${file2 || ""}|${tags || ""}|${date5}`;
27807
27807
  lines.splice(headerIdx + 1, 0, ` ${newEntry}`);
27808
- lines[headerIdx] = lines[headerIdx].replace(/entries\[\d+\|/, `[${count + 1}|`);
27808
+ lines[headerIdx] = lines[headerIdx].replace(/\[\d+\|/, `[${count + 1}|`);
27809
27809
  writeMemory(lines.join("\n"));
27810
27810
  return {
27811
27811
  content: [{ type: "text", text: `\u{1F9E0} Guardado: ${category}/${key} (${id})
@@ -27827,7 +27827,7 @@ server.registerTool(
27827
27827
  },
27828
27828
  async ({ query, category, from_date, to_date }) => {
27829
27829
  const data = readMemory();
27830
- const lines = data.split("\n").filter((l) => l.startsWith(" ") && l.includes("|"));
27830
+ const lines = data.split("\n").filter((l) => l.startsWith(" ") && l.includes("|") && !l.startsWith("summaries:"));
27831
27831
  const queryLower = query.toLowerCase();
27832
27832
  const results = lines.map((line) => {
27833
27833
  const trimmed = line.trim();
@@ -27862,19 +27862,19 @@ server.registerTool(
27862
27862
  async ({ key }) => {
27863
27863
  const data = readMemory();
27864
27864
  const lines = data.split("\n");
27865
- const headerIdx = lines.findIndex((l) => l.startsWith("entries["));
27865
+ const headerIdx = lines.findIndex((l) => l.startsWith("entries[") || /^\[\d+\|]/.test(l));
27866
27866
  if (headerIdx === -1) {
27867
27867
  return { content: [{ type: "text", text: "No hay entradas en memoria" }] };
27868
27868
  }
27869
- const entryLines = lines.slice(headerIdx + 1).filter((l) => l.trim().length > 0);
27869
+ const entryLines = lines.slice(headerIdx + 1).filter((l) => l.trim().length > 0 && !l.startsWith("summaries:"));
27870
27870
  const filtered = entryLines.filter((l) => {
27871
27871
  const parts = l.trim().split("|");
27872
27872
  return parts[0] !== key && parts[2] !== key;
27873
27873
  });
27874
27874
  const removed = entryLines.length - filtered.length;
27875
- const match = lines[headerIdx].match(/entries\[(\d+)\|/);
27875
+ const match = lines[headerIdx].match(/\[(\d+)\|/);
27876
27876
  const count = match ? parseInt(match[1]) : 0;
27877
- lines[headerIdx] = lines[headerIdx].replace(/entries\[\d+\|/, `[${count - removed}|`);
27877
+ lines[headerIdx] = lines[headerIdx].replace(/\[\d+\|/, `[${count - removed}|`);
27878
27878
  lines.splice(headerIdx + 1, entryLines.length, ...filtered.map((l) => ` ${l.trim()}`));
27879
27879
  writeMemory(lines.join("\n"));
27880
27880
  return {
@@ -27891,7 +27891,7 @@ server.registerTool(
27891
27891
  },
27892
27892
  async () => {
27893
27893
  const data = readMemory();
27894
- const lines = data.split("\n").filter((l) => l.startsWith(" ") && l.includes("|"));
27894
+ const lines = data.split("\n").filter((l) => l.startsWith(" ") && l.includes("|") && !l.startsWith(" summaries:"));
27895
27895
  const entries = lines.map((l) => {
27896
27896
  const parts = l.trim().split("|");
27897
27897
  return { category: parts[1] || "unknown" };
@@ -27900,7 +27900,7 @@ server.registerTool(
27900
27900
  for (const e of entries) {
27901
27901
  byCategory[e.category] = (byCategory[e.category] || 0) + 1;
27902
27902
  }
27903
- const summaryLines = data.split("\n").filter((l) => l.includes(":") && !l.startsWith(" ") && !l.startsWith("version") && !l.startsWith("entries"));
27903
+ const summaryLines = data.split("\n").filter((l) => l.includes(":") && !l.startsWith(" ") && !l.startsWith("version") && !l.startsWith("entries") && !/^\[\d+\|]/.test(l));
27904
27904
  const stats = [
27905
27905
  `Entradas totales: ${entries.length}`,
27906
27906
  `Res\xFAmenes de archivos: ${summaryLines.length}`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toon-memory",
3
- "version": "1.6.1",
3
+ "version": "1.6.2",
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/cli/setup.ts CHANGED
@@ -116,10 +116,10 @@ function detectAgents(): Agent[] {
116
116
  }
117
117
 
118
118
  /**
119
- * Install custom tools and memory directory for OpenCode.
119
+ * Install memory directory for OpenCode.
120
120
  *
121
- * Creates `.opencode/tools/` and `.opencode/memory/` directories,
122
- * copies `memory.ts` tool, and creates initial `data.toon` if needed.
121
+ * Creates `.opencode/memory/` directory and initial `data.toon` if needed.
122
+ * The MCP server handles all memory operations - no plugin needed.
123
123
  *
124
124
  * @example
125
125
  * ```bash
@@ -127,18 +127,13 @@ function detectAgents(): Agent[] {
127
127
  * ```
128
128
  */
129
129
  function installOpenCodeTools(): void {
130
- const toolsDir = join(projectRoot, ".opencode", "tools")
131
130
  const memoryDir = join(projectRoot, ".opencode", "memory")
132
131
  const memoryFile = join(memoryDir, "data.toon")
133
132
 
134
- if (!existsSync(toolsDir)) mkdirSync(toolsDir, { recursive: true })
135
133
  if (!existsSync(memoryDir)) mkdirSync(memoryDir, { recursive: true })
136
134
 
137
- cpSync(join(sourceDir, "memory.ts"), join(toolsDir, "memory.ts"))
138
- console.log(" Copied memory.ts to .opencode/tools/")
139
-
140
135
  if (!existsSync(memoryFile)) {
141
- writeFileSync(memoryFile, "version: 1\nentries[0|]{id|category|key|content|file|tags|date}:\n")
136
+ writeFileSync(memoryFile, "version: 1\n[0|]\n")
142
137
  console.log(" Created .opencode/memory/data.toon")
143
138
  }
144
139
  }
package/src/mcp/server.ts CHANGED
@@ -310,18 +310,18 @@ server.registerTool(
310
310
  const date = new Date().toISOString().split("T")[0]
311
311
  const lines = data.split("\n")
312
312
 
313
- let headerIdx = lines.findIndex((l) => l.startsWith("entries["))
313
+ let headerIdx = lines.findIndex((l) => l.startsWith("entries[") || /^\[\d+\|]/.test(l))
314
314
  if (headerIdx === -1) {
315
- lines.push(`entries[0|]{id|category|key|content|file|tags|date}:`)
315
+ lines.push(`[0|]`)
316
316
  headerIdx = lines.length - 1
317
317
  }
318
318
 
319
- const match = lines[headerIdx].match(/entries\[(\d+)\|/)
319
+ const match = lines[headerIdx].match(/\[(\d+)\|/)
320
320
  const count = match ? parseInt(match[1]) : 0
321
321
  const newEntry = `${id}|${category}|${key}|${content}|${file || ""}|${tags || ""}|${date}`
322
322
 
323
323
  lines.splice(headerIdx + 1, 0, ` ${newEntry}`)
324
- lines[headerIdx] = lines[headerIdx].replace(/entries\[\d+\|/, `[${count + 1}|`)
324
+ lines[headerIdx] = lines[headerIdx].replace(/\[\d+\|/, `[${count + 1}|`)
325
325
 
326
326
  writeMemory(lines.join("\n"))
327
327
  return {
@@ -355,7 +355,7 @@ server.registerTool(
355
355
  },
356
356
  async ({ query, category, from_date, to_date }) => {
357
357
  const data = readMemory()
358
- const lines = data.split("\n").filter((l) => l.startsWith(" ") && l.includes("|"))
358
+ const lines = data.split("\n").filter((l) => l.startsWith(" ") && l.includes("|") && !l.startsWith("summaries:"))
359
359
  const queryLower = query.toLowerCase()
360
360
 
361
361
  const results = lines
@@ -406,22 +406,22 @@ server.registerTool(
406
406
  async ({ key }) => {
407
407
  const data = readMemory()
408
408
  const lines = data.split("\n")
409
- const headerIdx = lines.findIndex((l) => l.startsWith("entries["))
409
+ const headerIdx = lines.findIndex((l) => l.startsWith("entries[") || /^\[\d+\|]/.test(l))
410
410
 
411
411
  if (headerIdx === -1) {
412
412
  return { content: [{ type: "text" as const, text: "No hay entradas en memoria" }] }
413
413
  }
414
414
 
415
- const entryLines = lines.slice(headerIdx + 1).filter((l) => l.trim().length > 0)
415
+ const entryLines = lines.slice(headerIdx + 1).filter((l) => l.trim().length > 0 && !l.startsWith("summaries:"))
416
416
  const filtered = entryLines.filter((l) => {
417
417
  const parts = l.trim().split("|")
418
418
  return parts[0] !== key && parts[2] !== key
419
419
  })
420
420
 
421
421
  const removed = entryLines.length - filtered.length
422
- const match = lines[headerIdx].match(/entries\[(\d+)\|/)
422
+ const match = lines[headerIdx].match(/\[(\d+)\|/)
423
423
  const count = match ? parseInt(match[1]) : 0
424
- lines[headerIdx] = lines[headerIdx].replace(/entries\[\d+\|/, `[${count - removed}|`)
424
+ lines[headerIdx] = lines[headerIdx].replace(/\[\d+\|/, `[${count - removed}|`)
425
425
  lines.splice(headerIdx + 1, entryLines.length, ...filtered.map((l) => ` ${l.trim()}`))
426
426
 
427
427
  writeMemory(lines.join("\n"))
@@ -449,7 +449,7 @@ server.registerTool(
449
449
  },
450
450
  async () => {
451
451
  const data = readMemory()
452
- const lines = data.split("\n").filter((l) => l.startsWith(" ") && l.includes("|"))
452
+ const lines = data.split("\n").filter((l) => l.startsWith(" ") && l.includes("|") && !l.startsWith(" summaries:"))
453
453
  const entries = lines.map((l) => {
454
454
  const parts = l.trim().split("|")
455
455
  return { category: parts[1] || "unknown" }
@@ -460,7 +460,7 @@ server.registerTool(
460
460
  byCategory[e.category] = (byCategory[e.category] || 0) + 1
461
461
  }
462
462
 
463
- const summaryLines = data.split("\n").filter((l) => l.includes(":") && !l.startsWith(" ") && !l.startsWith("version") && !l.startsWith("entries"))
463
+ const summaryLines = data.split("\n").filter((l) => l.includes(":") && !l.startsWith(" ") && !l.startsWith("version") && !l.startsWith("entries") && !/^\[\d+\|]/.test(l))
464
464
  const stats = [
465
465
  `Entradas totales: ${entries.length}`,
466
466
  `Resúmenes de archivos: ${summaryLines.length}`,