@hasna/mementos 0.14.68 → 0.14.70
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/__fixtures__/clean-fallback-stub-server.d.ts +2 -0
- package/dist/cli/__fixtures__/clean-fallback-stub-server.d.ts.map +1 -0
- package/dist/cli/commands/io-clean.d.ts.map +1 -1
- package/dist/cli/commands/memory-cmd-crud.d.ts.map +1 -1
- 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/global-options.d.ts +27 -0
- package/dist/cli/global-options.d.ts.map +1 -0
- package/dist/cli/index.js +699 -301
- package/dist/cli/register-all.d.ts +17 -0
- package/dist/cli/register-all.d.ts.map +1 -0
- package/dist/cli/startup-side-effects.d.ts +9 -0
- package/dist/cli/startup-side-effects.d.ts.map +1 -0
- package/dist/db/__fixtures__/fail-closed-stub-server.d.ts +2 -0
- package/dist/db/__fixtures__/fail-closed-stub-server.d.ts.map +1 -0
- package/dist/db/agents.d.ts.map +1 -1
- package/dist/db/api-mode.d.ts +70 -2
- package/dist/db/api-mode.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/locks.d.ts.map +1 -1
- package/dist/db/memories.d.ts +24 -6
- 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/db/session-jobs.d.ts.map +1 -1
- package/dist/db/store-backend.d.ts +33 -0
- package/dist/db/store-backend.d.ts.map +1 -0
- package/dist/index.js +196 -62
- 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/enum-validation.d.ts +20 -0
- package/dist/lib/enum-validation.d.ts.map +1 -0
- package/dist/lib/gdpr.d.ts.map +1 -1
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +301 -78
- package/dist/mcp/tools/system-tools-memory-admin.d.ts.map +1 -1
- package/dist/server/helpers.d.ts +11 -0
- package/dist/server/helpers.d.ts.map +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +304 -72
- package/dist/storage.d.ts +11 -2
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +42 -11
- package/dist/test-support/preload-local-store.d.ts +2 -0
- package/dist/test-support/preload-local-store.d.ts.map +1 -0
- package/dist/test-support/store-isolation.d.ts +83 -0
- package/dist/test-support/store-isolation.d.ts.map +1 -0
- package/dist/types/index.d.ts +8 -4
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -46,6 +46,27 @@ var __export = (target, all) => {
|
|
|
46
46
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
47
47
|
var __require = import.meta.require;
|
|
48
48
|
|
|
49
|
+
// src/generated/storage-kit/mode.ts
|
|
50
|
+
function normalizeStorageMode(value) {
|
|
51
|
+
const normalized = value.trim().toLowerCase().replace(/-/g, "_");
|
|
52
|
+
if (normalized === "local")
|
|
53
|
+
return { mode: "local", deprecatedAlias: null };
|
|
54
|
+
if (normalized === "cloud")
|
|
55
|
+
return { mode: "cloud", deprecatedAlias: null };
|
|
56
|
+
if (DEPRECATED_STORAGE_MODE_ALIASES.includes(normalized)) {
|
|
57
|
+
return { mode: "cloud", deprecatedAlias: normalized };
|
|
58
|
+
}
|
|
59
|
+
throw new Error(`Unknown storage mode: ${value}. Use local or cloud.`);
|
|
60
|
+
}
|
|
61
|
+
var DEPRECATED_STORAGE_MODE_ALIASES;
|
|
62
|
+
var init_mode = __esm(() => {
|
|
63
|
+
DEPRECATED_STORAGE_MODE_ALIASES = [
|
|
64
|
+
"remote",
|
|
65
|
+
"hybrid",
|
|
66
|
+
"self_hosted"
|
|
67
|
+
];
|
|
68
|
+
});
|
|
69
|
+
|
|
49
70
|
// src/storage.ts
|
|
50
71
|
import { Database } from "bun:sqlite";
|
|
51
72
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
@@ -57,6 +78,12 @@ import pg from "pg";
|
|
|
57
78
|
function markServerContext() {
|
|
58
79
|
_serverContext = true;
|
|
59
80
|
}
|
|
81
|
+
function resetServerContextForTests() {
|
|
82
|
+
if (process.env["NODE_ENV"] !== "test") {
|
|
83
|
+
throw new Error("resetServerContextForTests is only available under NODE_ENV=test");
|
|
84
|
+
}
|
|
85
|
+
_serverContext = false;
|
|
86
|
+
}
|
|
60
87
|
function isServerContext() {
|
|
61
88
|
return _serverContext;
|
|
62
89
|
}
|
|
@@ -307,18 +334,20 @@ function warnDeprecatedStorageMode(alias) {
|
|
|
307
334
|
warnedDeprecatedModes.add(alias);
|
|
308
335
|
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" });
|
|
309
336
|
}
|
|
310
|
-
function
|
|
311
|
-
if (!value)
|
|
337
|
+
function normalizeStorageMode2(value, source) {
|
|
338
|
+
if (!value || !value.trim())
|
|
312
339
|
return null;
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
340
|
+
let normalized;
|
|
341
|
+
try {
|
|
342
|
+
normalized = normalizeStorageMode(value);
|
|
343
|
+
} catch (error) {
|
|
344
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
345
|
+
throw new Error(`mementos: ${source}=${value} is not a valid mode. ${detail}`);
|
|
316
346
|
}
|
|
317
|
-
if (normalized
|
|
318
|
-
warnDeprecatedStorageMode(normalized);
|
|
319
|
-
return "cloud";
|
|
347
|
+
if (normalized.deprecatedAlias) {
|
|
348
|
+
warnDeprecatedStorageMode(normalized.deprecatedAlias);
|
|
320
349
|
}
|
|
321
|
-
return
|
|
350
|
+
return normalized.mode;
|
|
322
351
|
}
|
|
323
352
|
function readConfigFile() {
|
|
324
353
|
if (!existsSync(STORAGE_CONFIG_PATH)) {
|
|
@@ -357,7 +386,7 @@ function getStorageDatabaseEnvName() {
|
|
|
357
386
|
}
|
|
358
387
|
function getStorageModeOverride() {
|
|
359
388
|
for (const env of MODE_ENV_NAMES) {
|
|
360
|
-
const value =
|
|
389
|
+
const value = normalizeStorageMode2(readEnv(env.name) ?? undefined, env.name);
|
|
361
390
|
if (value)
|
|
362
391
|
return value;
|
|
363
392
|
}
|
|
@@ -367,7 +396,7 @@ function getStorageConfig() {
|
|
|
367
396
|
const fileConfig = readConfigFile();
|
|
368
397
|
const modeOverride = getStorageModeOverride();
|
|
369
398
|
const envConnectionString = getConfiguredConnectionString();
|
|
370
|
-
const fileMode =
|
|
399
|
+
const fileMode = normalizeStorageMode2(fileConfig.mode, `${STORAGE_CONFIG_PATH} "mode"`);
|
|
371
400
|
const merged = {
|
|
372
401
|
...DEFAULT_STORAGE_CONFIG,
|
|
373
402
|
...fileConfig,
|
|
@@ -794,6 +823,7 @@ CREATE TABLE IF NOT EXISTS _sync_meta (
|
|
|
794
823
|
direction TEXT DEFAULT 'push'
|
|
795
824
|
)`;
|
|
796
825
|
var init_storage = __esm(() => {
|
|
826
|
+
init_mode();
|
|
797
827
|
PgSyncPool = class PgSyncPool {
|
|
798
828
|
worker;
|
|
799
829
|
status;
|
|
@@ -938,7 +968,7 @@ import { tmpdir } from "os";
|
|
|
938
968
|
import { join as join2 } from "path";
|
|
939
969
|
import { writeFileSync as writeFileSync2, unlinkSync } from "fs";
|
|
940
970
|
import { randomUUID } from "crypto";
|
|
941
|
-
function firstEnv(
|
|
971
|
+
function firstEnv(keys) {
|
|
942
972
|
for (const k of keys) {
|
|
943
973
|
const v = process.env[k]?.trim();
|
|
944
974
|
if (v)
|
|
@@ -946,8 +976,38 @@ function firstEnv(...keys) {
|
|
|
946
976
|
}
|
|
947
977
|
return;
|
|
948
978
|
}
|
|
979
|
+
function firstEnvKey(keys) {
|
|
980
|
+
for (const k of keys) {
|
|
981
|
+
if (process.env[k]?.trim())
|
|
982
|
+
return k;
|
|
983
|
+
}
|
|
984
|
+
return null;
|
|
985
|
+
}
|
|
949
986
|
function hasDatabaseUrl() {
|
|
950
|
-
return Boolean(firstEnv(
|
|
987
|
+
return Boolean(firstEnv(DATABASE_URL_ENV_KEYS));
|
|
988
|
+
}
|
|
989
|
+
function isLoopbackHost(rawHost) {
|
|
990
|
+
const host = rawHost.replace(/^\[/, "").replace(/\]$/, "").toLowerCase();
|
|
991
|
+
return host === "localhost" || host === "::1" || /^127\./.test(host);
|
|
992
|
+
}
|
|
993
|
+
function assertRequestAllowedUnderTest(baseUrl) {
|
|
994
|
+
if (process.env["NODE_ENV"] !== "test")
|
|
995
|
+
return;
|
|
996
|
+
if (process.env[ALLOW_REMOTE_API_IN_TESTS_ENV]?.trim())
|
|
997
|
+
return;
|
|
998
|
+
let host;
|
|
999
|
+
try {
|
|
1000
|
+
host = new URL(baseUrl).hostname;
|
|
1001
|
+
} catch {
|
|
1002
|
+
host = "";
|
|
1003
|
+
}
|
|
1004
|
+
if (host && isLoopbackHost(host))
|
|
1005
|
+
return;
|
|
1006
|
+
throw new Error("api-mode: REFUSING to make a cloud request from a test process \u2014 this would write to or read " + "from the SHARED PRODUCTION memory store, where test fixtures are indistinguishable from real " + `memories.
|
|
1007
|
+
` + ` host : ${host || "(unparseable base URL)"}
|
|
1008
|
+
` + ` how this happens: a selector set at module scope (after the bun test preload ran), or \`bun test\` ` + `invoked from a directory with no bunfig.toml so the preload never loaded.
|
|
1009
|
+
` + " fix : build the child/process env via src/test-support/store-isolation.ts, or point the " + `suite at a loopback stub.
|
|
1010
|
+
` + ` override : set ${ALLOW_REMOTE_API_IN_TESTS_ENV}=1 only for a test that must reach a remote endpoint.`);
|
|
951
1011
|
}
|
|
952
1012
|
function normalizeBase(raw) {
|
|
953
1013
|
let base = raw.trim().replace(/\/+$/, "");
|
|
@@ -955,9 +1015,24 @@ function normalizeBase(raw) {
|
|
|
955
1015
|
return base;
|
|
956
1016
|
return `${base}/v1`;
|
|
957
1017
|
}
|
|
1018
|
+
function assertUnambiguousStoreEnv() {
|
|
1019
|
+
if (firstEnvKey(DB_PATH_ENV_KEYS))
|
|
1020
|
+
return;
|
|
1021
|
+
if (hasDatabaseUrl())
|
|
1022
|
+
return;
|
|
1023
|
+
const urlKey = firstEnvKey(API_URL_ENV_KEYS);
|
|
1024
|
+
const keyKey = firstEnvKey(API_KEY_ENV_KEYS);
|
|
1025
|
+
if (urlKey && !keyKey) {
|
|
1026
|
+
throw new MementosStoreConfigError(`${urlKey} points at the cloud memory store but ${API_KEY_ENV_KEYS[0]} is not set. ` + `Refusing to serve the on-box SQLite store in its place, because it holds a different ` + `dataset. Set ${API_KEY_ENV_KEYS[0]} to reach the cloud store. If you meant to use the ` + `on-box SQLite store, unset ${urlKey} or set ${DB_PATH_ENV_KEYS[0]} explicitly.`);
|
|
1027
|
+
}
|
|
1028
|
+
if (keyKey && !urlKey) {
|
|
1029
|
+
throw new MementosStoreConfigError(`${keyKey} is set but ${API_URL_ENV_KEYS[0]} is not, so the cloud memory store cannot be ` + `reached. Refusing to serve the on-box SQLite store in its place, because it holds a ` + `different dataset. Set ${API_URL_ENV_KEYS[0]} to reach the cloud store. If you meant to ` + `use the on-box SQLite store, unset ${keyKey} or set ${DB_PATH_ENV_KEYS[0]} explicitly.`);
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
958
1032
|
function getApiConfig() {
|
|
959
|
-
|
|
960
|
-
const
|
|
1033
|
+
assertUnambiguousStoreEnv();
|
|
1034
|
+
const rawBase = firstEnv(API_URL_ENV_KEYS);
|
|
1035
|
+
const apiKey = firstEnv(API_KEY_ENV_KEYS);
|
|
961
1036
|
if (!rawBase || !apiKey)
|
|
962
1037
|
return null;
|
|
963
1038
|
return { baseUrl: normalizeBase(rawBase), apiKey };
|
|
@@ -971,6 +1046,7 @@ function apiRequestRaw(method, path, body) {
|
|
|
971
1046
|
const cfg = getApiConfig();
|
|
972
1047
|
if (!cfg)
|
|
973
1048
|
throw new Error("api-mode: not configured (HASNA_MEMENTOS_API_URL / HASNA_MEMENTOS_API_KEY)");
|
|
1049
|
+
assertRequestAllowedUnderTest(cfg.baseUrl);
|
|
974
1050
|
const url = `${cfg.baseUrl}${path.startsWith("/") ? path : `/${path}`}`;
|
|
975
1051
|
const hasBody = body !== undefined && body !== null;
|
|
976
1052
|
const timeout = process.env["HASNA_MEMENTOS_API_TIMEOUT"] || DEFAULT_TIMEOUT_S;
|
|
@@ -1037,13 +1113,13 @@ x-api-key: ${cfg.apiKey}
|
|
|
1037
1113
|
}
|
|
1038
1114
|
return { status, body: respBody };
|
|
1039
1115
|
}
|
|
1040
|
-
function apiJson(method, path, body) {
|
|
1116
|
+
function apiJson(method, path, body, options) {
|
|
1041
1117
|
const raw = apiRequestRaw(method, path, body);
|
|
1042
1118
|
if (raw.status >= 200 && raw.status < 300) {
|
|
1043
1119
|
const data = raw.body.trim() ? JSON.parse(raw.body) : undefined;
|
|
1044
1120
|
return { status: raw.status, data };
|
|
1045
1121
|
}
|
|
1046
|
-
if (raw.status === 404) {
|
|
1122
|
+
if (raw.status === 404 && options?.allow404) {
|
|
1047
1123
|
return { status: 404, data: undefined };
|
|
1048
1124
|
}
|
|
1049
1125
|
let msg = `mementos cloud ${method} ${path} \u2192 ${raw.status}`;
|
|
@@ -1075,8 +1151,19 @@ function toQuery(params) {
|
|
|
1075
1151
|
const s = sp.toString();
|
|
1076
1152
|
return s ? `?${s}` : "";
|
|
1077
1153
|
}
|
|
1078
|
-
var ApiRequestError, DEFAULT_TIMEOUT_S = "45";
|
|
1154
|
+
var API_URL_ENV_KEYS, API_KEY_ENV_KEYS, DATABASE_URL_ENV_KEYS, ALLOW_REMOTE_API_IN_TESTS_ENV = "MEMENTOS_ALLOW_REMOTE_API_IN_TESTS", DB_PATH_ENV_KEYS, MementosStoreConfigError, ApiRequestError, DEFAULT_TIMEOUT_S = "45";
|
|
1079
1155
|
var init_api_mode = __esm(() => {
|
|
1156
|
+
API_URL_ENV_KEYS = ["HASNA_MEMENTOS_API_URL", "MEMENTOS_API_URL"];
|
|
1157
|
+
API_KEY_ENV_KEYS = ["HASNA_MEMENTOS_API_KEY", "MEMENTOS_API_KEY"];
|
|
1158
|
+
DATABASE_URL_ENV_KEYS = ["HASNA_MEMENTOS_DATABASE_URL", "MEMENTOS_DATABASE_URL"];
|
|
1159
|
+
DB_PATH_ENV_KEYS = ["HASNA_MEMENTOS_DB_PATH", "MEMENTOS_DB_PATH"];
|
|
1160
|
+
MementosStoreConfigError = class MementosStoreConfigError extends Error {
|
|
1161
|
+
code = "MEMENTOS_STORE_CONFIG";
|
|
1162
|
+
constructor(message) {
|
|
1163
|
+
super(message);
|
|
1164
|
+
this.name = "MementosStoreConfigError";
|
|
1165
|
+
}
|
|
1166
|
+
};
|
|
1080
1167
|
ApiRequestError = class ApiRequestError extends Error {
|
|
1081
1168
|
status;
|
|
1082
1169
|
body;
|
|
@@ -1090,7 +1177,24 @@ var init_api_mode = __esm(() => {
|
|
|
1090
1177
|
});
|
|
1091
1178
|
|
|
1092
1179
|
// src/db/migrations.ts
|
|
1093
|
-
var
|
|
1180
|
+
var MEMORY_VERSION_SNAPSHOT_TRIGGER = `
|
|
1181
|
+
CREATE TRIGGER IF NOT EXISTS memories_version_snapshot
|
|
1182
|
+
BEFORE UPDATE ON memories
|
|
1183
|
+
WHEN NEW.version > OLD.version
|
|
1184
|
+
BEGIN
|
|
1185
|
+
INSERT OR IGNORE INTO memory_versions (
|
|
1186
|
+
id, memory_id, version, value, importance, scope, category, tags,
|
|
1187
|
+
summary, pinned, status, when_to_use, created_at
|
|
1188
|
+
) VALUES (
|
|
1189
|
+
lower(hex(randomblob(4))) || '-' || lower(hex(randomblob(2))) || '-' ||
|
|
1190
|
+
lower(hex(randomblob(2))) || '-' || lower(hex(randomblob(2))) || '-' ||
|
|
1191
|
+
lower(hex(randomblob(6))),
|
|
1192
|
+
OLD.id, OLD.version, OLD.value, OLD.importance, OLD.scope, OLD.category,
|
|
1193
|
+
OLD.tags, OLD.summary, OLD.pinned, OLD.status, OLD.when_to_use,
|
|
1194
|
+
OLD.updated_at
|
|
1195
|
+
);
|
|
1196
|
+
END;
|
|
1197
|
+
`, MIGRATIONS;
|
|
1094
1198
|
var init_migrations = __esm(() => {
|
|
1095
1199
|
MIGRATIONS = [
|
|
1096
1200
|
`
|
|
@@ -1988,6 +2092,10 @@ CREATE INDEX IF NOT EXISTS idx_memory_reflection_lessons_memory ON memory_reflec
|
|
|
1988
2092
|
CREATE INDEX IF NOT EXISTS idx_memory_reflection_lessons_kind ON memory_reflection_lessons(kind);
|
|
1989
2093
|
|
|
1990
2094
|
INSERT OR IGNORE INTO _migrations (id) VALUES (35);
|
|
2095
|
+
`,
|
|
2096
|
+
`
|
|
2097
|
+
${MEMORY_VERSION_SNAPSHOT_TRIGGER}
|
|
2098
|
+
INSERT OR IGNORE INTO _migrations (id) VALUES (36);
|
|
1991
2099
|
`
|
|
1992
2100
|
];
|
|
1993
2101
|
});
|
|
@@ -2002,6 +2110,7 @@ __export(exports_database, {
|
|
|
2002
2110
|
now: () => now,
|
|
2003
2111
|
getDbPath: () => getDbPath,
|
|
2004
2112
|
getDatabase: () => getDatabase,
|
|
2113
|
+
escapeLikePrefix: () => escapeLikePrefix,
|
|
2005
2114
|
closeDatabase: () => closeDatabase
|
|
2006
2115
|
});
|
|
2007
2116
|
import { existsSync as existsSync2, mkdirSync as mkdirSync2, cpSync } from "fs";
|
|
@@ -2176,15 +2285,20 @@ function uuid() {
|
|
|
2176
2285
|
function shortUuid() {
|
|
2177
2286
|
return crypto.randomUUID().slice(0, 8);
|
|
2178
2287
|
}
|
|
2288
|
+
function escapeLikePrefix(s) {
|
|
2289
|
+
return s.replace(/\\/g, "\\\\").replace(/%/g, "\\%").replace(/_/g, "\\_");
|
|
2290
|
+
}
|
|
2179
2291
|
function resolvePartialId(db, table, partialId) {
|
|
2180
2292
|
if (!ALLOWED_TABLES.has(table)) {
|
|
2181
2293
|
throw new Error(`Invalid table name: ${table}`);
|
|
2182
2294
|
}
|
|
2295
|
+
if (partialId === "")
|
|
2296
|
+
return null;
|
|
2183
2297
|
if (partialId.length >= 36) {
|
|
2184
2298
|
const row = db.query(`SELECT id FROM ${table} WHERE id = ?`).get(partialId);
|
|
2185
2299
|
return row?.id ?? null;
|
|
2186
2300
|
}
|
|
2187
|
-
const rows = db.query(`SELECT id FROM ${table} WHERE id LIKE
|
|
2301
|
+
const rows = db.query(`SELECT id FROM ${table} WHERE id LIKE ? ESCAPE '\\'`).all(`${escapeLikePrefix(partialId)}%`);
|
|
2188
2302
|
if (rows.length === 1) {
|
|
2189
2303
|
return rows[0].id;
|
|
2190
2304
|
}
|
|
@@ -49293,7 +49407,10 @@ function parseMemoryRow(row) {
|
|
|
49293
49407
|
}
|
|
49294
49408
|
function createMemory(input, dedupeMode = "merge", db) {
|
|
49295
49409
|
if (!db && isApiMode()) {
|
|
49296
|
-
const { data } = apiJson("POST", "/memories", { ...input, dedupe: dedupeMode });
|
|
49410
|
+
const { status, data } = apiJson("POST", "/memories", { ...input, dedupe: dedupeMode });
|
|
49411
|
+
if (!data || !data.id) {
|
|
49412
|
+
throw new ApiRequestError(`mementos cloud POST /memories \u2192 ${status} but no memory was returned; the write did not persist (key: ${input.key})`, status, "");
|
|
49413
|
+
}
|
|
49297
49414
|
return data;
|
|
49298
49415
|
}
|
|
49299
49416
|
const d = db || getDatabase();
|
|
@@ -49450,7 +49567,7 @@ function listMemoriesByKey(key, db) {
|
|
|
49450
49567
|
}
|
|
49451
49568
|
function getMemory(id, db) {
|
|
49452
49569
|
if (!db && isApiMode()) {
|
|
49453
|
-
const { status, data } = apiJson("GET", `/memories/${encodeURIComponent(id)}
|
|
49570
|
+
const { status, data } = apiJson("GET", `/memories/${encodeURIComponent(id)}`, undefined, { allow404: true });
|
|
49454
49571
|
return status === 404 ? null : data ?? null;
|
|
49455
49572
|
}
|
|
49456
49573
|
const d = db || getDatabase();
|
|
@@ -49674,36 +49791,22 @@ function listMemories(filter, db) {
|
|
|
49674
49791
|
}
|
|
49675
49792
|
function updateMemory(id, input, db) {
|
|
49676
49793
|
if (!db && isApiMode()) {
|
|
49677
|
-
const { status, data } = apiJson("PATCH", `/memories/${encodeURIComponent(id)}`, input);
|
|
49794
|
+
const { status, data } = apiJson("PATCH", `/memories/${encodeURIComponent(id)}`, input, { allow404: true });
|
|
49678
49795
|
if (status === 404)
|
|
49679
49796
|
throw new MemoryNotFoundError(id);
|
|
49797
|
+
if (data && typeof input.version === "number" && typeof data.version === "number" && data.version <= input.version) {
|
|
49798
|
+
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.`);
|
|
49799
|
+
}
|
|
49680
49800
|
return data;
|
|
49681
49801
|
}
|
|
49682
49802
|
const d = db || getDatabase();
|
|
49683
49803
|
const existing = getMemory(id, d);
|
|
49684
49804
|
if (!existing)
|
|
49685
49805
|
throw new MemoryNotFoundError(id);
|
|
49806
|
+
const memoryId = existing.id;
|
|
49686
49807
|
if (existing.version !== input.version) {
|
|
49687
49808
|
throw new VersionConflictError(id, input.version, existing.version);
|
|
49688
49809
|
}
|
|
49689
|
-
try {
|
|
49690
|
-
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)
|
|
49691
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
49692
|
-
uuid(),
|
|
49693
|
-
existing.id,
|
|
49694
|
-
existing.version,
|
|
49695
|
-
existing.value,
|
|
49696
|
-
existing.importance,
|
|
49697
|
-
existing.scope,
|
|
49698
|
-
existing.category,
|
|
49699
|
-
JSON.stringify(existing.tags),
|
|
49700
|
-
existing.summary,
|
|
49701
|
-
existing.pinned ? 1 : 0,
|
|
49702
|
-
existing.status,
|
|
49703
|
-
existing.when_to_use || null,
|
|
49704
|
-
existing.updated_at
|
|
49705
|
-
]);
|
|
49706
|
-
} catch {}
|
|
49707
49810
|
const sets = ["version = version + 1", "updated_at = ?"];
|
|
49708
49811
|
const params = [now()];
|
|
49709
49812
|
if (input.value !== undefined) {
|
|
@@ -49753,15 +49856,18 @@ function updateMemory(id, input, db) {
|
|
|
49753
49856
|
if (input.tags !== undefined) {
|
|
49754
49857
|
sets.push("tags = ?");
|
|
49755
49858
|
params.push(JSON.stringify(input.tags));
|
|
49756
|
-
d.run("DELETE FROM memory_tags WHERE memory_id = ?", [
|
|
49859
|
+
d.run("DELETE FROM memory_tags WHERE memory_id = ?", [memoryId]);
|
|
49757
49860
|
const insertTag = d.prepare("INSERT OR IGNORE INTO memory_tags (memory_id, tag) VALUES (?, ?)");
|
|
49758
49861
|
for (const tag of input.tags) {
|
|
49759
|
-
insertTag.run(
|
|
49862
|
+
insertTag.run(memoryId, tag);
|
|
49760
49863
|
}
|
|
49761
49864
|
}
|
|
49762
|
-
params.push(
|
|
49763
|
-
d.run(`UPDATE memories SET ${sets.join(", ")} WHERE id = ?`, params);
|
|
49764
|
-
|
|
49865
|
+
params.push(memoryId);
|
|
49866
|
+
const result = d.run(`UPDATE memories SET ${sets.join(", ")} WHERE id = ?`, params);
|
|
49867
|
+
if (result.changes === 0) {
|
|
49868
|
+
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.`);
|
|
49869
|
+
}
|
|
49870
|
+
const updated = getMemory(memoryId, d);
|
|
49765
49871
|
if (input.value !== undefined) {
|
|
49766
49872
|
try {
|
|
49767
49873
|
const oldLinks = getEntityMemoryLinks(undefined, updated.id, d);
|
|
@@ -49782,14 +49888,15 @@ function updateMemory(id, input, db) {
|
|
|
49782
49888
|
}
|
|
49783
49889
|
function deleteMemory(id, db) {
|
|
49784
49890
|
if (!db && isApiMode()) {
|
|
49785
|
-
const { status } = apiJson("DELETE", `/memories/${encodeURIComponent(id)}
|
|
49891
|
+
const { status } = apiJson("DELETE", `/memories/${encodeURIComponent(id)}`, undefined, { allow404: true });
|
|
49786
49892
|
return status !== 404;
|
|
49787
49893
|
}
|
|
49788
49894
|
const d = db || getDatabase();
|
|
49789
|
-
const
|
|
49895
|
+
const memoryId = resolvePartialId(d, "memories", id) ?? id;
|
|
49896
|
+
const result = d.run("DELETE FROM memories WHERE id = ?", [memoryId]);
|
|
49790
49897
|
if (result.changes > 0) {
|
|
49791
49898
|
hookRegistry.runHooks("PostMemoryDelete", {
|
|
49792
|
-
memoryId
|
|
49899
|
+
memoryId,
|
|
49793
49900
|
timestamp: Date.now()
|
|
49794
49901
|
});
|
|
49795
49902
|
}
|
|
@@ -49803,11 +49910,12 @@ function bulkDeleteMemories(ids, db) {
|
|
|
49803
49910
|
return data?.deleted ?? 0;
|
|
49804
49911
|
}
|
|
49805
49912
|
const d = db || getDatabase();
|
|
49806
|
-
const
|
|
49807
|
-
const
|
|
49913
|
+
const resolvedIds = ids.map((id) => resolvePartialId(d, "memories", id) ?? id);
|
|
49914
|
+
const placeholders = resolvedIds.map(() => "?").join(",");
|
|
49915
|
+
const countRow = d.query(`SELECT COUNT(*) as c FROM memories WHERE id IN (${placeholders})`).get(...resolvedIds);
|
|
49808
49916
|
const count = countRow.c;
|
|
49809
49917
|
if (count > 0) {
|
|
49810
|
-
d.run(`DELETE FROM memories WHERE id IN (${placeholders})`,
|
|
49918
|
+
d.run(`DELETE FROM memories WHERE id IN (${placeholders})`, resolvedIds);
|
|
49811
49919
|
}
|
|
49812
49920
|
return count;
|
|
49813
49921
|
}
|
|
@@ -49952,7 +50060,7 @@ function registerAgent(name, sessionId, description, role, projectId, db) {
|
|
|
49952
50060
|
}
|
|
49953
50061
|
function getAgent(idOrName, db) {
|
|
49954
50062
|
if (!db && isApiMode()) {
|
|
49955
|
-
const { status, data } = apiJson("GET", `/agents/${encodeURIComponent(idOrName)}
|
|
50063
|
+
const { status, data } = apiJson("GET", `/agents/${encodeURIComponent(idOrName)}`, undefined, { allow404: true });
|
|
49956
50064
|
if (status === 404 || !data)
|
|
49957
50065
|
return null;
|
|
49958
50066
|
return data;
|
|
@@ -49964,7 +50072,7 @@ function getAgent(idOrName, db) {
|
|
|
49964
50072
|
row = d.query("SELECT * FROM agents WHERE LOWER(name) = ?").get(idOrName.trim().toLowerCase());
|
|
49965
50073
|
if (row)
|
|
49966
50074
|
return parseAgentRow(row);
|
|
49967
|
-
const rows = d.query("SELECT * FROM agents WHERE id LIKE ?").all(`${idOrName}%`);
|
|
50075
|
+
const rows = d.query("SELECT * FROM agents WHERE id LIKE ? ESCAPE '\\'").all(`${escapeLikePrefix(idOrName)}%`);
|
|
49968
50076
|
if (rows.length === 1)
|
|
49969
50077
|
return parseAgentRow(rows[0]);
|
|
49970
50078
|
return null;
|
|
@@ -50005,7 +50113,7 @@ function listAgentsByProject(projectId, db) {
|
|
|
50005
50113
|
}
|
|
50006
50114
|
function updateAgent(id, updates, db) {
|
|
50007
50115
|
if (!db && isApiMode()) {
|
|
50008
|
-
const { status, data } = apiJson("PATCH", `/agents/${encodeURIComponent(id)}`, updates);
|
|
50116
|
+
const { status, data } = apiJson("PATCH", `/agents/${encodeURIComponent(id)}`, updates, { allow404: true });
|
|
50009
50117
|
if (status === 404 || !data)
|
|
50010
50118
|
return null;
|
|
50011
50119
|
return data;
|
|
@@ -50112,7 +50220,7 @@ function acquireLock(agentId, resourceType, resourceId, lockType = "exclusive",
|
|
|
50112
50220
|
}
|
|
50113
50221
|
function releaseLock(lockId, agentId, db) {
|
|
50114
50222
|
if (!db && isApiMode()) {
|
|
50115
|
-
const { status } = apiJson("DELETE", `/locks/${encodeURIComponent(lockId)}`, { agent_id: agentId });
|
|
50223
|
+
const { status } = apiJson("DELETE", `/locks/${encodeURIComponent(lockId)}`, { agent_id: agentId }, { allow404: true });
|
|
50116
50224
|
return status !== 404;
|
|
50117
50225
|
}
|
|
50118
50226
|
const d = db || getDatabase();
|
|
@@ -50321,7 +50429,7 @@ function registerProject(name, path, description, memoryPrefix, db) {
|
|
|
50321
50429
|
}
|
|
50322
50430
|
function getProject(idOrPath, db) {
|
|
50323
50431
|
if (!db && isApiMode()) {
|
|
50324
|
-
const { status, data } = apiJson("GET", `/projects/${encodeURIComponent(idOrPath)}
|
|
50432
|
+
const { status, data } = apiJson("GET", `/projects/${encodeURIComponent(idOrPath)}`, undefined, { allow404: true });
|
|
50325
50433
|
if (status === 404 || !data)
|
|
50326
50434
|
return null;
|
|
50327
50435
|
return data;
|
|
@@ -50514,7 +50622,7 @@ function createEntity(input, db) {
|
|
|
50514
50622
|
}
|
|
50515
50623
|
function getEntity(id, db) {
|
|
50516
50624
|
if (!db && isApiMode()) {
|
|
50517
|
-
const { status, data } = apiJson("GET", `/entities/${encodeURIComponent(id)}
|
|
50625
|
+
const { status, data } = apiJson("GET", `/entities/${encodeURIComponent(id)}`, undefined, { allow404: true });
|
|
50518
50626
|
if (status === 404 || !data)
|
|
50519
50627
|
throw new EntityNotFoundError(id);
|
|
50520
50628
|
return data;
|
|
@@ -50597,7 +50705,7 @@ function listEntities(filter = {}, db) {
|
|
|
50597
50705
|
}
|
|
50598
50706
|
function updateEntity(id, input, db) {
|
|
50599
50707
|
if (!db && isApiMode()) {
|
|
50600
|
-
const { status, data } = apiJson("PATCH", `/entities/${encodeURIComponent(id)}`, input);
|
|
50708
|
+
const { status, data } = apiJson("PATCH", `/entities/${encodeURIComponent(id)}`, input, { allow404: true });
|
|
50601
50709
|
if (status === 404 || !data)
|
|
50602
50710
|
throw new EntityNotFoundError(id);
|
|
50603
50711
|
return data;
|
|
@@ -50630,7 +50738,7 @@ function updateEntity(id, input, db) {
|
|
|
50630
50738
|
}
|
|
50631
50739
|
function deleteEntity(id, db) {
|
|
50632
50740
|
if (!db && isApiMode()) {
|
|
50633
|
-
const { status } = apiJson("DELETE", `/entities/${encodeURIComponent(id)}
|
|
50741
|
+
const { status } = apiJson("DELETE", `/entities/${encodeURIComponent(id)}`, undefined, { allow404: true });
|
|
50634
50742
|
if (status === 404)
|
|
50635
50743
|
throw new EntityNotFoundError(id);
|
|
50636
50744
|
return;
|
|
@@ -52691,7 +52799,7 @@ function createRelation(input, db) {
|
|
|
52691
52799
|
}
|
|
52692
52800
|
function getRelation(id, db) {
|
|
52693
52801
|
if (!db && isApiMode()) {
|
|
52694
|
-
const { status, data } = apiJson("GET", `/relations/${encodeURIComponent(id)}
|
|
52802
|
+
const { status, data } = apiJson("GET", `/relations/${encodeURIComponent(id)}`, undefined, { allow404: true });
|
|
52695
52803
|
if (status === 404 || !data)
|
|
52696
52804
|
throw new Error(`Relation not found: ${id}`);
|
|
52697
52805
|
return data;
|
|
@@ -52736,7 +52844,7 @@ function listRelations(filter, db) {
|
|
|
52736
52844
|
}
|
|
52737
52845
|
function deleteRelation(id, db) {
|
|
52738
52846
|
if (!db && isApiMode()) {
|
|
52739
|
-
const { status } = apiJson("DELETE", `/relations/${encodeURIComponent(id)}
|
|
52847
|
+
const { status } = apiJson("DELETE", `/relations/${encodeURIComponent(id)}`, undefined, { allow404: true });
|
|
52740
52848
|
if (status === 404)
|
|
52741
52849
|
throw new Error(`Relation not found: ${id}`);
|
|
52742
52850
|
return;
|
|
@@ -53379,6 +53487,32 @@ class AutoMemoryQueue {
|
|
|
53379
53487
|
getStats() {
|
|
53380
53488
|
return { ...this.stats, pending: this.queue.length };
|
|
53381
53489
|
}
|
|
53490
|
+
async waitForIdleForTests(timeoutMs = 3000) {
|
|
53491
|
+
const start = Date.now();
|
|
53492
|
+
while (Date.now() - start < timeoutMs) {
|
|
53493
|
+
if (this.queue.length === 0 && this.activeCount === 0)
|
|
53494
|
+
return;
|
|
53495
|
+
await new Promise((r) => setTimeout(r, 20));
|
|
53496
|
+
}
|
|
53497
|
+
throw new Error("autoMemoryQueue did not become idle before test reset");
|
|
53498
|
+
}
|
|
53499
|
+
resetForTests(handler) {
|
|
53500
|
+
if (this.activeCount !== 0) {
|
|
53501
|
+
throw new Error("Cannot reset autoMemoryQueue while jobs are processing");
|
|
53502
|
+
}
|
|
53503
|
+
this.queue = [];
|
|
53504
|
+
this.running = false;
|
|
53505
|
+
this.stats = {
|
|
53506
|
+
pending: 0,
|
|
53507
|
+
processing: 0,
|
|
53508
|
+
processed: 0,
|
|
53509
|
+
failed: 0,
|
|
53510
|
+
dropped: 0
|
|
53511
|
+
};
|
|
53512
|
+
if (handler !== undefined) {
|
|
53513
|
+
this.handler = handler;
|
|
53514
|
+
}
|
|
53515
|
+
}
|
|
53382
53516
|
startLoop() {
|
|
53383
53517
|
this.running = true;
|
|
53384
53518
|
this.loop();
|
|
@@ -36,6 +36,8 @@ declare class AutoMemoryQueue {
|
|
|
36
36
|
*/
|
|
37
37
|
enqueue(job: ExtractionJob): void;
|
|
38
38
|
getStats(): Readonly<QueueStats>;
|
|
39
|
+
waitForIdleForTests(timeoutMs?: number): Promise<void>;
|
|
40
|
+
resetForTests(handler?: JobHandler | null): void;
|
|
39
41
|
private startLoop;
|
|
40
42
|
private loop;
|
|
41
43
|
private processJob;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auto-memory-queue.d.ts","sourceRoot":"","sources":["../../src/lib/auto-memory-queue.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iFAAiF;IACjF,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,yDAAyD;IACzD,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAC;CACxC;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,KAAK,UAAU,GAAG,CAAC,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAKxD,cAAM,eAAe;IACnB,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,OAAO,CAA2B;IAC1C,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,WAAW,CAAK;IAExB,OAAO,CAAC,KAAK,CAMX;IAEF,mDAAmD;IACnD,UAAU,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI;IAKrC;;;OAGG;IACH,OAAO,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI;IAYjC,QAAQ,IAAI,QAAQ,CAAC,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"auto-memory-queue.d.ts","sourceRoot":"","sources":["../../src/lib/auto-memory-queue.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iFAAiF;IACjF,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,yDAAyD;IACzD,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAC;CACxC;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,KAAK,UAAU,GAAG,CAAC,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAKxD,cAAM,eAAe;IACnB,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,OAAO,CAA2B;IAC1C,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,WAAW,CAAK;IAExB,OAAO,CAAC,KAAK,CAMX;IAEF,mDAAmD;IACnD,UAAU,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI;IAKrC;;;OAGG;IACH,OAAO,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI;IAYjC,QAAQ,IAAI,QAAQ,CAAC,UAAU,CAAC;IAI1B,mBAAmB,CAAC,SAAS,SAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAS1D,aAAa,CAAC,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI,GAAG,IAAI;IAkBhD,OAAO,CAAC,SAAS;YAKH,IAAI;YAiBJ,UAAU;CAiBzB;AAED,kDAAkD;AAClD,eAAO,MAAM,eAAe,iBAAwB,CAAC"}
|
|
@@ -15,4 +15,5 @@ export declare function processConversationTurn(turn: string, context: Omit<Extr
|
|
|
15
15
|
export declare function getAutoMemoryStats(): Readonly<import("./auto-memory-queue.js").QueueStats>;
|
|
16
16
|
/** Configure the auto-memory pipeline at runtime */
|
|
17
17
|
export declare function configureAutoMemory(config: Parameters<typeof providerRegistry.configure>[0]): void;
|
|
18
|
+
export declare function resetAutoMemoryForTests(): Promise<void>;
|
|
18
19
|
//# sourceMappingURL=auto-memory.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auto-memory.d.ts","sourceRoot":"","sources":["../../src/lib/auto-memory.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAmB,KAAK,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAgO7E;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,WAAW,CAAC,EAClD,MAAM,GAAE,aAAa,CAAC,QAAQ,CAAU,GACvC,IAAI,CAQN;AAED,8BAA8B;AAC9B,wBAAgB,kBAAkB,0DAEjC;AAED,oDAAoD;AACpD,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GACvD,IAAI,CAEN"}
|
|
1
|
+
{"version":3,"file":"auto-memory.d.ts","sourceRoot":"","sources":["../../src/lib/auto-memory.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAmB,KAAK,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAgO7E;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,WAAW,CAAC,EAClD,MAAM,GAAE,aAAa,CAAC,QAAQ,CAAU,GACvC,IAAI,CAQN;AAED,8BAA8B;AAC9B,wBAAgB,kBAAkB,0DAEjC;AAED,oDAAoD;AACpD,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GACvD,IAAI,CAEN;AAED,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,IAAI,CAAC,CAK7D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"built-in-hooks.d.ts","sourceRoot":"","sources":["../../src/lib/built-in-hooks.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"built-in-hooks.d.ts","sourceRoot":"","sources":["../../src/lib/built-in-hooks.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAyOlD,wBAAgB,kBAAkB,IAAI,IAAI,CAyBzC;AAuBD,wBAAgB,cAAc,IAAI,IAAI,CAGrC;AAGD,YAAY,EAAE,QAAQ,EAAE,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface EnumViolation {
|
|
2
|
+
field: string;
|
|
3
|
+
value: string;
|
|
4
|
+
allowed: readonly string[];
|
|
5
|
+
}
|
|
6
|
+
/** Human-readable, actionable rejection message naming the field and the accepted set. */
|
|
7
|
+
export declare function formatEnumViolation(v: EnumViolation): string;
|
|
8
|
+
/**
|
|
9
|
+
* Validate one enum-constrained field. Returns the violation, or `null` when
|
|
10
|
+
* the value is acceptable. `undefined`/`null` are acceptable — they mean "leave
|
|
11
|
+
* the column at its default", which is a separate concern from a bad value.
|
|
12
|
+
*/
|
|
13
|
+
export declare function validateEnumField(field: string, value: unknown): EnumViolation | null;
|
|
14
|
+
/**
|
|
15
|
+
* Validate every enum-constrained field present on a create/update payload.
|
|
16
|
+
* Returns the first violation so the caller can fail fast with one clear
|
|
17
|
+
* message, or `null` when the payload is clean.
|
|
18
|
+
*/
|
|
19
|
+
export declare function validateMemoryEnums(input: Record<string, unknown>): EnumViolation | null;
|
|
20
|
+
//# sourceMappingURL=enum-validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enum-validation.d.ts","sourceRoot":"","sources":["../../src/lib/enum-validation.ts"],"names":[],"mappings":"AA6BA,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5B;AAED,0FAA0F;AAC1F,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,aAAa,GAAG,MAAM,CAE5D;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,aAAa,GAAG,IAAI,CAMrF;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,aAAa,GAAG,IAAI,CAOxF"}
|
package/dist/lib/gdpr.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gdpr.d.ts","sourceRoot":"","sources":["../../src/lib/gdpr.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,aAAa,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AAG1D,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CACvB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE;IACP,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;CACd,EACN,EAAE,CAAC,EAAE,QAAQ,GACZ,iBAAiB,
|
|
1
|
+
{"version":3,"file":"gdpr.d.ts","sourceRoot":"","sources":["../../src/lib/gdpr.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,aAAa,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AAG1D,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CACvB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE;IACP,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;CACd,EACN,EAAE,CAAC,EAAE,QAAQ,GACZ,iBAAiB,CA+FnB"}
|
package/dist/mcp/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA4CpE,0FAA0F;AAC1F,eAAO,IAAI,SAAS,EAAE,SAAS,GAAG,IAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA4CpE,0FAA0F;AAC1F,eAAO,IAAI,SAAS,EAAE,SAAS,GAAG,IAAW,CAAC;AAsB9C,wBAAgB,WAAW,IAAI,SAAS,CA2EvC"}
|