toon-memory 1.6.1 → 1.6.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/cli/setup.js +2 -6
- package/mcp/server.js +31 -14
- package/package.json +1 -1
- package/src/cli/setup.ts +4 -9
- package/src/mcp/server.ts +35 -14
package/dist/cli/setup.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync,
|
|
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\
|
|
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,19 +27796,36 @@ 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(`
|
|
27801
|
+
lines.push(`[0|]`);
|
|
27802
27802
|
headerIdx = lines.length - 1;
|
|
27803
27803
|
}
|
|
27804
|
-
|
|
27805
|
-
|
|
27804
|
+
let existingIdx = -1;
|
|
27805
|
+
for (let i = headerIdx + 1; i < lines.length; i++) {
|
|
27806
|
+
const line = lines[i];
|
|
27807
|
+
if (!line.startsWith(" ") || !line.includes("|")) continue;
|
|
27808
|
+
if (line.startsWith(" summaries:")) break;
|
|
27809
|
+
const parts = line.trim().split("|");
|
|
27810
|
+
if (parts[2] === key) {
|
|
27811
|
+
existingIdx = i;
|
|
27812
|
+
break;
|
|
27813
|
+
}
|
|
27814
|
+
}
|
|
27806
27815
|
const newEntry = `${id}|${category}|${key}|${content}|${file2 || ""}|${tags || ""}|${date5}`;
|
|
27807
|
-
|
|
27808
|
-
|
|
27816
|
+
let action = "Guardado";
|
|
27817
|
+
if (existingIdx !== -1) {
|
|
27818
|
+
lines[existingIdx] = ` ${newEntry}`;
|
|
27819
|
+
action = "Actualizado";
|
|
27820
|
+
} else {
|
|
27821
|
+
const match = lines[headerIdx].match(/\[(\d+)\|/);
|
|
27822
|
+
const count = match ? parseInt(match[1]) : 0;
|
|
27823
|
+
lines.splice(headerIdx + 1, 0, ` ${newEntry}`);
|
|
27824
|
+
lines[headerIdx] = lines[headerIdx].replace(/\[\d+\|/, `[${count + 1}|`);
|
|
27825
|
+
}
|
|
27809
27826
|
writeMemory(lines.join("\n"));
|
|
27810
27827
|
return {
|
|
27811
|
-
content: [{ type: "text", text: `\u{1F9E0}
|
|
27828
|
+
content: [{ type: "text", text: `\u{1F9E0} ${action}: ${category}/${key} (${id})
|
|
27812
27829
|
${content}` }]
|
|
27813
27830
|
};
|
|
27814
27831
|
}
|
|
@@ -27827,7 +27844,7 @@ server.registerTool(
|
|
|
27827
27844
|
},
|
|
27828
27845
|
async ({ query, category, from_date, to_date }) => {
|
|
27829
27846
|
const data = readMemory();
|
|
27830
|
-
const lines = data.split("\n").filter((l) => l.startsWith(" ") && l.includes("|"));
|
|
27847
|
+
const lines = data.split("\n").filter((l) => l.startsWith(" ") && l.includes("|") && !l.startsWith("summaries:"));
|
|
27831
27848
|
const queryLower = query.toLowerCase();
|
|
27832
27849
|
const results = lines.map((line) => {
|
|
27833
27850
|
const trimmed = line.trim();
|
|
@@ -27862,19 +27879,19 @@ server.registerTool(
|
|
|
27862
27879
|
async ({ key }) => {
|
|
27863
27880
|
const data = readMemory();
|
|
27864
27881
|
const lines = data.split("\n");
|
|
27865
|
-
const headerIdx = lines.findIndex((l) => l.startsWith("entries["));
|
|
27882
|
+
const headerIdx = lines.findIndex((l) => l.startsWith("entries[") || /^\[\d+\|]/.test(l));
|
|
27866
27883
|
if (headerIdx === -1) {
|
|
27867
27884
|
return { content: [{ type: "text", text: "No hay entradas en memoria" }] };
|
|
27868
27885
|
}
|
|
27869
|
-
const entryLines = lines.slice(headerIdx + 1).filter((l) => l.trim().length > 0);
|
|
27886
|
+
const entryLines = lines.slice(headerIdx + 1).filter((l) => l.trim().length > 0 && !l.startsWith("summaries:"));
|
|
27870
27887
|
const filtered = entryLines.filter((l) => {
|
|
27871
27888
|
const parts = l.trim().split("|");
|
|
27872
27889
|
return parts[0] !== key && parts[2] !== key;
|
|
27873
27890
|
});
|
|
27874
27891
|
const removed = entryLines.length - filtered.length;
|
|
27875
|
-
const match = lines[headerIdx].match(
|
|
27892
|
+
const match = lines[headerIdx].match(/\[(\d+)\|/);
|
|
27876
27893
|
const count = match ? parseInt(match[1]) : 0;
|
|
27877
|
-
lines[headerIdx] = lines[headerIdx].replace(
|
|
27894
|
+
lines[headerIdx] = lines[headerIdx].replace(/\[\d+\|/, `[${count - removed}|`);
|
|
27878
27895
|
lines.splice(headerIdx + 1, entryLines.length, ...filtered.map((l) => ` ${l.trim()}`));
|
|
27879
27896
|
writeMemory(lines.join("\n"));
|
|
27880
27897
|
return {
|
|
@@ -27891,7 +27908,7 @@ server.registerTool(
|
|
|
27891
27908
|
},
|
|
27892
27909
|
async () => {
|
|
27893
27910
|
const data = readMemory();
|
|
27894
|
-
const lines = data.split("\n").filter((l) => l.startsWith(" ") && l.includes("|"));
|
|
27911
|
+
const lines = data.split("\n").filter((l) => l.startsWith(" ") && l.includes("|") && !l.startsWith(" summaries:"));
|
|
27895
27912
|
const entries = lines.map((l) => {
|
|
27896
27913
|
const parts = l.trim().split("|");
|
|
27897
27914
|
return { category: parts[1] || "unknown" };
|
|
@@ -27900,7 +27917,7 @@ server.registerTool(
|
|
|
27900
27917
|
for (const e of entries) {
|
|
27901
27918
|
byCategory[e.category] = (byCategory[e.category] || 0) + 1;
|
|
27902
27919
|
}
|
|
27903
|
-
const summaryLines = data.split("\n").filter((l) => l.includes(":") && !l.startsWith(" ") && !l.startsWith("version") && !l.startsWith("entries"));
|
|
27920
|
+
const summaryLines = data.split("\n").filter((l) => l.includes(":") && !l.startsWith(" ") && !l.startsWith("version") && !l.startsWith("entries") && !/^\[\d+\|]/.test(l));
|
|
27904
27921
|
const stats = [
|
|
27905
27922
|
`Entradas totales: ${entries.length}`,
|
|
27906
27923
|
`Res\xFAmenes de archivos: ${summaryLines.length}`,
|
package/package.json
CHANGED
package/src/cli/setup.ts
CHANGED
|
@@ -116,10 +116,10 @@ function detectAgents(): Agent[] {
|
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
/**
|
|
119
|
-
* Install
|
|
119
|
+
* Install memory directory for OpenCode.
|
|
120
120
|
*
|
|
121
|
-
* Creates `.opencode/
|
|
122
|
-
*
|
|
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\
|
|
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,22 +310,43 @@ 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(`
|
|
315
|
+
lines.push(`[0|]`)
|
|
316
316
|
headerIdx = lines.length - 1
|
|
317
317
|
}
|
|
318
318
|
|
|
319
|
-
|
|
320
|
-
|
|
319
|
+
// Find existing entry with same key (upsert)
|
|
320
|
+
let existingIdx = -1
|
|
321
|
+
for (let i = headerIdx + 1; i < lines.length; i++) {
|
|
322
|
+
const line = lines[i]
|
|
323
|
+
if (!line.startsWith(" ") || !line.includes("|")) continue
|
|
324
|
+
if (line.startsWith(" summaries:")) break
|
|
325
|
+
const parts = line.trim().split("|")
|
|
326
|
+
if (parts[2] === key) {
|
|
327
|
+
existingIdx = i
|
|
328
|
+
break
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
321
332
|
const newEntry = `${id}|${category}|${key}|${content}|${file || ""}|${tags || ""}|${date}`
|
|
333
|
+
let action = "Guardado"
|
|
322
334
|
|
|
323
|
-
|
|
324
|
-
|
|
335
|
+
if (existingIdx !== -1) {
|
|
336
|
+
// Update existing entry
|
|
337
|
+
lines[existingIdx] = ` ${newEntry}`
|
|
338
|
+
action = "Actualizado"
|
|
339
|
+
} else {
|
|
340
|
+
// Create new entry
|
|
341
|
+
const match = lines[headerIdx].match(/\[(\d+)\|/)
|
|
342
|
+
const count = match ? parseInt(match[1]) : 0
|
|
343
|
+
lines.splice(headerIdx + 1, 0, ` ${newEntry}`)
|
|
344
|
+
lines[headerIdx] = lines[headerIdx].replace(/\[\d+\|/, `[${count + 1}|`)
|
|
345
|
+
}
|
|
325
346
|
|
|
326
347
|
writeMemory(lines.join("\n"))
|
|
327
348
|
return {
|
|
328
|
-
content: [{ type: "text" as const, text: `🧠
|
|
349
|
+
content: [{ type: "text" as const, text: `🧠 ${action}: ${category}/${key} (${id})\n${content}` }],
|
|
329
350
|
}
|
|
330
351
|
}
|
|
331
352
|
)
|
|
@@ -355,7 +376,7 @@ server.registerTool(
|
|
|
355
376
|
},
|
|
356
377
|
async ({ query, category, from_date, to_date }) => {
|
|
357
378
|
const data = readMemory()
|
|
358
|
-
const lines = data.split("\n").filter((l) => l.startsWith(" ") && l.includes("|"))
|
|
379
|
+
const lines = data.split("\n").filter((l) => l.startsWith(" ") && l.includes("|") && !l.startsWith("summaries:"))
|
|
359
380
|
const queryLower = query.toLowerCase()
|
|
360
381
|
|
|
361
382
|
const results = lines
|
|
@@ -406,22 +427,22 @@ server.registerTool(
|
|
|
406
427
|
async ({ key }) => {
|
|
407
428
|
const data = readMemory()
|
|
408
429
|
const lines = data.split("\n")
|
|
409
|
-
const headerIdx = lines.findIndex((l) => l.startsWith("entries["))
|
|
430
|
+
const headerIdx = lines.findIndex((l) => l.startsWith("entries[") || /^\[\d+\|]/.test(l))
|
|
410
431
|
|
|
411
432
|
if (headerIdx === -1) {
|
|
412
433
|
return { content: [{ type: "text" as const, text: "No hay entradas en memoria" }] }
|
|
413
434
|
}
|
|
414
435
|
|
|
415
|
-
const entryLines = lines.slice(headerIdx + 1).filter((l) => l.trim().length > 0)
|
|
436
|
+
const entryLines = lines.slice(headerIdx + 1).filter((l) => l.trim().length > 0 && !l.startsWith("summaries:"))
|
|
416
437
|
const filtered = entryLines.filter((l) => {
|
|
417
438
|
const parts = l.trim().split("|")
|
|
418
439
|
return parts[0] !== key && parts[2] !== key
|
|
419
440
|
})
|
|
420
441
|
|
|
421
442
|
const removed = entryLines.length - filtered.length
|
|
422
|
-
const match = lines[headerIdx].match(
|
|
443
|
+
const match = lines[headerIdx].match(/\[(\d+)\|/)
|
|
423
444
|
const count = match ? parseInt(match[1]) : 0
|
|
424
|
-
lines[headerIdx] = lines[headerIdx].replace(
|
|
445
|
+
lines[headerIdx] = lines[headerIdx].replace(/\[\d+\|/, `[${count - removed}|`)
|
|
425
446
|
lines.splice(headerIdx + 1, entryLines.length, ...filtered.map((l) => ` ${l.trim()}`))
|
|
426
447
|
|
|
427
448
|
writeMemory(lines.join("\n"))
|
|
@@ -449,7 +470,7 @@ server.registerTool(
|
|
|
449
470
|
},
|
|
450
471
|
async () => {
|
|
451
472
|
const data = readMemory()
|
|
452
|
-
const lines = data.split("\n").filter((l) => l.startsWith(" ") && l.includes("|"))
|
|
473
|
+
const lines = data.split("\n").filter((l) => l.startsWith(" ") && l.includes("|") && !l.startsWith(" summaries:"))
|
|
453
474
|
const entries = lines.map((l) => {
|
|
454
475
|
const parts = l.trim().split("|")
|
|
455
476
|
return { category: parts[1] || "unknown" }
|
|
@@ -460,7 +481,7 @@ server.registerTool(
|
|
|
460
481
|
byCategory[e.category] = (byCategory[e.category] || 0) + 1
|
|
461
482
|
}
|
|
462
483
|
|
|
463
|
-
const summaryLines = data.split("\n").filter((l) => l.includes(":") && !l.startsWith(" ") && !l.startsWith("version") && !l.startsWith("entries"))
|
|
484
|
+
const summaryLines = data.split("\n").filter((l) => l.includes(":") && !l.startsWith(" ") && !l.startsWith("version") && !l.startsWith("entries") && !/^\[\d+\|]/.test(l))
|
|
464
485
|
const stats = [
|
|
465
486
|
`Entradas totales: ${entries.length}`,
|
|
466
487
|
`Resúmenes de archivos: ${summaryLines.length}`,
|