@hasna/mementos 0.14.69 → 0.14.71
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/README.md +155 -73
- package/dist/cli/commands/storage.d.ts.map +1 -1
- package/dist/cli/commands/system-mcp.d.ts.map +1 -1
- package/dist/cli/commands/system-profile.d.ts.map +1 -1
- package/dist/cli/index.js +200 -63
- package/dist/db/__fixtures__/fail-closed-stub-server.d.ts.map +1 -1
- package/dist/db/agents.d.ts.map +1 -1
- package/dist/db/database.d.ts +16 -0
- package/dist/db/database.d.ts.map +1 -1
- package/dist/db/memories.d.ts.map +1 -1
- package/dist/db/migrations.d.ts +1 -0
- package/dist/db/migrations.d.ts.map +1 -1
- package/dist/db/pg-migrations.d.ts.map +1 -1
- package/dist/index.js +116 -42
- package/dist/lib/auto-memory-queue.d.ts +2 -0
- package/dist/lib/auto-memory-queue.d.ts.map +1 -1
- package/dist/lib/auto-memory.d.ts +1 -0
- package/dist/lib/auto-memory.d.ts.map +1 -1
- package/dist/lib/built-in-hooks.d.ts.map +1 -1
- package/dist/lib/gdpr.d.ts +17 -2
- package/dist/lib/gdpr.d.ts.map +1 -1
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +166 -55
- package/dist/mcp/tools/system-tools-memory-admin.d.ts.map +1 -1
- package/dist/server/index.js +119 -42
- package/dist/storage.d.ts +11 -2
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +42 -11
- package/package.json +1 -1
package/dist/mcp/index.js
CHANGED
|
@@ -145,6 +145,27 @@ var init_types = __esm(() => {
|
|
|
145
145
|
};
|
|
146
146
|
});
|
|
147
147
|
|
|
148
|
+
// src/generated/storage-kit/mode.ts
|
|
149
|
+
function normalizeStorageMode(value) {
|
|
150
|
+
const normalized = value.trim().toLowerCase().replace(/-/g, "_");
|
|
151
|
+
if (normalized === "local")
|
|
152
|
+
return { mode: "local", deprecatedAlias: null };
|
|
153
|
+
if (normalized === "cloud")
|
|
154
|
+
return { mode: "cloud", deprecatedAlias: null };
|
|
155
|
+
if (DEPRECATED_STORAGE_MODE_ALIASES.includes(normalized)) {
|
|
156
|
+
return { mode: "cloud", deprecatedAlias: normalized };
|
|
157
|
+
}
|
|
158
|
+
throw new Error(`Unknown storage mode: ${value}. Use local or cloud.`);
|
|
159
|
+
}
|
|
160
|
+
var DEPRECATED_STORAGE_MODE_ALIASES;
|
|
161
|
+
var init_mode = __esm(() => {
|
|
162
|
+
DEPRECATED_STORAGE_MODE_ALIASES = [
|
|
163
|
+
"remote",
|
|
164
|
+
"hybrid",
|
|
165
|
+
"self_hosted"
|
|
166
|
+
];
|
|
167
|
+
});
|
|
168
|
+
|
|
148
169
|
// src/storage.ts
|
|
149
170
|
import { Database } from "bun:sqlite";
|
|
150
171
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
@@ -403,18 +424,20 @@ function warnDeprecatedStorageMode(alias) {
|
|
|
403
424
|
warnedDeprecatedModes.add(alias);
|
|
404
425
|
process.emitWarning(`${MEMENTOS_STORAGE_ENV.mode}="${alias}" is deprecated; use "cloud". ` + `"${alias}" now maps to pure-remote cloud storage. The local<->remote ` + `sync path is deprecated and is not the fleet cutover path.`, { type: "DeprecationWarning", code: "MEMENTOS_STORAGE_MODE_ALIAS" });
|
|
405
426
|
}
|
|
406
|
-
function
|
|
407
|
-
if (!value)
|
|
427
|
+
function normalizeStorageMode2(value, source) {
|
|
428
|
+
if (!value || !value.trim())
|
|
408
429
|
return null;
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
430
|
+
let normalized;
|
|
431
|
+
try {
|
|
432
|
+
normalized = normalizeStorageMode(value);
|
|
433
|
+
} catch (error) {
|
|
434
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
435
|
+
throw new Error(`mementos: ${source}=${value} is not a valid mode. ${detail}`);
|
|
412
436
|
}
|
|
413
|
-
if (normalized
|
|
414
|
-
warnDeprecatedStorageMode(normalized);
|
|
415
|
-
return "cloud";
|
|
437
|
+
if (normalized.deprecatedAlias) {
|
|
438
|
+
warnDeprecatedStorageMode(normalized.deprecatedAlias);
|
|
416
439
|
}
|
|
417
|
-
return
|
|
440
|
+
return normalized.mode;
|
|
418
441
|
}
|
|
419
442
|
function readConfigFile() {
|
|
420
443
|
if (!existsSync(STORAGE_CONFIG_PATH)) {
|
|
@@ -444,7 +467,7 @@ function getStorageDatabaseUrl() {
|
|
|
444
467
|
}
|
|
445
468
|
function getStorageModeOverride() {
|
|
446
469
|
for (const env of MODE_ENV_NAMES) {
|
|
447
|
-
const value =
|
|
470
|
+
const value = normalizeStorageMode2(readEnv(env.name) ?? undefined, env.name);
|
|
448
471
|
if (value)
|
|
449
472
|
return value;
|
|
450
473
|
}
|
|
@@ -454,7 +477,7 @@ function getStorageConfig() {
|
|
|
454
477
|
const fileConfig = readConfigFile();
|
|
455
478
|
const modeOverride = getStorageModeOverride();
|
|
456
479
|
const envConnectionString = getConfiguredConnectionString();
|
|
457
|
-
const fileMode =
|
|
480
|
+
const fileMode = normalizeStorageMode2(fileConfig.mode, `${STORAGE_CONFIG_PATH} "mode"`);
|
|
458
481
|
const merged = {
|
|
459
482
|
...DEFAULT_STORAGE_CONFIG,
|
|
460
483
|
...fileConfig,
|
|
@@ -865,6 +888,7 @@ CREATE TABLE IF NOT EXISTS _sync_meta (
|
|
|
865
888
|
direction TEXT DEFAULT 'push'
|
|
866
889
|
)`;
|
|
867
890
|
var init_storage = __esm(() => {
|
|
891
|
+
init_mode();
|
|
868
892
|
PgSyncPool = class PgSyncPool {
|
|
869
893
|
worker;
|
|
870
894
|
status;
|
|
@@ -1216,7 +1240,24 @@ var init_api_mode = __esm(() => {
|
|
|
1216
1240
|
});
|
|
1217
1241
|
|
|
1218
1242
|
// src/db/migrations.ts
|
|
1219
|
-
var
|
|
1243
|
+
var MEMORY_VERSION_SNAPSHOT_TRIGGER = `
|
|
1244
|
+
CREATE TRIGGER IF NOT EXISTS memories_version_snapshot
|
|
1245
|
+
BEFORE UPDATE ON memories
|
|
1246
|
+
WHEN NEW.version > OLD.version
|
|
1247
|
+
BEGIN
|
|
1248
|
+
INSERT OR IGNORE INTO memory_versions (
|
|
1249
|
+
id, memory_id, version, value, importance, scope, category, tags,
|
|
1250
|
+
summary, pinned, status, when_to_use, created_at
|
|
1251
|
+
) VALUES (
|
|
1252
|
+
lower(hex(randomblob(4))) || '-' || lower(hex(randomblob(2))) || '-' ||
|
|
1253
|
+
lower(hex(randomblob(2))) || '-' || lower(hex(randomblob(2))) || '-' ||
|
|
1254
|
+
lower(hex(randomblob(6))),
|
|
1255
|
+
OLD.id, OLD.version, OLD.value, OLD.importance, OLD.scope, OLD.category,
|
|
1256
|
+
OLD.tags, OLD.summary, OLD.pinned, OLD.status, OLD.when_to_use,
|
|
1257
|
+
OLD.updated_at
|
|
1258
|
+
);
|
|
1259
|
+
END;
|
|
1260
|
+
`, MIGRATIONS;
|
|
1220
1261
|
var init_migrations = __esm(() => {
|
|
1221
1262
|
MIGRATIONS = [
|
|
1222
1263
|
`
|
|
@@ -2114,6 +2155,10 @@ CREATE INDEX IF NOT EXISTS idx_memory_reflection_lessons_memory ON memory_reflec
|
|
|
2114
2155
|
CREATE INDEX IF NOT EXISTS idx_memory_reflection_lessons_kind ON memory_reflection_lessons(kind);
|
|
2115
2156
|
|
|
2116
2157
|
INSERT OR IGNORE INTO _migrations (id) VALUES (35);
|
|
2158
|
+
`,
|
|
2159
|
+
`
|
|
2160
|
+
${MEMORY_VERSION_SNAPSHOT_TRIGGER}
|
|
2161
|
+
INSERT OR IGNORE INTO _migrations (id) VALUES (36);
|
|
2117
2162
|
`
|
|
2118
2163
|
];
|
|
2119
2164
|
});
|
|
@@ -2128,6 +2173,7 @@ __export(exports_database, {
|
|
|
2128
2173
|
now: () => now,
|
|
2129
2174
|
getDbPath: () => getDbPath,
|
|
2130
2175
|
getDatabase: () => getDatabase,
|
|
2176
|
+
escapeLikePrefix: () => escapeLikePrefix,
|
|
2131
2177
|
closeDatabase: () => closeDatabase
|
|
2132
2178
|
});
|
|
2133
2179
|
import { existsSync as existsSync2, mkdirSync as mkdirSync2, cpSync } from "fs";
|
|
@@ -2302,15 +2348,20 @@ function uuid() {
|
|
|
2302
2348
|
function shortUuid() {
|
|
2303
2349
|
return crypto.randomUUID().slice(0, 8);
|
|
2304
2350
|
}
|
|
2351
|
+
function escapeLikePrefix(s) {
|
|
2352
|
+
return s.replace(/\\/g, "\\\\").replace(/%/g, "\\%").replace(/_/g, "\\_");
|
|
2353
|
+
}
|
|
2305
2354
|
function resolvePartialId(db, table, partialId) {
|
|
2306
2355
|
if (!ALLOWED_TABLES.has(table)) {
|
|
2307
2356
|
throw new Error(`Invalid table name: ${table}`);
|
|
2308
2357
|
}
|
|
2358
|
+
if (partialId === "")
|
|
2359
|
+
return null;
|
|
2309
2360
|
if (partialId.length >= 36) {
|
|
2310
2361
|
const row = db.query(`SELECT id FROM ${table} WHERE id = ?`).get(partialId);
|
|
2311
2362
|
return row?.id ?? null;
|
|
2312
2363
|
}
|
|
2313
|
-
const rows = db.query(`SELECT id FROM ${table} WHERE id LIKE
|
|
2364
|
+
const rows = db.query(`SELECT id FROM ${table} WHERE id LIKE ? ESCAPE '\\'`).all(`${escapeLikePrefix(partialId)}%`);
|
|
2314
2365
|
if (rows.length === 1) {
|
|
2315
2366
|
return rows[0].id;
|
|
2316
2367
|
}
|
|
@@ -3372,33 +3423,19 @@ function updateMemory(id, input, db) {
|
|
|
3372
3423
|
const { status, data } = apiJson("PATCH", `/memories/${encodeURIComponent(id)}`, input, { allow404: true });
|
|
3373
3424
|
if (status === 404)
|
|
3374
3425
|
throw new MemoryNotFoundError(id);
|
|
3426
|
+
if (data && typeof input.version === "number" && typeof data.version === "number" && data.version <= input.version) {
|
|
3427
|
+
throw new Error(`Update did not persist for memory ${id}: the server returned success but the record is unchanged ` + `(version still ${data.version}). Your data was NOT written. ` + `The server is likely running a build predating the partial-id fix \u2014 pass the full 36-character id as a workaround.`);
|
|
3428
|
+
}
|
|
3375
3429
|
return data;
|
|
3376
3430
|
}
|
|
3377
3431
|
const d = db || getDatabase();
|
|
3378
3432
|
const existing = getMemory(id, d);
|
|
3379
3433
|
if (!existing)
|
|
3380
3434
|
throw new MemoryNotFoundError(id);
|
|
3435
|
+
const memoryId = existing.id;
|
|
3381
3436
|
if (existing.version !== input.version) {
|
|
3382
3437
|
throw new VersionConflictError(id, input.version, existing.version);
|
|
3383
3438
|
}
|
|
3384
|
-
try {
|
|
3385
|
-
d.run(`INSERT OR IGNORE INTO memory_versions (id, memory_id, version, value, importance, scope, category, tags, summary, pinned, status, when_to_use, created_at)
|
|
3386
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
3387
|
-
uuid(),
|
|
3388
|
-
existing.id,
|
|
3389
|
-
existing.version,
|
|
3390
|
-
existing.value,
|
|
3391
|
-
existing.importance,
|
|
3392
|
-
existing.scope,
|
|
3393
|
-
existing.category,
|
|
3394
|
-
JSON.stringify(existing.tags),
|
|
3395
|
-
existing.summary,
|
|
3396
|
-
existing.pinned ? 1 : 0,
|
|
3397
|
-
existing.status,
|
|
3398
|
-
existing.when_to_use || null,
|
|
3399
|
-
existing.updated_at
|
|
3400
|
-
]);
|
|
3401
|
-
} catch {}
|
|
3402
3439
|
const sets = ["version = version + 1", "updated_at = ?"];
|
|
3403
3440
|
const params = [now()];
|
|
3404
3441
|
if (input.value !== undefined) {
|
|
@@ -3448,15 +3485,18 @@ function updateMemory(id, input, db) {
|
|
|
3448
3485
|
if (input.tags !== undefined) {
|
|
3449
3486
|
sets.push("tags = ?");
|
|
3450
3487
|
params.push(JSON.stringify(input.tags));
|
|
3451
|
-
d.run("DELETE FROM memory_tags WHERE memory_id = ?", [
|
|
3488
|
+
d.run("DELETE FROM memory_tags WHERE memory_id = ?", [memoryId]);
|
|
3452
3489
|
const insertTag = d.prepare("INSERT OR IGNORE INTO memory_tags (memory_id, tag) VALUES (?, ?)");
|
|
3453
3490
|
for (const tag of input.tags) {
|
|
3454
|
-
insertTag.run(
|
|
3491
|
+
insertTag.run(memoryId, tag);
|
|
3455
3492
|
}
|
|
3456
3493
|
}
|
|
3457
|
-
params.push(
|
|
3458
|
-
d.run(`UPDATE memories SET ${sets.join(", ")} WHERE id = ?`, params);
|
|
3459
|
-
|
|
3494
|
+
params.push(memoryId);
|
|
3495
|
+
const result = d.run(`UPDATE memories SET ${sets.join(", ")} WHERE id = ?`, params);
|
|
3496
|
+
if (result.changes === 0) {
|
|
3497
|
+
throw new Error(`Update affected no rows for memory ${memoryId}: the record was read but not written. ` + `This is a bug in @hasna/mementos, not a bad argument \u2014 please report it.`);
|
|
3498
|
+
}
|
|
3499
|
+
const updated = getMemory(memoryId, d);
|
|
3460
3500
|
if (input.value !== undefined) {
|
|
3461
3501
|
try {
|
|
3462
3502
|
const oldLinks = getEntityMemoryLinks(undefined, updated.id, d);
|
|
@@ -3481,10 +3521,11 @@ function deleteMemory(id, db) {
|
|
|
3481
3521
|
return status !== 404;
|
|
3482
3522
|
}
|
|
3483
3523
|
const d = db || getDatabase();
|
|
3484
|
-
const
|
|
3524
|
+
const memoryId = resolvePartialId(d, "memories", id) ?? id;
|
|
3525
|
+
const result = d.run("DELETE FROM memories WHERE id = ?", [memoryId]);
|
|
3485
3526
|
if (result.changes > 0) {
|
|
3486
3527
|
hookRegistry.runHooks("PostMemoryDelete", {
|
|
3487
|
-
memoryId
|
|
3528
|
+
memoryId,
|
|
3488
3529
|
timestamp: Date.now()
|
|
3489
3530
|
});
|
|
3490
3531
|
}
|
|
@@ -3498,11 +3539,12 @@ function bulkDeleteMemories(ids, db) {
|
|
|
3498
3539
|
return data?.deleted ?? 0;
|
|
3499
3540
|
}
|
|
3500
3541
|
const d = db || getDatabase();
|
|
3501
|
-
const
|
|
3502
|
-
const
|
|
3542
|
+
const resolvedIds = ids.map((id) => resolvePartialId(d, "memories", id) ?? id);
|
|
3543
|
+
const placeholders = resolvedIds.map(() => "?").join(",");
|
|
3544
|
+
const countRow = d.query(`SELECT COUNT(*) as c FROM memories WHERE id IN (${placeholders})`).get(...resolvedIds);
|
|
3503
3545
|
const count = countRow.c;
|
|
3504
3546
|
if (count > 0) {
|
|
3505
|
-
d.run(`DELETE FROM memories WHERE id IN (${placeholders})`,
|
|
3547
|
+
d.run(`DELETE FROM memories WHERE id IN (${placeholders})`, resolvedIds);
|
|
3506
3548
|
}
|
|
3507
3549
|
return count;
|
|
3508
3550
|
}
|
|
@@ -5704,6 +5746,32 @@ class AutoMemoryQueue {
|
|
|
5704
5746
|
getStats() {
|
|
5705
5747
|
return { ...this.stats, pending: this.queue.length };
|
|
5706
5748
|
}
|
|
5749
|
+
async waitForIdleForTests(timeoutMs = 3000) {
|
|
5750
|
+
const start = Date.now();
|
|
5751
|
+
while (Date.now() - start < timeoutMs) {
|
|
5752
|
+
if (this.queue.length === 0 && this.activeCount === 0)
|
|
5753
|
+
return;
|
|
5754
|
+
await new Promise((r) => setTimeout(r, 20));
|
|
5755
|
+
}
|
|
5756
|
+
throw new Error("autoMemoryQueue did not become idle before test reset");
|
|
5757
|
+
}
|
|
5758
|
+
resetForTests(handler) {
|
|
5759
|
+
if (this.activeCount !== 0) {
|
|
5760
|
+
throw new Error("Cannot reset autoMemoryQueue while jobs are processing");
|
|
5761
|
+
}
|
|
5762
|
+
this.queue = [];
|
|
5763
|
+
this.running = false;
|
|
5764
|
+
this.stats = {
|
|
5765
|
+
pending: 0,
|
|
5766
|
+
processing: 0,
|
|
5767
|
+
processed: 0,
|
|
5768
|
+
failed: 0,
|
|
5769
|
+
dropped: 0
|
|
5770
|
+
};
|
|
5771
|
+
if (handler !== undefined) {
|
|
5772
|
+
this.handler = handler;
|
|
5773
|
+
}
|
|
5774
|
+
}
|
|
5707
5775
|
startLoop() {
|
|
5708
5776
|
this.running = true;
|
|
5709
5777
|
this.loop();
|
|
@@ -5749,6 +5817,7 @@ var init_auto_memory_queue = __esm(() => {
|
|
|
5749
5817
|
// src/lib/auto-memory.ts
|
|
5750
5818
|
var exports_auto_memory = {};
|
|
5751
5819
|
__export(exports_auto_memory, {
|
|
5820
|
+
resetAutoMemoryForTests: () => resetAutoMemoryForTests,
|
|
5752
5821
|
processConversationTurn: () => processConversationTurn,
|
|
5753
5822
|
getAutoMemoryStats: () => getAutoMemoryStats,
|
|
5754
5823
|
configureAutoMemory: () => configureAutoMemory
|
|
@@ -5909,6 +5978,12 @@ function getAutoMemoryStats() {
|
|
|
5909
5978
|
function configureAutoMemory(config) {
|
|
5910
5979
|
providerRegistry.configure(config);
|
|
5911
5980
|
}
|
|
5981
|
+
async function resetAutoMemoryForTests() {
|
|
5982
|
+
if (autoMemoryQueue.getStats().processing > 0) {
|
|
5983
|
+
await autoMemoryQueue.waitForIdleForTests();
|
|
5984
|
+
}
|
|
5985
|
+
autoMemoryQueue.resetForTests(processJob);
|
|
5986
|
+
}
|
|
5912
5987
|
var DEDUP_SIMILARITY_THRESHOLD = 0.85;
|
|
5913
5988
|
var init_auto_memory = __esm(() => {
|
|
5914
5989
|
init_memories();
|
|
@@ -6597,6 +6672,8 @@ var init_built_in_hooks = __esm(() => {
|
|
|
6597
6672
|
priority: 100,
|
|
6598
6673
|
description: "Trigger async LLM entity extraction when a memory is saved",
|
|
6599
6674
|
handler: async (ctx) => {
|
|
6675
|
+
if (process.env["NODE_ENV"] === "test")
|
|
6676
|
+
return;
|
|
6600
6677
|
if (ctx.wasUpdated)
|
|
6601
6678
|
return;
|
|
6602
6679
|
const processConversationTurn2 = await getAutoMemory();
|
|
@@ -11971,11 +12048,14 @@ __export(exports_gdpr, {
|
|
|
11971
12048
|
});
|
|
11972
12049
|
function gdprErase(identifier, options = {}, db) {
|
|
11973
12050
|
const d = db || getDatabase();
|
|
12051
|
+
if (identifier.trim() === "") {
|
|
12052
|
+
throw new Error("GDPR erase requires a non-empty identifier: an empty or whitespace-only " + "identifier matches every memory and would redact the entire store");
|
|
12053
|
+
}
|
|
11974
12054
|
const timestamp = now();
|
|
11975
12055
|
const conditions = [
|
|
11976
|
-
"(key LIKE ? OR value LIKE ? OR summary LIKE ? OR tags LIKE ? OR metadata LIKE ?)"
|
|
12056
|
+
"(key LIKE ? ESCAPE '\\' OR value LIKE ? ESCAPE '\\' OR summary LIKE ? ESCAPE '\\' OR tags LIKE ? ESCAPE '\\' OR metadata LIKE ? ESCAPE '\\')"
|
|
11977
12057
|
];
|
|
11978
|
-
const searchParam = `%${identifier}%`;
|
|
12058
|
+
const searchParam = `%${escapeLikePrefix(identifier)}%`;
|
|
11979
12059
|
const params = [searchParam, searchParam, searchParam, searchParam, searchParam];
|
|
11980
12060
|
if (options.project_id) {
|
|
11981
12061
|
conditions.push("project_id = ?");
|
|
@@ -11994,18 +12074,23 @@ function gdprErase(identifier, options = {}, db) {
|
|
|
11994
12074
|
timestamp
|
|
11995
12075
|
};
|
|
11996
12076
|
}
|
|
11997
|
-
const memoryIds =
|
|
11998
|
-
|
|
11999
|
-
|
|
12077
|
+
const memoryIds = d.transaction(() => {
|
|
12078
|
+
const ids = [];
|
|
12079
|
+
for (const row of rows) {
|
|
12080
|
+
const redactedKey = `[REDACTED]:${crypto.randomUUID()}`;
|
|
12081
|
+
d.run(`UPDATE memories SET
|
|
12082
|
+
key = ?,
|
|
12000
12083
|
value = '[REDACTED]',
|
|
12001
12084
|
summary = NULL,
|
|
12002
12085
|
tags = '[]',
|
|
12003
12086
|
metadata = '{}',
|
|
12004
12087
|
updated_at = ?
|
|
12005
|
-
WHERE id = ?`, [timestamp, row.id]);
|
|
12006
|
-
|
|
12007
|
-
|
|
12008
|
-
|
|
12088
|
+
WHERE id = ?`, [redactedKey, timestamp, row.id]);
|
|
12089
|
+
d.run("DELETE FROM memory_tags WHERE memory_id = ?", [row.id]);
|
|
12090
|
+
ids.push(row.id);
|
|
12091
|
+
}
|
|
12092
|
+
return ids;
|
|
12093
|
+
});
|
|
12009
12094
|
return {
|
|
12010
12095
|
erased_count: memoryIds.length,
|
|
12011
12096
|
memory_ids: memoryIds,
|
|
@@ -12897,6 +12982,31 @@ var init_pg_migrations = __esm(() => {
|
|
|
12897
12982
|
);
|
|
12898
12983
|
CREATE INDEX IF NOT EXISTS idx_task_comments_task ON task_comments(task_id);
|
|
12899
12984
|
CREATE INDEX IF NOT EXISTS idx_task_comments_agent ON task_comments(agent_id);
|
|
12985
|
+
`,
|
|
12986
|
+
`
|
|
12987
|
+
CREATE OR REPLACE FUNCTION snapshot_memory_version() RETURNS trigger AS $$
|
|
12988
|
+
BEGIN
|
|
12989
|
+
INSERT INTO memory_versions (
|
|
12990
|
+
id, memory_id, version, value, importance, scope, category, tags,
|
|
12991
|
+
summary, pinned, status, when_to_use, created_at
|
|
12992
|
+
) VALUES (
|
|
12993
|
+
gen_random_uuid()::text,
|
|
12994
|
+
OLD.id, OLD.version, OLD.value, OLD.importance, OLD.scope, OLD.category,
|
|
12995
|
+
OLD.tags, OLD.summary, OLD.pinned, OLD.status, OLD.when_to_use,
|
|
12996
|
+
OLD.updated_at
|
|
12997
|
+
) ON CONFLICT DO NOTHING;
|
|
12998
|
+
RETURN NEW;
|
|
12999
|
+
END;
|
|
13000
|
+
$$ LANGUAGE plpgsql;
|
|
13001
|
+
|
|
13002
|
+
DROP TRIGGER IF EXISTS memories_version_snapshot ON memories;
|
|
13003
|
+
CREATE TRIGGER memories_version_snapshot
|
|
13004
|
+
BEFORE UPDATE ON memories
|
|
13005
|
+
FOR EACH ROW
|
|
13006
|
+
WHEN (NEW.version > OLD.version)
|
|
13007
|
+
EXECUTE FUNCTION snapshot_memory_version();
|
|
13008
|
+
|
|
13009
|
+
INSERT INTO _migrations (id) VALUES (36) ON CONFLICT DO NOTHING;
|
|
12900
13010
|
`
|
|
12901
13011
|
];
|
|
12902
13012
|
});
|
|
@@ -55710,7 +55820,7 @@ function getAgent(idOrName, db) {
|
|
|
55710
55820
|
row = d.query("SELECT * FROM agents WHERE LOWER(name) = ?").get(idOrName.trim().toLowerCase());
|
|
55711
55821
|
if (row)
|
|
55712
55822
|
return parseAgentRow(row);
|
|
55713
|
-
const rows = d.query("SELECT * FROM agents WHERE id LIKE ?").all(`${idOrName}%`);
|
|
55823
|
+
const rows = d.query("SELECT * FROM agents WHERE id LIKE ? ESCAPE '\\'").all(`${escapeLikePrefix(idOrName)}%`);
|
|
55714
55824
|
if (rows.length === 1)
|
|
55715
55825
|
return parseAgentRow(rows[0]);
|
|
55716
55826
|
return null;
|
|
@@ -63762,7 +63872,7 @@ ${lines.join(`
|
|
|
63762
63872
|
}
|
|
63763
63873
|
});
|
|
63764
63874
|
server.tool("memory_gdpr_erase", "GDPR right to be forgotten: erase all memories containing a PII identifier. Replaces content with [REDACTED], preserves anonymized audit trail. IRREVERSIBLE.", {
|
|
63765
|
-
identifier: z.string().describe("PII to search for and erase (name, email, etc.)"),
|
|
63875
|
+
identifier: z.string().min(1).describe("PII to search for and erase (name, email, etc.)"),
|
|
63766
63876
|
project_id: z.string().optional(),
|
|
63767
63877
|
dry_run: z.boolean().optional().describe("Preview what would be erased without actually erasing (default: false)")
|
|
63768
63878
|
}, async (args) => {
|
|
@@ -65427,11 +65537,12 @@ function hasFlag(...flags) {
|
|
|
65427
65537
|
function printHelp() {
|
|
65428
65538
|
process.stdout.write(`Usage: mementos-mcp [options]
|
|
65429
65539
|
|
|
65430
|
-
Mementos MCP server (
|
|
65540
|
+
Mementos MCP server (Streamable HTTP transport by default)
|
|
65431
65541
|
|
|
65432
65542
|
Options:
|
|
65433
|
-
--http Serve MCP over Streamable HTTP (127.0.0.1)
|
|
65434
|
-
--
|
|
65543
|
+
--http Serve MCP over Streamable HTTP (default, 127.0.0.1)
|
|
65544
|
+
--stdio Serve MCP over stdio (env: MCP_STDIO=1)
|
|
65545
|
+
--port <number> HTTP port (default: 8867, env: MCP_HTTP_PORT)
|
|
65435
65546
|
-h, --help Show help
|
|
65436
65547
|
-V, --version Show version
|
|
65437
65548
|
`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"system-tools-memory-admin.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/system-tools-memory-admin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAA6B,MAAM,0BAA0B,CAAC;AAI1F,wBAAgB,8BAA8B,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,iBAAiB,EAAE,EAAE,cAAc,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"system-tools-memory-admin.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/system-tools-memory-admin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAA6B,MAAM,0BAA0B,CAAC;AAI1F,wBAAgB,8BAA8B,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,iBAAiB,EAAE,EAAE,cAAc,GAAG,IAAI,CAwTtJ"}
|