toon-memory 1.6.6 → 1.6.8

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/install.ps1 CHANGED
@@ -2,6 +2,9 @@
2
2
  # Usage: irm https://raw.githubusercontent.com/LuiggiVal08/toon-memory/main/install.ps1 | iex
3
3
 
4
4
  $TOON_VERSION = "1.0.9"
5
+ # SHA-256 checksum of the tarball. Update on each release.
6
+ # Generate with: certutil -hashfile toon-memory-$TOON_VERSION.tgz SHA256
7
+ $TOON_CHECKSUM = "d5b2a8cbe0f3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9"
5
8
 
6
9
  Write-Host "🧠 toon-memory installer" -ForegroundColor Cyan
7
10
  Write-Host ""
@@ -32,6 +35,16 @@ if (Get-Command npm -ErrorAction SilentlyContinue) {
32
35
  $tgzPath = "$INSTALL_DIR\toon-memory.tgz"
33
36
  Invoke-WebRequest -Uri $url -OutFile $tgzPath
34
37
 
38
+ # Verify integrity
39
+ $actualHash = (Get-FileHash -Path $tgzPath -Algorithm SHA256).Hash.ToLower()
40
+ if ($actualHash -ne $TOON_CHECKSUM) {
41
+ Write-Host "❌ Checksum mismatch! Expected $TOON_CHECKSUM, got $actualHash" -ForegroundColor Red
42
+ Write-Host "The downloaded file may be corrupted or tampered with." -ForegroundColor Red
43
+ Remove-Item -Path $tgzPath -Force
44
+ exit 1
45
+ }
46
+ Write-Host "✅ Integrity verified" -ForegroundColor Green
47
+
35
48
  # Extract
36
49
  cd $INSTALL_DIR
37
50
  tar xzf toon-memory.tgz
package/mcp/server.js CHANGED
@@ -27648,6 +27648,7 @@ var MEMORY_DIR = join(process.cwd(), ".opencode", "memory");
27648
27648
  var MEMORY_FILE = join(MEMORY_DIR, "data.toon");
27649
27649
  var ARCHIVE_FILE = join(MEMORY_DIR, "archive.toon");
27650
27650
  var CONFIG_FILE = join(MEMORY_DIR, "config.json");
27651
+ var ENV_FILE = join(MEMORY_DIR, ".env");
27651
27652
  var ARCHIVE_DAYS = 30;
27652
27653
  var ALGORITHM = "aes-256-gcm";
27653
27654
  function loadConfig() {
@@ -27664,6 +27665,21 @@ function saveConfig(config2) {
27664
27665
  ensureMemoryDir();
27665
27666
  writeFileSync(CONFIG_FILE, JSON.stringify(config2, null, 2));
27666
27667
  }
27668
+ function readEnvKey() {
27669
+ try {
27670
+ if (!existsSync(ENV_FILE)) return void 0;
27671
+ const content = readFileSync(ENV_FILE, "utf-8").trim();
27672
+ const match = content.match(/^TOON_MEMORY_KEY=(.+)$/m);
27673
+ return match ? match[1] : void 0;
27674
+ } catch {
27675
+ return void 0;
27676
+ }
27677
+ }
27678
+ function writeEnvKey(key) {
27679
+ ensureMemoryDir();
27680
+ writeFileSync(ENV_FILE, `TOON_MEMORY_KEY=${key}
27681
+ `);
27682
+ }
27667
27683
  function ensureMemoryDir() {
27668
27684
  if (!existsSync(MEMORY_DIR)) mkdirSync(MEMORY_DIR, { recursive: true });
27669
27685
  }
@@ -27700,11 +27716,13 @@ function readMemory() {
27700
27716
  ensureMemoryFile();
27701
27717
  const config2 = loadConfig();
27702
27718
  const data = readFileSync(MEMORY_FILE, "utf-8");
27703
- if (config2.encrypted && config2.key) {
27719
+ if (config2.encrypted) {
27720
+ const key = readEnvKey();
27721
+ if (!key) return "";
27704
27722
  try {
27705
- return decrypt(data, config2.key);
27723
+ return decrypt(data, key);
27706
27724
  } catch {
27707
- return data;
27725
+ return "";
27708
27726
  }
27709
27727
  }
27710
27728
  return data;
@@ -27712,12 +27730,14 @@ function readMemory() {
27712
27730
  function writeMemory(content) {
27713
27731
  ensureMemoryFile();
27714
27732
  const config2 = loadConfig();
27715
- if (config2.encrypted && config2.key) {
27716
- const encrypted = encrypt(content, config2.key);
27733
+ if (config2.encrypted) {
27734
+ const key = readEnvKey();
27735
+ if (!key) return;
27736
+ const encrypted = encrypt(content, key);
27717
27737
  writeFileSync(MEMORY_FILE, encrypted);
27718
- } else {
27719
- writeFileSync(MEMORY_FILE, content);
27738
+ return;
27720
27739
  }
27740
+ writeFileSync(MEMORY_FILE, content);
27721
27741
  }
27722
27742
  function generateId() {
27723
27743
  return randomBytes(4).toString("hex");
@@ -28022,14 +28042,10 @@ server.registerTool(
28022
28042
  const data = readFileSync(MEMORY_FILE, "utf-8");
28023
28043
  const encrypted = encrypt(data, key);
28024
28044
  writeFileSync(MEMORY_FILE, encrypted);
28025
- saveConfig({ encrypted: true, key });
28045
+ saveConfig({ encrypted: true });
28046
+ writeEnvKey(key);
28026
28047
  return {
28027
- content: [{
28028
- type: "text",
28029
- text: `\u{1F510} Encriptaci\xF3n habilitada
28030
- \u26A0\uFE0F Guarda esta clave (no se puede recuperar):
28031
- ${key}`
28032
- }]
28048
+ content: [{ type: "text", text: "\u{1F510} Encriptaci\xF3n habilitada" }]
28033
28049
  };
28034
28050
  }
28035
28051
  );
@@ -28047,9 +28063,13 @@ server.registerTool(
28047
28063
  if (!config2.encrypted) {
28048
28064
  return { content: [{ type: "text", text: "La encriptaci\xF3n no est\xE1 habilitada" }] };
28049
28065
  }
28066
+ const resolvedKey = key || readEnvKey() || "";
28067
+ if (!resolvedKey) {
28068
+ return { content: [{ type: "text", text: "\u274C No hay clave. P\xE1sala como argumento o la del archivo .env" }] };
28069
+ }
28050
28070
  try {
28051
28071
  const data = readFileSync(MEMORY_FILE, "utf-8");
28052
- const decrypted = decrypt(data, key);
28072
+ const decrypted = decrypt(data, resolvedKey);
28053
28073
  writeFileSync(MEMORY_FILE, decrypted);
28054
28074
  saveConfig({ encrypted: false });
28055
28075
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toon-memory",
3
- "version": "1.6.6",
3
+ "version": "1.6.8",
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
@@ -20,6 +20,9 @@ const ARCHIVE_FILE = join(MEMORY_DIR, "archive.toon")
20
20
  /** Configuration file for encryption settings */
21
21
  const CONFIG_FILE = join(MEMORY_DIR, "config.json")
22
22
 
23
+ /** Env file storing the encryption key (gitignored via .opencode/) */
24
+ const ENV_FILE = join(MEMORY_DIR, ".env")
25
+
23
26
  /** Maximum active entries before auto-archive */
24
27
  const MAX_ENTRIES = 100
25
28
 
@@ -33,8 +36,6 @@ const ALGORITHM = "aes-256-gcm"
33
36
  interface MemoryConfig {
34
37
  /** Whether encryption is enabled */
35
38
  encrypted: boolean
36
- /** Encryption key (hex-encoded, 64 chars for AES-256) */
37
- key?: string
38
39
  }
39
40
 
40
41
  /**
@@ -71,6 +72,32 @@ function saveConfig(config: MemoryConfig): void {
71
72
  writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2))
72
73
  }
73
74
 
75
+ /**
76
+ * Read the encryption key from .env file.
77
+ *
78
+ * @returns The key string, or undefined if not set
79
+ */
80
+ function readEnvKey(): string | undefined {
81
+ try {
82
+ if (!existsSync(ENV_FILE)) return undefined
83
+ const content = readFileSync(ENV_FILE, "utf-8").trim()
84
+ const match = content.match(/^TOON_MEMORY_KEY=(.+)$/m)
85
+ return match ? match[1] : undefined
86
+ } catch {
87
+ return undefined
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Write the encryption key to .env file.
93
+ *
94
+ * @param key - Hex-encoded encryption key
95
+ */
96
+ function writeEnvKey(key: string): void {
97
+ ensureMemoryDir()
98
+ writeFileSync(ENV_FILE, `TOON_MEMORY_KEY=${key}\n`)
99
+ }
100
+
74
101
  /**
75
102
  * Ensure memory directory exists, creating it if necessary.
76
103
  */
@@ -148,6 +175,7 @@ function generateKey(): string {
148
175
 
149
176
  /**
150
177
  * Read memory file, decrypting if encryption is enabled.
178
+ * Key is read from TOON_MEMORY_KEY env var.
151
179
  *
152
180
  * @returns Memory content as string (TOON format)
153
181
  */
@@ -156,11 +184,13 @@ function readMemory(): string {
156
184
  const config = loadConfig()
157
185
  const data = readFileSync(MEMORY_FILE, "utf-8")
158
186
 
159
- if (config.encrypted && config.key) {
187
+ if (config.encrypted) {
188
+ const key = readEnvKey()
189
+ if (!key) return ""
160
190
  try {
161
- return decrypt(data, config.key)
191
+ return decrypt(data, key)
162
192
  } catch {
163
- return data
193
+ return ""
164
194
  }
165
195
  }
166
196
 
@@ -169,6 +199,7 @@ function readMemory(): string {
169
199
 
170
200
  /**
171
201
  * Write content to memory file, encrypting if encryption is enabled.
202
+ * Key is read from TOON_MEMORY_KEY env var.
172
203
  *
173
204
  * @param content - Memory content to write (TOON format)
174
205
  */
@@ -176,12 +207,15 @@ function writeMemory(content: string): void {
176
207
  ensureMemoryFile()
177
208
  const config = loadConfig()
178
209
 
179
- if (config.encrypted && config.key) {
180
- const encrypted = encrypt(content, config.key)
210
+ if (config.encrypted) {
211
+ const key = readEnvKey()
212
+ if (!key) return
213
+ const encrypted = encrypt(content, key)
181
214
  writeFileSync(MEMORY_FILE, encrypted)
182
- } else {
183
- writeFileSync(MEMORY_FILE, content)
215
+ return
184
216
  }
217
+
218
+ writeFileSync(MEMORY_FILE, content)
185
219
  }
186
220
 
187
221
  /**
@@ -648,13 +682,11 @@ server.registerTool(
648
682
  const encrypted = encrypt(data, key)
649
683
  writeFileSync(MEMORY_FILE, encrypted)
650
684
 
651
- saveConfig({ encrypted: true, key })
685
+ saveConfig({ encrypted: true })
686
+ writeEnvKey(key)
652
687
 
653
688
  return {
654
- content: [{
655
- type: "text" as const,
656
- text: `🔐 Encriptación habilitada\n⚠️ Guarda esta clave (no se puede recuperar):\n${key}`
657
- }],
689
+ content: [{ type: "text" as const, text: "🔐 Encriptación habilitada" }],
658
690
  }
659
691
  }
660
692
  )
@@ -685,9 +717,14 @@ server.registerTool(
685
717
  return { content: [{ type: "text" as const, text: "La encriptación no está habilitada" }] }
686
718
  }
687
719
 
720
+ const resolvedKey = key || readEnvKey() || ""
721
+ if (!resolvedKey) {
722
+ return { content: [{ type: "text" as const, text: "❌ No hay clave. Pásala como argumento o la del archivo .env" }] }
723
+ }
724
+
688
725
  try {
689
726
  const data = readFileSync(MEMORY_FILE, "utf-8")
690
- const decrypted = decrypt(data, key)
727
+ const decrypted = decrypt(data, resolvedKey)
691
728
 
692
729
  writeFileSync(MEMORY_FILE, decrypted)
693
730
  saveConfig({ encrypted: false })