toon-memory 1.6.6 → 1.6.7

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,9 +27716,11 @@ 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 data;
27704
27722
  try {
27705
- return decrypt(data, config2.key);
27723
+ return decrypt(data, key);
27706
27724
  } catch {
27707
27725
  return data;
27708
27726
  }
@@ -27712,12 +27730,15 @@ 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);
27717
- writeFileSync(MEMORY_FILE, encrypted);
27718
- } else {
27719
- writeFileSync(MEMORY_FILE, content);
27733
+ if (config2.encrypted) {
27734
+ const key = readEnvKey();
27735
+ if (key) {
27736
+ const encrypted = encrypt(content, key);
27737
+ writeFileSync(MEMORY_FILE, encrypted);
27738
+ return;
27739
+ }
27720
27740
  }
27741
+ writeFileSync(MEMORY_FILE, content);
27721
27742
  }
27722
27743
  function generateId() {
27723
27744
  return randomBytes(4).toString("hex");
@@ -28022,7 +28043,8 @@ server.registerTool(
28022
28043
  const data = readFileSync(MEMORY_FILE, "utf-8");
28023
28044
  const encrypted = encrypt(data, key);
28024
28045
  writeFileSync(MEMORY_FILE, encrypted);
28025
- saveConfig({ encrypted: true, key });
28046
+ saveConfig({ encrypted: true });
28047
+ writeEnvKey(key);
28026
28048
  return {
28027
28049
  content: [{
28028
28050
  type: "text",
@@ -28047,9 +28069,13 @@ server.registerTool(
28047
28069
  if (!config2.encrypted) {
28048
28070
  return { content: [{ type: "text", text: "La encriptaci\xF3n no est\xE1 habilitada" }] };
28049
28071
  }
28072
+ const resolvedKey = key || readEnvKey() || "";
28073
+ if (!resolvedKey) {
28074
+ return { content: [{ type: "text", text: "\u274C No hay clave. P\xE1sala como argumento o la del archivo .env" }] };
28075
+ }
28050
28076
  try {
28051
28077
  const data = readFileSync(MEMORY_FILE, "utf-8");
28052
- const decrypted = decrypt(data, key);
28078
+ const decrypted = decrypt(data, resolvedKey);
28053
28079
  writeFileSync(MEMORY_FILE, decrypted);
28054
28080
  saveConfig({ encrypted: false });
28055
28081
  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.7",
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,9 +184,11 @@ 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 data
160
190
  try {
161
- return decrypt(data, config.key)
191
+ return decrypt(data, key)
162
192
  } catch {
163
193
  return data
164
194
  }
@@ -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,16 @@ 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)
181
- writeFileSync(MEMORY_FILE, encrypted)
182
- } else {
183
- writeFileSync(MEMORY_FILE, content)
210
+ if (config.encrypted) {
211
+ const key = readEnvKey()
212
+ if (key) {
213
+ const encrypted = encrypt(content, key)
214
+ writeFileSync(MEMORY_FILE, encrypted)
215
+ return
216
+ }
184
217
  }
218
+
219
+ writeFileSync(MEMORY_FILE, content)
185
220
  }
186
221
 
187
222
  /**
@@ -648,7 +683,8 @@ server.registerTool(
648
683
  const encrypted = encrypt(data, key)
649
684
  writeFileSync(MEMORY_FILE, encrypted)
650
685
 
651
- saveConfig({ encrypted: true, key })
686
+ saveConfig({ encrypted: true })
687
+ writeEnvKey(key)
652
688
 
653
689
  return {
654
690
  content: [{
@@ -685,9 +721,14 @@ server.registerTool(
685
721
  return { content: [{ type: "text" as const, text: "La encriptación no está habilitada" }] }
686
722
  }
687
723
 
724
+ const resolvedKey = key || readEnvKey() || ""
725
+ if (!resolvedKey) {
726
+ return { content: [{ type: "text" as const, text: "❌ No hay clave. Pásala como argumento o la del archivo .env" }] }
727
+ }
728
+
688
729
  try {
689
730
  const data = readFileSync(MEMORY_FILE, "utf-8")
690
- const decrypted = decrypt(data, key)
731
+ const decrypted = decrypt(data, resolvedKey)
691
732
 
692
733
  writeFileSync(MEMORY_FILE, decrypted)
693
734
  saveConfig({ encrypted: false })