@hasna/mementos 0.2.0 → 0.3.1

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/index.js CHANGED
@@ -2298,6 +2298,36 @@ var init_types = __esm(() => {
2298
2298
  };
2299
2299
  });
2300
2300
 
2301
+ // src/lib/redact.ts
2302
+ function redactSecrets(text) {
2303
+ let result = text;
2304
+ for (const { pattern } of SECRET_PATTERNS) {
2305
+ pattern.lastIndex = 0;
2306
+ result = result.replace(pattern, REDACTED);
2307
+ }
2308
+ return result;
2309
+ }
2310
+ var REDACTED = "[REDACTED]", SECRET_PATTERNS;
2311
+ var init_redact = __esm(() => {
2312
+ SECRET_PATTERNS = [
2313
+ { name: "openai_key", pattern: /sk-[a-zA-Z0-9_-]{20,}/g },
2314
+ { name: "anthropic_key", pattern: /sk-ant-[a-zA-Z0-9_-]{20,}/g },
2315
+ { name: "generic_key", pattern: /(?:pk|tok|key|token|api[_-]?key)[_-][a-zA-Z0-9_-]{16,}/gi },
2316
+ { name: "aws_key", pattern: /AKIA[A-Z0-9]{16}/g },
2317
+ { name: "aws_secret", pattern: /(?<=AWS_SECRET_ACCESS_KEY\s*=\s*)[A-Za-z0-9/+=]{40}/g },
2318
+ { name: "github_token", pattern: /gh[ps]_[a-zA-Z0-9]{36,}/g },
2319
+ { name: "github_oauth", pattern: /gho_[a-zA-Z0-9]{36,}/g },
2320
+ { name: "npm_token", pattern: /npm_[a-zA-Z0-9]{36,}/g },
2321
+ { name: "bearer", pattern: /Bearer\s+[a-zA-Z0-9_\-.]{20,}/g },
2322
+ { name: "conn_string", pattern: /(?:postgres|postgresql|mysql|mongodb|redis|amqp|mqtt):\/\/[^\s"'`]+@[^\s"'`]+/gi },
2323
+ { name: "env_secret", pattern: /(?:SECRET|TOKEN|PASSWORD|PASSPHRASE|API_KEY|PRIVATE_KEY|AUTH|CREDENTIAL)[_A-Z]*\s*=\s*["']?[^\s"'\n]{8,}["']?/gi },
2324
+ { name: "stripe_key", pattern: /(?:sk|pk|rk)_(?:test|live)_[a-zA-Z0-9]{20,}/g },
2325
+ { name: "slack_token", pattern: /xox[bpras]-[a-zA-Z0-9-]{20,}/g },
2326
+ { name: "jwt", pattern: /eyJ[a-zA-Z0-9_-]{10,}\.eyJ[a-zA-Z0-9_-]{10,}\.[a-zA-Z0-9_-]{10,}/g },
2327
+ { name: "hex_secret", pattern: /(?<=(?:key|token|secret|password|hash)\s*[:=]\s*["']?)[0-9a-f]{32,}(?=["']?)/gi }
2328
+ ];
2329
+ });
2330
+
2301
2331
  // src/db/memories.ts
2302
2332
  function parseMemoryRow(row) {
2303
2333
  return {
@@ -2335,6 +2365,8 @@ function createMemory(input, dedupeMode = "merge", db) {
2335
2365
  const tags = input.tags || [];
2336
2366
  const tagsJson = JSON.stringify(tags);
2337
2367
  const metadataJson = JSON.stringify(input.metadata || {});
2368
+ const safeValue = redactSecrets(input.value);
2369
+ const safeSummary = input.summary ? redactSecrets(input.summary) : null;
2338
2370
  if (dedupeMode === "merge") {
2339
2371
  const existing = d.query(`SELECT id, version FROM memories
2340
2372
  WHERE key = ? AND scope = ?
@@ -2348,9 +2380,9 @@ function createMemory(input, dedupeMode = "merge", db) {
2348
2380
  pinned = COALESCE(pinned, 0),
2349
2381
  version = version + 1, updated_at = ?
2350
2382
  WHERE id = ?`, [
2351
- input.value,
2383
+ safeValue,
2352
2384
  input.category || "knowledge",
2353
- input.summary || null,
2385
+ safeSummary,
2354
2386
  tagsJson,
2355
2387
  input.importance ?? 5,
2356
2388
  metadataJson,
@@ -2529,7 +2561,7 @@ function updateMemory(id, input, db) {
2529
2561
  const params = [now()];
2530
2562
  if (input.value !== undefined) {
2531
2563
  sets.push("value = ?");
2532
- params.push(input.value);
2564
+ params.push(redactSecrets(input.value));
2533
2565
  }
2534
2566
  if (input.category !== undefined) {
2535
2567
  sets.push("category = ?");
@@ -2602,6 +2634,7 @@ function cleanExpiredMemories(db) {
2602
2634
  var init_memories = __esm(() => {
2603
2635
  init_types();
2604
2636
  init_database();
2637
+ init_redact();
2605
2638
  });
2606
2639
 
2607
2640
  // src/lib/poll.ts
@@ -3048,7 +3081,9 @@ var DEFAULT_CONFIG = {
3048
3081
  sync_agents: ["claude", "codex", "gemini"],
3049
3082
  auto_cleanup: {
3050
3083
  enabled: true,
3051
- expired_check_interval: 3600
3084
+ expired_check_interval: 3600,
3085
+ unused_archive_days: 7,
3086
+ stale_deprioritize_days: 14
3052
3087
  }
3053
3088
  };
3054
3089
  function deepMerge(target, source) {
@@ -3142,12 +3177,40 @@ function archiveStale(staleDays, db) {
3142
3177
  AND COALESCE(accessed_at, created_at) < ?`, [timestamp, cutoff]);
3143
3178
  return result.changes;
3144
3179
  }
3180
+ function archiveUnused(days, db) {
3181
+ const d = db || getDatabase();
3182
+ const timestamp = now();
3183
+ const cutoff = new Date(Date.now() - days * 24 * 60 * 60 * 1000).toISOString();
3184
+ const result = d.run(`UPDATE memories
3185
+ SET status = 'archived', updated_at = ?
3186
+ WHERE status = 'active'
3187
+ AND pinned = 0
3188
+ AND access_count = 0
3189
+ AND created_at < ?`, [timestamp, cutoff]);
3190
+ return result.changes;
3191
+ }
3192
+ function deprioritizeStale(days, db) {
3193
+ const d = db || getDatabase();
3194
+ const timestamp = now();
3195
+ const cutoff = new Date(Date.now() - days * 24 * 60 * 60 * 1000).toISOString();
3196
+ const result = d.run(`UPDATE memories
3197
+ SET importance = MAX(importance - 1, 1),
3198
+ version = version + 1,
3199
+ updated_at = ?
3200
+ WHERE status = 'active'
3201
+ AND pinned = 0
3202
+ AND importance > 1
3203
+ AND COALESCE(accessed_at, updated_at) < ?`, [timestamp, cutoff]);
3204
+ return result.changes;
3205
+ }
3145
3206
  function runCleanup(config, db) {
3146
3207
  const d = db || getDatabase();
3147
3208
  const expired = cleanExpiredMemories(d);
3148
3209
  const evicted = enforceQuotas(config, d);
3149
3210
  const archived = archiveStale(90, d);
3150
- return { expired, evicted, archived };
3211
+ const unused_archived = archiveUnused(config.auto_cleanup.unused_archive_days ?? 7, d);
3212
+ const deprioritized = deprioritizeStale(config.auto_cleanup.stale_deprioritize_days ?? 14, d);
3213
+ return { expired, evicted, archived, unused_archived, deprioritized };
3151
3214
  }
3152
3215
 
3153
3216
  // src/lib/injector.ts
@@ -3201,32 +3264,91 @@ class MemoryInjector {
3201
3264
  seen.add(m.id);
3202
3265
  return true;
3203
3266
  });
3204
- unique.sort((a, b) => {
3267
+ if (unique.length === 0) {
3268
+ return "";
3269
+ }
3270
+ const totalCharBudget = maxTokens * 4;
3271
+ const footer = "Tip: Use memory_search for deeper lookup on specific topics.";
3272
+ const footerChars = footer.length;
3273
+ const keyBudget = Math.floor((totalCharBudget - footerChars) * 0.67);
3274
+ const recentBudget = Math.floor((totalCharBudget - footerChars) * 0.33);
3275
+ const keyRanked = [...unique].sort((a, b) => {
3205
3276
  if (a.pinned !== b.pinned)
3206
3277
  return a.pinned ? -1 : 1;
3207
3278
  if (b.importance !== a.importance)
3208
3279
  return b.importance - a.importance;
3209
3280
  return new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime();
3210
3281
  });
3211
- const charBudget = maxTokens * 4;
3212
- const lines = [];
3213
- let totalChars = 0;
3214
- for (const m of unique) {
3282
+ const keyLines = [];
3283
+ const keyIds = new Set;
3284
+ let keyChars = 0;
3285
+ for (const m of keyRanked) {
3215
3286
  if (this.injectedIds.has(m.id))
3216
3287
  continue;
3217
3288
  const line = `- [${m.scope}/${m.category}] ${m.key}: ${m.value}`;
3218
- if (totalChars + line.length > charBudget)
3289
+ if (keyChars + line.length > keyBudget)
3219
3290
  break;
3220
- lines.push(line);
3221
- totalChars += line.length;
3222
- this.injectedIds.add(m.id);
3223
- touchMemory(m.id, db);
3291
+ keyLines.push(line);
3292
+ keyIds.add(m.id);
3293
+ keyChars += line.length;
3294
+ }
3295
+ const recentRanked = [...unique].sort((a, b) => {
3296
+ const aTime = a.accessed_at ? new Date(a.accessed_at).getTime() : 0;
3297
+ const bTime = b.accessed_at ? new Date(b.accessed_at).getTime() : 0;
3298
+ return bTime - aTime;
3299
+ });
3300
+ const recentLines = [];
3301
+ let recentChars = 0;
3302
+ const maxRecent = 5;
3303
+ for (const m of recentRanked) {
3304
+ if (recentLines.length >= maxRecent)
3305
+ break;
3306
+ if (keyIds.has(m.id))
3307
+ continue;
3308
+ if (this.injectedIds.has(m.id))
3309
+ continue;
3310
+ const line = `- [${m.scope}/${m.category}] ${m.key}: ${m.value}`;
3311
+ if (recentChars + line.length > recentBudget)
3312
+ break;
3313
+ recentLines.push(line);
3314
+ recentChars += line.length;
3224
3315
  }
3225
- if (lines.length === 0) {
3316
+ if (keyLines.length === 0 && recentLines.length === 0) {
3226
3317
  return "";
3227
3318
  }
3319
+ const allInjectedMemoryIds = [
3320
+ ...keyIds,
3321
+ ...recentLines.map((_, i) => {
3322
+ let idx = 0;
3323
+ for (const m of recentRanked) {
3324
+ if (keyIds.has(m.id) || this.injectedIds.has(m.id))
3325
+ continue;
3326
+ if (idx === i)
3327
+ return m.id;
3328
+ idx++;
3329
+ }
3330
+ return "";
3331
+ })
3332
+ ].filter(Boolean);
3333
+ for (const id of allInjectedMemoryIds) {
3334
+ this.injectedIds.add(id);
3335
+ touchMemory(id, db);
3336
+ }
3337
+ const sections = [];
3338
+ if (keyLines.length > 0) {
3339
+ sections.push(`## Key Memories
3340
+ ${keyLines.join(`
3341
+ `)}`);
3342
+ }
3343
+ if (recentLines.length > 0) {
3344
+ sections.push(`## Recent Context
3345
+ ${recentLines.join(`
3346
+ `)}`);
3347
+ }
3348
+ sections.push(footer);
3228
3349
  return `<agent-memories>
3229
- ${lines.join(`
3350
+ ${sections.join(`
3351
+
3230
3352
  `)}
3231
3353
  </agent-memories>`;
3232
3354
  }
@@ -3725,9 +3847,11 @@ program2.command("clean").description("Remove expired memories and enforce quota
3725
3847
  outputJson(result);
3726
3848
  } else {
3727
3849
  console.log(chalk.bold("Cleanup complete:"));
3728
- console.log(` Expired removed: ${chalk.red(String(result.expired))}`);
3729
- console.log(` Evicted (quota): ${chalk.yellow(String(result.evicted))}`);
3730
- console.log(` Archived (stale): ${chalk.gray(String(result.archived))}`);
3850
+ console.log(` Expired removed: ${chalk.red(String(result.expired))}`);
3851
+ console.log(` Evicted (quota): ${chalk.yellow(String(result.evicted))}`);
3852
+ console.log(` Archived (stale): ${chalk.gray(String(result.archived))}`);
3853
+ console.log(` Archived (unused): ${chalk.gray(String(result.unused_archived))}`);
3854
+ console.log(` Deprioritized: ${chalk.blue(String(result.deprioritized))}`);
3731
3855
  }
3732
3856
  } catch (e) {
3733
3857
  handleError(e);
@@ -1 +1 @@
1
- {"version":3,"file":"memories.d.ts","sourceRoot":"","sources":["../../src/db/memories.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAyB,MAAM,YAAY,CAAC;AAC7D,OAAO,KAAK,EACV,iBAAiB,EACjB,UAAU,EACV,MAAM,EACN,YAAY,EACZ,iBAAiB,EAClB,MAAM,mBAAmB,CAAC;AAW3B,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAwBnE;AAMD,wBAAgB,YAAY,CAC1B,KAAK,EAAE,iBAAiB,EACxB,UAAU,GAAE,UAAoB,EAChC,EAAE,CAAC,EAAE,QAAQ,GACZ,MAAM,CAoGR;AAMD,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI,CAOlE;AAED,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,MAAM,EAChB,SAAS,CAAC,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,MAAM,EAClB,EAAE,CAAC,EAAE,QAAQ,GACZ,MAAM,GAAG,IAAI,CA4Bf;AAMD,wBAAgB,YAAY,CAAC,MAAM,CAAC,EAAE,YAAY,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,MAAM,EAAE,CA4G3E;AAMD,wBAAgB,YAAY,CAC1B,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,iBAAiB,EACxB,EAAE,CAAC,EAAE,QAAQ,GACZ,MAAM,CAiER;AAMD,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,OAAO,CAI/D;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,MAAM,CAUvE;AAMD,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,IAAI,CAM3D;AAMD,wBAAgB,oBAAoB,CAAC,EAAE,CAAC,EAAE,QAAQ,GAAG,MAAM,CAQ1D"}
1
+ {"version":3,"file":"memories.d.ts","sourceRoot":"","sources":["../../src/db/memories.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAyB,MAAM,YAAY,CAAC;AAC7D,OAAO,KAAK,EACV,iBAAiB,EACjB,UAAU,EACV,MAAM,EACN,YAAY,EACZ,iBAAiB,EAClB,MAAM,mBAAmB,CAAC;AAY3B,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAwBnE;AAMD,wBAAgB,YAAY,CAC1B,KAAK,EAAE,iBAAiB,EACxB,UAAU,GAAE,UAAoB,EAChC,EAAE,CAAC,EAAE,QAAQ,GACZ,MAAM,CAwGR;AAMD,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI,CAOlE;AAED,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,MAAM,EAChB,SAAS,CAAC,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,MAAM,EAClB,EAAE,CAAC,EAAE,QAAQ,GACZ,MAAM,GAAG,IAAI,CA4Bf;AAMD,wBAAgB,YAAY,CAAC,MAAM,CAAC,EAAE,YAAY,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,MAAM,EAAE,CA4G3E;AAMD,wBAAgB,YAAY,CAC1B,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,iBAAiB,EACxB,EAAE,CAAC,EAAE,QAAQ,GACZ,MAAM,CAiER;AAMD,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,OAAO,CAI/D;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,MAAM,CAUvE;AAMD,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,IAAI,CAM3D;AAMD,wBAAgB,oBAAoB,CAAC,EAAE,CAAC,EAAE,QAAQ,GAAG,MAAM,CAQ1D"}
package/dist/index.d.ts CHANGED
@@ -8,6 +8,7 @@ export { searchMemories } from "./lib/search.js";
8
8
  export { loadConfig, DEFAULT_CONFIG } from "./lib/config.js";
9
9
  export { MemoryInjector } from "./lib/injector.js";
10
10
  export type { InjectionOptions } from "./lib/injector.js";
11
- export { enforceQuotas, archiveStale, runCleanup } from "./lib/retention.js";
11
+ export { enforceQuotas, archiveStale, archiveUnused, deprioritizeStale, runCleanup } from "./lib/retention.js";
12
12
  export { syncMemories, defaultSyncAgents } from "./lib/sync.js";
13
+ export { redactSecrets, containsSecrets } from "./lib/redact.js";
13
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,YAAY,EACV,MAAM,EACN,mBAAmB,EACnB,WAAW,EACX,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,WAAW,EACX,iBAAiB,EACjB,iBAAiB,EACjB,UAAU,EACV,KAAK,EACL,OAAO,EACP,cAAc,EACd,aAAa,EACb,WAAW,EACX,UAAU,EACV,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,iBAAiB,EACjB,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,WAAW,EACX,aAAa,EACb,aAAa,EACb,SAAS,EACT,gBAAgB,EAChB,GAAG,EACH,IAAI,EACJ,SAAS,GACV,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,YAAY,EACZ,SAAS,EACT,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,WAAW,EACX,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,aAAa,EACb,QAAQ,EACR,UAAU,EACV,WAAW,GACZ,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,eAAe,EACf,UAAU,EACV,YAAY,GACb,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGjD,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAG7D,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAG1D,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAG7E,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,YAAY,EACV,MAAM,EACN,mBAAmB,EACnB,WAAW,EACX,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,WAAW,EACX,iBAAiB,EACjB,iBAAiB,EACjB,UAAU,EACV,KAAK,EACL,OAAO,EACP,cAAc,EACd,aAAa,EACb,WAAW,EACX,UAAU,EACV,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,iBAAiB,EACjB,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,WAAW,EACX,aAAa,EACb,aAAa,EACb,SAAS,EACT,gBAAgB,EAChB,GAAG,EACH,IAAI,EACJ,SAAS,GACV,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,YAAY,EACZ,SAAS,EACT,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,WAAW,EACX,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,aAAa,EACb,QAAQ,EACR,UAAU,EACV,WAAW,GACZ,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,eAAe,EACf,UAAU,EACV,YAAY,GACb,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGjD,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAG7D,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAG1D,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAG/G,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAGhE,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC"}
package/dist/index.js CHANGED
@@ -243,6 +243,42 @@ function resolvePartialId(db, table, partialId) {
243
243
  }
244
244
  return null;
245
245
  }
246
+ // src/lib/redact.ts
247
+ var REDACTED = "[REDACTED]";
248
+ var SECRET_PATTERNS = [
249
+ { name: "openai_key", pattern: /sk-[a-zA-Z0-9_-]{20,}/g },
250
+ { name: "anthropic_key", pattern: /sk-ant-[a-zA-Z0-9_-]{20,}/g },
251
+ { name: "generic_key", pattern: /(?:pk|tok|key|token|api[_-]?key)[_-][a-zA-Z0-9_-]{16,}/gi },
252
+ { name: "aws_key", pattern: /AKIA[A-Z0-9]{16}/g },
253
+ { name: "aws_secret", pattern: /(?<=AWS_SECRET_ACCESS_KEY\s*=\s*)[A-Za-z0-9/+=]{40}/g },
254
+ { name: "github_token", pattern: /gh[ps]_[a-zA-Z0-9]{36,}/g },
255
+ { name: "github_oauth", pattern: /gho_[a-zA-Z0-9]{36,}/g },
256
+ { name: "npm_token", pattern: /npm_[a-zA-Z0-9]{36,}/g },
257
+ { name: "bearer", pattern: /Bearer\s+[a-zA-Z0-9_\-.]{20,}/g },
258
+ { name: "conn_string", pattern: /(?:postgres|postgresql|mysql|mongodb|redis|amqp|mqtt):\/\/[^\s"'`]+@[^\s"'`]+/gi },
259
+ { name: "env_secret", pattern: /(?:SECRET|TOKEN|PASSWORD|PASSPHRASE|API_KEY|PRIVATE_KEY|AUTH|CREDENTIAL)[_A-Z]*\s*=\s*["']?[^\s"'\n]{8,}["']?/gi },
260
+ { name: "stripe_key", pattern: /(?:sk|pk|rk)_(?:test|live)_[a-zA-Z0-9]{20,}/g },
261
+ { name: "slack_token", pattern: /xox[bpras]-[a-zA-Z0-9-]{20,}/g },
262
+ { name: "jwt", pattern: /eyJ[a-zA-Z0-9_-]{10,}\.eyJ[a-zA-Z0-9_-]{10,}\.[a-zA-Z0-9_-]{10,}/g },
263
+ { name: "hex_secret", pattern: /(?<=(?:key|token|secret|password|hash)\s*[:=]\s*["']?)[0-9a-f]{32,}(?=["']?)/gi }
264
+ ];
265
+ function redactSecrets(text) {
266
+ let result = text;
267
+ for (const { pattern } of SECRET_PATTERNS) {
268
+ pattern.lastIndex = 0;
269
+ result = result.replace(pattern, REDACTED);
270
+ }
271
+ return result;
272
+ }
273
+ function containsSecrets(text) {
274
+ for (const { pattern } of SECRET_PATTERNS) {
275
+ pattern.lastIndex = 0;
276
+ if (pattern.test(text))
277
+ return true;
278
+ }
279
+ return false;
280
+ }
281
+
246
282
  // src/db/memories.ts
247
283
  function parseMemoryRow(row) {
248
284
  return {
@@ -280,6 +316,8 @@ function createMemory(input, dedupeMode = "merge", db) {
280
316
  const tags = input.tags || [];
281
317
  const tagsJson = JSON.stringify(tags);
282
318
  const metadataJson = JSON.stringify(input.metadata || {});
319
+ const safeValue = redactSecrets(input.value);
320
+ const safeSummary = input.summary ? redactSecrets(input.summary) : null;
283
321
  if (dedupeMode === "merge") {
284
322
  const existing = d.query(`SELECT id, version FROM memories
285
323
  WHERE key = ? AND scope = ?
@@ -293,9 +331,9 @@ function createMemory(input, dedupeMode = "merge", db) {
293
331
  pinned = COALESCE(pinned, 0),
294
332
  version = version + 1, updated_at = ?
295
333
  WHERE id = ?`, [
296
- input.value,
334
+ safeValue,
297
335
  input.category || "knowledge",
298
- input.summary || null,
336
+ safeSummary,
299
337
  tagsJson,
300
338
  input.importance ?? 5,
301
339
  metadataJson,
@@ -474,7 +512,7 @@ function updateMemory(id, input, db) {
474
512
  const params = [now()];
475
513
  if (input.value !== undefined) {
476
514
  sets.push("value = ?");
477
- params.push(input.value);
515
+ params.push(redactSecrets(input.value));
478
516
  }
479
517
  if (input.category !== undefined) {
480
518
  sets.push("category = ?");
@@ -845,7 +883,9 @@ var DEFAULT_CONFIG = {
845
883
  sync_agents: ["claude", "codex", "gemini"],
846
884
  auto_cleanup: {
847
885
  enabled: true,
848
- expired_check_interval: 3600
886
+ expired_check_interval: 3600,
887
+ unused_archive_days: 7,
888
+ stale_deprioritize_days: 14
849
889
  }
850
890
  };
851
891
  function deepMerge(target, source) {
@@ -951,32 +991,91 @@ class MemoryInjector {
951
991
  seen.add(m.id);
952
992
  return true;
953
993
  });
954
- unique.sort((a, b) => {
994
+ if (unique.length === 0) {
995
+ return "";
996
+ }
997
+ const totalCharBudget = maxTokens * 4;
998
+ const footer = "Tip: Use memory_search for deeper lookup on specific topics.";
999
+ const footerChars = footer.length;
1000
+ const keyBudget = Math.floor((totalCharBudget - footerChars) * 0.67);
1001
+ const recentBudget = Math.floor((totalCharBudget - footerChars) * 0.33);
1002
+ const keyRanked = [...unique].sort((a, b) => {
955
1003
  if (a.pinned !== b.pinned)
956
1004
  return a.pinned ? -1 : 1;
957
1005
  if (b.importance !== a.importance)
958
1006
  return b.importance - a.importance;
959
1007
  return new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime();
960
1008
  });
961
- const charBudget = maxTokens * 4;
962
- const lines = [];
963
- let totalChars = 0;
964
- for (const m of unique) {
1009
+ const keyLines = [];
1010
+ const keyIds = new Set;
1011
+ let keyChars = 0;
1012
+ for (const m of keyRanked) {
965
1013
  if (this.injectedIds.has(m.id))
966
1014
  continue;
967
1015
  const line = `- [${m.scope}/${m.category}] ${m.key}: ${m.value}`;
968
- if (totalChars + line.length > charBudget)
1016
+ if (keyChars + line.length > keyBudget)
969
1017
  break;
970
- lines.push(line);
971
- totalChars += line.length;
972
- this.injectedIds.add(m.id);
973
- touchMemory(m.id, db);
1018
+ keyLines.push(line);
1019
+ keyIds.add(m.id);
1020
+ keyChars += line.length;
974
1021
  }
975
- if (lines.length === 0) {
1022
+ const recentRanked = [...unique].sort((a, b) => {
1023
+ const aTime = a.accessed_at ? new Date(a.accessed_at).getTime() : 0;
1024
+ const bTime = b.accessed_at ? new Date(b.accessed_at).getTime() : 0;
1025
+ return bTime - aTime;
1026
+ });
1027
+ const recentLines = [];
1028
+ let recentChars = 0;
1029
+ const maxRecent = 5;
1030
+ for (const m of recentRanked) {
1031
+ if (recentLines.length >= maxRecent)
1032
+ break;
1033
+ if (keyIds.has(m.id))
1034
+ continue;
1035
+ if (this.injectedIds.has(m.id))
1036
+ continue;
1037
+ const line = `- [${m.scope}/${m.category}] ${m.key}: ${m.value}`;
1038
+ if (recentChars + line.length > recentBudget)
1039
+ break;
1040
+ recentLines.push(line);
1041
+ recentChars += line.length;
1042
+ }
1043
+ if (keyLines.length === 0 && recentLines.length === 0) {
976
1044
  return "";
977
1045
  }
1046
+ const allInjectedMemoryIds = [
1047
+ ...keyIds,
1048
+ ...recentLines.map((_, i) => {
1049
+ let idx = 0;
1050
+ for (const m of recentRanked) {
1051
+ if (keyIds.has(m.id) || this.injectedIds.has(m.id))
1052
+ continue;
1053
+ if (idx === i)
1054
+ return m.id;
1055
+ idx++;
1056
+ }
1057
+ return "";
1058
+ })
1059
+ ].filter(Boolean);
1060
+ for (const id of allInjectedMemoryIds) {
1061
+ this.injectedIds.add(id);
1062
+ touchMemory(id, db);
1063
+ }
1064
+ const sections = [];
1065
+ if (keyLines.length > 0) {
1066
+ sections.push(`## Key Memories
1067
+ ${keyLines.join(`
1068
+ `)}`);
1069
+ }
1070
+ if (recentLines.length > 0) {
1071
+ sections.push(`## Recent Context
1072
+ ${recentLines.join(`
1073
+ `)}`);
1074
+ }
1075
+ sections.push(footer);
978
1076
  return `<agent-memories>
979
- ${lines.join(`
1077
+ ${sections.join(`
1078
+
980
1079
  `)}
981
1080
  </agent-memories>`;
982
1081
  }
@@ -1022,12 +1121,40 @@ function archiveStale(staleDays, db) {
1022
1121
  AND COALESCE(accessed_at, created_at) < ?`, [timestamp, cutoff]);
1023
1122
  return result.changes;
1024
1123
  }
1124
+ function archiveUnused(days, db) {
1125
+ const d = db || getDatabase();
1126
+ const timestamp = now();
1127
+ const cutoff = new Date(Date.now() - days * 24 * 60 * 60 * 1000).toISOString();
1128
+ const result = d.run(`UPDATE memories
1129
+ SET status = 'archived', updated_at = ?
1130
+ WHERE status = 'active'
1131
+ AND pinned = 0
1132
+ AND access_count = 0
1133
+ AND created_at < ?`, [timestamp, cutoff]);
1134
+ return result.changes;
1135
+ }
1136
+ function deprioritizeStale(days, db) {
1137
+ const d = db || getDatabase();
1138
+ const timestamp = now();
1139
+ const cutoff = new Date(Date.now() - days * 24 * 60 * 60 * 1000).toISOString();
1140
+ const result = d.run(`UPDATE memories
1141
+ SET importance = MAX(importance - 1, 1),
1142
+ version = version + 1,
1143
+ updated_at = ?
1144
+ WHERE status = 'active'
1145
+ AND pinned = 0
1146
+ AND importance > 1
1147
+ AND COALESCE(accessed_at, updated_at) < ?`, [timestamp, cutoff]);
1148
+ return result.changes;
1149
+ }
1025
1150
  function runCleanup(config, db) {
1026
1151
  const d = db || getDatabase();
1027
1152
  const expired = cleanExpiredMemories(d);
1028
1153
  const evicted = enforceQuotas(config, d);
1029
1154
  const archived = archiveStale(90, d);
1030
- return { expired, evicted, archived };
1155
+ const unused_archived = archiveUnused(config.auto_cleanup.unused_archive_days ?? 7, d);
1156
+ const deprioritized = deprioritizeStale(config.auto_cleanup.stale_deprioritize_days ?? 14, d);
1157
+ return { expired, evicted, archived, unused_archived, deprioritized };
1031
1158
  }
1032
1159
  // src/lib/sync.ts
1033
1160
  import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync2, writeFileSync } from "fs";
@@ -1171,6 +1298,7 @@ export {
1171
1298
  resetDatabase,
1172
1299
  registerProject,
1173
1300
  registerAgent,
1301
+ redactSecrets,
1174
1302
  now,
1175
1303
  loadConfig,
1176
1304
  listProjects,
@@ -1183,12 +1311,15 @@ export {
1183
1311
  getDatabase,
1184
1312
  getAgent,
1185
1313
  enforceQuotas,
1314
+ deprioritizeStale,
1186
1315
  deleteMemory,
1187
1316
  defaultSyncAgents,
1188
1317
  createMemory,
1318
+ containsSecrets,
1189
1319
  closeDatabase,
1190
1320
  cleanExpiredMemories,
1191
1321
  bulkDeleteMemories,
1322
+ archiveUnused,
1192
1323
  archiveStale,
1193
1324
  VersionConflictError,
1194
1325
  MemoryNotFoundError,
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAA+B,MAAM,UAAU,CAAC;AAM5E,eAAO,MAAM,cAAc,EAAE,cAqB5B,CAAC;AA4DF,wBAAgB,UAAU,IAAI,cAAc,CAwC3C;AAgDD,wBAAgB,SAAS,IAAI,MAAM,CA+BlC"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAA+B,MAAM,UAAU,CAAC;AAM5E,eAAO,MAAM,cAAc,EAAE,cAuB5B,CAAC;AA4DF,wBAAgB,UAAU,IAAI,cAAc,CAwC3C;AAgDD,wBAAgB,SAAS,IAAI,MAAM,CA+BlC"}
@@ -15,7 +15,7 @@ export declare class MemoryInjector {
15
15
  constructor(config?: MementosConfig);
16
16
  /**
17
17
  * Get formatted injection context suitable for system prompt insertion.
18
- * Selects memories by scope visibility, importance, and category.
18
+ * Produces structured output with Key Memories and Recent Context sections.
19
19
  * Token-budget aware.
20
20
  */
21
21
  getInjectionContext(options?: InjectionOptions): string;
@@ -1 +1 @@
1
- {"version":3,"file":"injector.d.ts","sourceRoot":"","sources":["../../src/lib/injector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,KAAK,EAAU,cAAc,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAQhF,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,EAAE,CAAC,EAAE,QAAQ,CAAC;CACf;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,WAAW,CAA0B;gBAEjC,MAAM,CAAC,EAAE,cAAc;IAInC;;;;OAIG;IACH,mBAAmB,CAAC,OAAO,GAAE,gBAAqB,GAAG,MAAM;IAkG3D;;OAEG;IACH,UAAU,IAAI,IAAI;IAIlB;;OAEG;IACH,gBAAgB,IAAI,MAAM;CAG3B"}
1
+ {"version":3,"file":"injector.d.ts","sourceRoot":"","sources":["../../src/lib/injector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,KAAK,EAAU,cAAc,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAQhF,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,EAAE,CAAC,EAAE,QAAQ,CAAC;CACf;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,WAAW,CAA0B;gBAEjC,MAAM,CAAC,EAAE,cAAc;IAInC;;;;OAIG;IACH,mBAAmB,CAAC,OAAO,GAAE,gBAAqB,GAAG,MAAM;IA0K3D;;OAEG;IACH,UAAU,IAAI,IAAI;IAIlB;;OAEG;IACH,gBAAgB,IAAI,MAAM;CAG3B"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Detect and redact secrets from text.
3
+ * Returns the text with secrets replaced by [REDACTED].
4
+ */
5
+ export declare function redactSecrets(text: string): string;
6
+ /**
7
+ * Check if text contains any detectable secrets.
8
+ */
9
+ export declare function containsSecrets(text: string): boolean;
10
+ //# sourceMappingURL=redact.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redact.d.ts","sourceRoot":"","sources":["../../src/lib/redact.ts"],"names":[],"mappings":"AAsCA;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQlD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAMrD"}
@@ -2,9 +2,13 @@ import type { Database } from "bun:sqlite";
2
2
  import type { MementosConfig } from "../types/index.js";
3
3
  export declare function enforceQuotas(config: MementosConfig, db?: Database): number;
4
4
  export declare function archiveStale(staleDays: number, db?: Database): number;
5
+ export declare function archiveUnused(days: number, db?: Database): number;
6
+ export declare function deprioritizeStale(days: number, db?: Database): number;
5
7
  export declare function runCleanup(config: MementosConfig, db?: Database): {
6
8
  expired: number;
7
9
  evicted: number;
8
10
  archived: number;
11
+ unused_archived: number;
12
+ deprioritized: number;
9
13
  };
10
14
  //# sourceMappingURL=retention.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"retention.d.ts","sourceRoot":"","sources":["../../src/lib/retention.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,cAAc,EAAe,MAAM,mBAAmB,CAAC;AAQrE,wBAAgB,aAAa,CAAC,MAAM,EAAE,cAAc,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,MAAM,CAuC3E;AAMD,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,MAAM,CAsBrE;AAMD,wBAAgB,UAAU,CACxB,MAAM,EAAE,cAAc,EACtB,EAAE,CAAC,EAAE,QAAQ,GACZ;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAQxD"}
1
+ {"version":3,"file":"retention.d.ts","sourceRoot":"","sources":["../../src/lib/retention.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,cAAc,EAAe,MAAM,mBAAmB,CAAC;AAQrE,wBAAgB,aAAa,CAAC,MAAM,EAAE,cAAc,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,MAAM,CAuC3E;AAMD,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,MAAM,CAsBrE;AAMD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,MAAM,CAmBjE;AAMD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,MAAM,CAwBrE;AAMD,wBAAgB,UAAU,CACxB,MAAM,EAAE,cAAc,EACtB,EAAE,CAAC,EAAE,QAAQ,GACZ;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,CAgBxG"}
package/dist/mcp/index.js CHANGED
@@ -4217,6 +4217,34 @@ function resolvePartialId(db, table, partialId) {
4217
4217
  return null;
4218
4218
  }
4219
4219
 
4220
+ // src/lib/redact.ts
4221
+ var REDACTED = "[REDACTED]";
4222
+ var SECRET_PATTERNS = [
4223
+ { name: "openai_key", pattern: /sk-[a-zA-Z0-9_-]{20,}/g },
4224
+ { name: "anthropic_key", pattern: /sk-ant-[a-zA-Z0-9_-]{20,}/g },
4225
+ { name: "generic_key", pattern: /(?:pk|tok|key|token|api[_-]?key)[_-][a-zA-Z0-9_-]{16,}/gi },
4226
+ { name: "aws_key", pattern: /AKIA[A-Z0-9]{16}/g },
4227
+ { name: "aws_secret", pattern: /(?<=AWS_SECRET_ACCESS_KEY\s*=\s*)[A-Za-z0-9/+=]{40}/g },
4228
+ { name: "github_token", pattern: /gh[ps]_[a-zA-Z0-9]{36,}/g },
4229
+ { name: "github_oauth", pattern: /gho_[a-zA-Z0-9]{36,}/g },
4230
+ { name: "npm_token", pattern: /npm_[a-zA-Z0-9]{36,}/g },
4231
+ { name: "bearer", pattern: /Bearer\s+[a-zA-Z0-9_\-.]{20,}/g },
4232
+ { name: "conn_string", pattern: /(?:postgres|postgresql|mysql|mongodb|redis|amqp|mqtt):\/\/[^\s"'`]+@[^\s"'`]+/gi },
4233
+ { name: "env_secret", pattern: /(?:SECRET|TOKEN|PASSWORD|PASSPHRASE|API_KEY|PRIVATE_KEY|AUTH|CREDENTIAL)[_A-Z]*\s*=\s*["']?[^\s"'\n]{8,}["']?/gi },
4234
+ { name: "stripe_key", pattern: /(?:sk|pk|rk)_(?:test|live)_[a-zA-Z0-9]{20,}/g },
4235
+ { name: "slack_token", pattern: /xox[bpras]-[a-zA-Z0-9-]{20,}/g },
4236
+ { name: "jwt", pattern: /eyJ[a-zA-Z0-9_-]{10,}\.eyJ[a-zA-Z0-9_-]{10,}\.[a-zA-Z0-9_-]{10,}/g },
4237
+ { name: "hex_secret", pattern: /(?<=(?:key|token|secret|password|hash)\s*[:=]\s*["']?)[0-9a-f]{32,}(?=["']?)/gi }
4238
+ ];
4239
+ function redactSecrets(text) {
4240
+ let result = text;
4241
+ for (const { pattern } of SECRET_PATTERNS) {
4242
+ pattern.lastIndex = 0;
4243
+ result = result.replace(pattern, REDACTED);
4244
+ }
4245
+ return result;
4246
+ }
4247
+
4220
4248
  // src/db/memories.ts
4221
4249
  function parseMemoryRow(row) {
4222
4250
  return {
@@ -4254,6 +4282,8 @@ function createMemory(input, dedupeMode = "merge", db) {
4254
4282
  const tags = input.tags || [];
4255
4283
  const tagsJson = JSON.stringify(tags);
4256
4284
  const metadataJson = JSON.stringify(input.metadata || {});
4285
+ const safeValue = redactSecrets(input.value);
4286
+ const safeSummary = input.summary ? redactSecrets(input.summary) : null;
4257
4287
  if (dedupeMode === "merge") {
4258
4288
  const existing = d.query(`SELECT id, version FROM memories
4259
4289
  WHERE key = ? AND scope = ?
@@ -4267,9 +4297,9 @@ function createMemory(input, dedupeMode = "merge", db) {
4267
4297
  pinned = COALESCE(pinned, 0),
4268
4298
  version = version + 1, updated_at = ?
4269
4299
  WHERE id = ?`, [
4270
- input.value,
4300
+ safeValue,
4271
4301
  input.category || "knowledge",
4272
- input.summary || null,
4302
+ safeSummary,
4273
4303
  tagsJson,
4274
4304
  input.importance ?? 5,
4275
4305
  metadataJson,
@@ -4448,7 +4478,7 @@ function updateMemory(id, input, db) {
4448
4478
  const params = [now()];
4449
4479
  if (input.value !== undefined) {
4450
4480
  sets.push("value = ?");
4451
- params.push(input.value);
4481
+ params.push(redactSecrets(input.value));
4452
4482
  }
4453
4483
  if (input.category !== undefined) {
4454
4484
  sets.push("category = ?");
@@ -4906,7 +4936,7 @@ function formatMemory(m) {
4906
4936
  return parts.join(`
4907
4937
  `);
4908
4938
  }
4909
- server.tool("memory_save", "Save a memory (create or upsert). Use scope 'global' for all agents, 'shared' for project-level, 'private' for single agent.", {
4939
+ server.tool("memory_save", "Save/upsert a memory. scope: global=all agents, shared=project, private=single agent.", {
4910
4940
  key: exports_external.string().describe("Unique key for the memory"),
4911
4941
  value: exports_external.string().describe("Memory content/value"),
4912
4942
  scope: exports_external.enum(["global", "shared", "private"]).optional().describe("Memory scope (default: private)"),
@@ -4967,7 +4997,7 @@ ${formatMemory(best.memory)}`
4967
4997
  return { content: [{ type: "text", text: formatError(e) }], isError: true };
4968
4998
  }
4969
4999
  });
4970
- server.tool("memory_list", "List memories with optional filters", {
5000
+ server.tool("memory_list", "List memories. Default: compact lines. full=true for complete JSON objects.", {
4971
5001
  scope: exports_external.enum(["global", "shared", "private"]).optional(),
4972
5002
  category: exports_external.enum(["preference", "fact", "knowledge", "history"]).optional(),
4973
5003
  tags: exports_external.array(exports_external.string()).optional(),
@@ -4978,19 +5008,25 @@ server.tool("memory_list", "List memories with optional filters", {
4978
5008
  session_id: exports_external.string().optional(),
4979
5009
  status: exports_external.enum(["active", "archived", "expired"]).optional(),
4980
5010
  limit: exports_external.coerce.number().optional().describe("Max results (default: 50)"),
4981
- offset: exports_external.coerce.number().optional()
5011
+ offset: exports_external.coerce.number().optional(),
5012
+ full: exports_external.boolean().optional().describe("Return full Memory objects as JSON instead of compact lines")
4982
5013
  }, async (args) => {
4983
5014
  try {
5015
+ const { full, ...filterArgs } = args;
4984
5016
  const filter = {
4985
- ...args,
4986
- limit: args.limit || 50
5017
+ ...filterArgs,
5018
+ limit: filterArgs.limit || 50
4987
5019
  };
4988
5020
  const memories = listMemories(filter);
4989
5021
  if (memories.length === 0) {
4990
- return { content: [{ type: "text", text: "No memories found matching filters." }] };
5022
+ return { content: [{ type: "text", text: "No memories found." }] };
5023
+ }
5024
+ if (full) {
5025
+ const compact = memories.map((m) => Object.fromEntries(Object.entries(m).filter(([, v]) => v !== null && v !== undefined && v !== 0 && v !== "")));
5026
+ return { content: [{ type: "text", text: JSON.stringify(compact, null, 2) }] };
4991
5027
  }
4992
- const lines = memories.map((m, i) => `${i + 1}. [${m.scope}/${m.category}] ${m.key} = ${m.value.slice(0, 100)}${m.value.length > 100 ? "..." : ""} (importance: ${m.importance}, id: ${m.id.slice(0, 8)})`);
4993
- return { content: [{ type: "text", text: `${memories.length} memor${memories.length === 1 ? "y" : "ies"} found:
5028
+ const lines = memories.map((m, i) => `${i + 1}. [${m.scope}/${m.category}] ${m.key} = ${m.value.slice(0, 100)}${m.value.length > 100 ? "..." : ""} (imp:${m.importance} id:${m.id.slice(0, 8)})`);
5029
+ return { content: [{ type: "text", text: `${memories.length} memories:
4994
5030
  ${lines.join(`
4995
5031
  `)}` }] };
4996
5032
  } catch (e) {
@@ -5165,7 +5201,7 @@ server.tool("memory_import", "Import memories from JSON array", {
5165
5201
  return { content: [{ type: "text", text: formatError(e) }], isError: true };
5166
5202
  }
5167
5203
  });
5168
- server.tool("memory_inject", "Get formatted memory context for injection into agent system prompts. Selects most relevant memories by scope, importance, and recency.", {
5204
+ server.tool("memory_inject", "Get memory context for system prompt injection. Selects by scope, importance, recency.", {
5169
5205
  agent_id: exports_external.string().optional().describe("Agent ID for scope filtering"),
5170
5206
  project_id: exports_external.string().optional().describe("Project ID for scope filtering"),
5171
5207
  session_id: exports_external.string().optional().describe("Session ID for scope filtering"),
@@ -5244,7 +5280,7 @@ ${lines.join(`
5244
5280
  return { content: [{ type: "text", text: formatError(e) }], isError: true };
5245
5281
  }
5246
5282
  });
5247
- server.tool("register_agent", "Register an agent and get a short UUID. Idempotent: same name returns existing agent.", {
5283
+ server.tool("register_agent", "Register an agent. Idempotent \u2014 same name returns existing agent.", {
5248
5284
  name: exports_external.string().describe("Agent name"),
5249
5285
  description: exports_external.string().optional().describe("Agent description"),
5250
5286
  role: exports_external.string().optional().describe("Agent role")
@@ -5304,7 +5340,7 @@ Last seen: ${agent.last_seen_at}`
5304
5340
  return { content: [{ type: "text", text: formatError(e) }], isError: true };
5305
5341
  }
5306
5342
  });
5307
- server.tool("update_agent", "Update an agent's name, description, role, or metadata. Agents can update themselves.", {
5343
+ server.tool("update_agent", "Update agent name, description, role, or metadata.", {
5308
5344
  id: exports_external.string().describe("Agent ID or name"),
5309
5345
  name: exports_external.string().optional().describe("New agent name"),
5310
5346
  description: exports_external.string().optional().describe("New description"),
@@ -5412,7 +5448,7 @@ server.tool("clean_expired", "Remove expired memories from the database", {}, as
5412
5448
  return { content: [{ type: "text", text: formatError(e) }], isError: true };
5413
5449
  }
5414
5450
  });
5415
- server.tool("memory_context", "Get all memories relevant to the current context. Smart selection by scope visibility, importance, and recency.", {
5451
+ server.tool("memory_context", "Get memories relevant to current context, filtered by scope/importance/recency.", {
5416
5452
  agent_id: exports_external.string().optional(),
5417
5453
  project_id: exports_external.string().optional(),
5418
5454
  scope: exports_external.enum(["global", "shared", "private"]).optional().describe("Limit to specific scope"),
@@ -217,6 +217,34 @@ function shortUuid() {
217
217
  return crypto.randomUUID().slice(0, 8);
218
218
  }
219
219
 
220
+ // src/lib/redact.ts
221
+ var REDACTED = "[REDACTED]";
222
+ var SECRET_PATTERNS = [
223
+ { name: "openai_key", pattern: /sk-[a-zA-Z0-9_-]{20,}/g },
224
+ { name: "anthropic_key", pattern: /sk-ant-[a-zA-Z0-9_-]{20,}/g },
225
+ { name: "generic_key", pattern: /(?:pk|tok|key|token|api[_-]?key)[_-][a-zA-Z0-9_-]{16,}/gi },
226
+ { name: "aws_key", pattern: /AKIA[A-Z0-9]{16}/g },
227
+ { name: "aws_secret", pattern: /(?<=AWS_SECRET_ACCESS_KEY\s*=\s*)[A-Za-z0-9/+=]{40}/g },
228
+ { name: "github_token", pattern: /gh[ps]_[a-zA-Z0-9]{36,}/g },
229
+ { name: "github_oauth", pattern: /gho_[a-zA-Z0-9]{36,}/g },
230
+ { name: "npm_token", pattern: /npm_[a-zA-Z0-9]{36,}/g },
231
+ { name: "bearer", pattern: /Bearer\s+[a-zA-Z0-9_\-.]{20,}/g },
232
+ { name: "conn_string", pattern: /(?:postgres|postgresql|mysql|mongodb|redis|amqp|mqtt):\/\/[^\s"'`]+@[^\s"'`]+/gi },
233
+ { name: "env_secret", pattern: /(?:SECRET|TOKEN|PASSWORD|PASSPHRASE|API_KEY|PRIVATE_KEY|AUTH|CREDENTIAL)[_A-Z]*\s*=\s*["']?[^\s"'\n]{8,}["']?/gi },
234
+ { name: "stripe_key", pattern: /(?:sk|pk|rk)_(?:test|live)_[a-zA-Z0-9]{20,}/g },
235
+ { name: "slack_token", pattern: /xox[bpras]-[a-zA-Z0-9-]{20,}/g },
236
+ { name: "jwt", pattern: /eyJ[a-zA-Z0-9_-]{10,}\.eyJ[a-zA-Z0-9_-]{10,}\.[a-zA-Z0-9_-]{10,}/g },
237
+ { name: "hex_secret", pattern: /(?<=(?:key|token|secret|password|hash)\s*[:=]\s*["']?)[0-9a-f]{32,}(?=["']?)/gi }
238
+ ];
239
+ function redactSecrets(text) {
240
+ let result = text;
241
+ for (const { pattern } of SECRET_PATTERNS) {
242
+ pattern.lastIndex = 0;
243
+ result = result.replace(pattern, REDACTED);
244
+ }
245
+ return result;
246
+ }
247
+
220
248
  // src/db/memories.ts
221
249
  function parseMemoryRow(row) {
222
250
  return {
@@ -254,6 +282,8 @@ function createMemory(input, dedupeMode = "merge", db) {
254
282
  const tags = input.tags || [];
255
283
  const tagsJson = JSON.stringify(tags);
256
284
  const metadataJson = JSON.stringify(input.metadata || {});
285
+ const safeValue = redactSecrets(input.value);
286
+ const safeSummary = input.summary ? redactSecrets(input.summary) : null;
257
287
  if (dedupeMode === "merge") {
258
288
  const existing = d.query(`SELECT id, version FROM memories
259
289
  WHERE key = ? AND scope = ?
@@ -267,9 +297,9 @@ function createMemory(input, dedupeMode = "merge", db) {
267
297
  pinned = COALESCE(pinned, 0),
268
298
  version = version + 1, updated_at = ?
269
299
  WHERE id = ?`, [
270
- input.value,
300
+ safeValue,
271
301
  input.category || "knowledge",
272
- input.summary || null,
302
+ safeSummary,
273
303
  tagsJson,
274
304
  input.importance ?? 5,
275
305
  metadataJson,
@@ -422,7 +452,7 @@ function updateMemory(id, input, db) {
422
452
  const params = [now()];
423
453
  if (input.value !== undefined) {
424
454
  sets.push("value = ?");
425
- params.push(input.value);
455
+ params.push(redactSecrets(input.value));
426
456
  }
427
457
  if (input.category !== undefined) {
428
458
  sets.push("category = ?");
@@ -121,6 +121,8 @@ export interface MementosConfig {
121
121
  auto_cleanup: {
122
122
  enabled: boolean;
123
123
  expired_check_interval: number;
124
+ unused_archive_days: number;
125
+ stale_deprioritize_days: number;
124
126
  };
125
127
  }
126
128
  export type DedupeMode = "merge" | "create";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/mementos",
3
- "version": "0.2.0",
3
+ "version": "0.3.1",
4
4
  "description": "Universal memory system for AI agents - CLI + MCP server + library API",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",