@hasna/mementos 0.14.83 → 0.14.84
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/Dockerfile.package +0 -1
- package/README.md +13 -10
- package/dashboard/bun.lock +519 -0
- package/dist/cli/commands/storage.d.ts.map +1 -1
- package/dist/cli/index.js +3437 -1445
- package/dist/db/api-mode.d.ts +5 -1
- package/dist/db/api-mode.d.ts.map +1 -1
- package/dist/db/database.d.ts.map +1 -1
- package/dist/db/store-backend.d.ts +3 -3
- package/dist/db/store-backend.d.ts.map +1 -1
- package/dist/generated/storage-kit/backend.d.ts +20 -0
- package/dist/generated/storage-kit/backend.d.ts.map +1 -0
- package/dist/generated/storage-kit/index.d.ts +2 -2
- package/dist/generated/storage-kit/index.d.ts.map +1 -1
- package/dist/generated/storage-kit/migrations.d.ts.map +1 -1
- package/dist/generated/storage-kit/own.d.ts +11 -0
- package/dist/generated/storage-kit/own.d.ts.map +1 -0
- package/dist/generated/storage-kit/pool.d.ts +7 -6
- package/dist/generated/storage-kit/pool.d.ts.map +1 -1
- package/dist/generated/storage-kit/tls.d.ts +30 -3
- package/dist/generated/storage-kit/tls.d.ts.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3428 -1422
- package/dist/lib/retired-storage-mode.d.ts +11 -0
- package/dist/lib/retired-storage-mode.d.ts.map +1 -0
- package/dist/lib/storage-sync.d.ts +2 -2
- package/dist/lib/storage-sync.d.ts.map +1 -1
- package/dist/mcp/index.js +3416 -1423
- package/dist/mcp/tools/project-tools.d.ts.map +1 -1
- package/dist/project-registration.js +160 -130
- package/dist/server/index.js +3390 -1379
- package/dist/storage.d.ts +18 -50
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +151 -122
- package/dist/test-support/store-isolation.d.ts +5 -0
- package/dist/test-support/store-isolation.d.ts.map +1 -1
- package/docker-entrypoint.sh +4 -5
- package/hasna.contract.json +2 -2
- package/package.json +5 -5
- package/dist/generated/storage-kit/mode.d.ts +0 -48
- package/dist/generated/storage-kit/mode.d.ts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-tools.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/project-tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"project-tools.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/project-tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAuDpE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA6M5D"}
|
|
@@ -46,24 +46,109 @@ 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/
|
|
50
|
-
function
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if (
|
|
55
|
-
return
|
|
56
|
-
if (
|
|
57
|
-
return
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
49
|
+
// src/generated/storage-kit/own.ts
|
|
50
|
+
function ownProp(source, key) {
|
|
51
|
+
if (source === null || source === undefined)
|
|
52
|
+
return;
|
|
53
|
+
const kind = typeof source;
|
|
54
|
+
if (kind !== "object" && kind !== "function")
|
|
55
|
+
return;
|
|
56
|
+
if (!Object.hasOwn(source, key))
|
|
57
|
+
return;
|
|
58
|
+
return source[key];
|
|
59
|
+
}
|
|
60
|
+
function ownString(source, key) {
|
|
61
|
+
const value = ownProp(source, key);
|
|
62
|
+
return typeof value === "string" ? value : undefined;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// src/generated/storage-kit/backend.ts
|
|
66
|
+
function envToken(name) {
|
|
67
|
+
return name.toUpperCase().replace(/-/g, "_");
|
|
68
|
+
}
|
|
69
|
+
function serverDataBackendEnvKeys(name) {
|
|
70
|
+
const token = envToken(name);
|
|
71
|
+
return {
|
|
72
|
+
databaseUrlKeys: [`HASNA_${token}_DATABASE_URL`, `${token}_DATABASE_URL`]
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
function legacyModeKeys(name) {
|
|
76
|
+
const token = envToken(name);
|
|
77
|
+
return [
|
|
78
|
+
`HASNA_${token}_STORAGE_MODE`,
|
|
79
|
+
`HASNA_${token}_MODE`,
|
|
80
|
+
`${token}_STORAGE_MODE`,
|
|
81
|
+
`${token}_MODE`
|
|
82
|
+
];
|
|
83
|
+
}
|
|
84
|
+
function firstEnv(env, keys) {
|
|
85
|
+
for (const key of keys) {
|
|
86
|
+
const value = ownString(env, key)?.trim();
|
|
87
|
+
if (value)
|
|
88
|
+
return { key, value };
|
|
89
|
+
}
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
function firstDefinedEnvKey(env, keys) {
|
|
93
|
+
for (const key of keys) {
|
|
94
|
+
if (Object.hasOwn(env, key) && env[key] !== undefined)
|
|
95
|
+
return key;
|
|
96
|
+
}
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
function assertNoLegacyStorageMode(name, env = process.env) {
|
|
100
|
+
const legacyKey = firstDefinedEnvKey(env, legacyModeKeys(name));
|
|
101
|
+
if (!legacyKey)
|
|
102
|
+
return;
|
|
103
|
+
const canonicalDatabaseUrl = serverDataBackendEnvKeys(name).databaseUrlKeys[0];
|
|
104
|
+
throw new Error(`${legacyKey} was removed. Delete the storage-mode variable; ` + `set ${canonicalDatabaseUrl} to select the postgresql server backend, ` + `or leave it unset for sqlite.`);
|
|
105
|
+
}
|
|
106
|
+
function resolveServerDataBackend(name, env = process.env) {
|
|
107
|
+
assertNoLegacyStorageMode(name, env);
|
|
108
|
+
const databaseUrl = firstEnv(env, serverDataBackendEnvKeys(name).databaseUrlKeys);
|
|
109
|
+
if (!databaseUrl) {
|
|
110
|
+
return {
|
|
111
|
+
backend: "sqlite",
|
|
112
|
+
source: "default",
|
|
113
|
+
databaseUrlPresent: false,
|
|
114
|
+
databaseUrlSource: null
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
backend: "postgresql",
|
|
119
|
+
source: databaseUrl.key,
|
|
120
|
+
databaseUrlPresent: true,
|
|
121
|
+
databaseUrlSource: databaseUrl.key
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
function resolveDatabaseUrl(name, env = process.env) {
|
|
125
|
+
assertNoLegacyStorageMode(name, env);
|
|
126
|
+
const hit = firstEnv(env, serverDataBackendEnvKeys(name).databaseUrlKeys);
|
|
127
|
+
return hit?.value ?? null;
|
|
128
|
+
}
|
|
129
|
+
var init_backend = () => {};
|
|
130
|
+
|
|
131
|
+
// src/lib/retired-storage-mode.ts
|
|
132
|
+
function firstDefinedEnvKey2(env, keys) {
|
|
133
|
+
for (const key of keys) {
|
|
134
|
+
if (Object.hasOwn(env, key) && env[key] !== undefined)
|
|
135
|
+
return key;
|
|
136
|
+
}
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
function assertNoLegacyStorageMode2(env = process.env) {
|
|
140
|
+
const legacyKey = firstDefinedEnvKey2(env, LEGACY_STORAGE_MODE_KEYS);
|
|
141
|
+
if (!legacyKey)
|
|
142
|
+
return;
|
|
143
|
+
throw new Error(`${legacyKey} was removed. Deployment modes no longer exist: delete the storage-mode variable. ` + `The client uses the local SQLite store, or the HTTP API selected by ` + `HASNA_MEMENTOS_API_URL + HASNA_MEMENTOS_API_KEY. ` + `On the server, set HASNA_MEMENTOS_DATABASE_URL to select the postgresql backend, ` + `or leave it unset for sqlite.`);
|
|
144
|
+
}
|
|
145
|
+
var LEGACY_STORAGE_MODE_KEYS;
|
|
146
|
+
var init_retired_storage_mode = __esm(() => {
|
|
147
|
+
LEGACY_STORAGE_MODE_KEYS = [
|
|
148
|
+
"HASNA_MEMENTOS_STORAGE_MODE",
|
|
149
|
+
"HASNA_MEMENTOS_MODE",
|
|
150
|
+
"MEMENTOS_STORAGE_MODE",
|
|
151
|
+
"MEMENTOS_MODE"
|
|
67
152
|
];
|
|
68
153
|
});
|
|
69
154
|
|
|
@@ -328,27 +413,6 @@ function readEnv(name) {
|
|
|
328
413
|
const value = process.env[name]?.trim();
|
|
329
414
|
return value ? value : null;
|
|
330
415
|
}
|
|
331
|
-
function warnDeprecatedStorageMode(alias) {
|
|
332
|
-
if (warnedDeprecatedModes.has(alias))
|
|
333
|
-
return;
|
|
334
|
-
warnedDeprecatedModes.add(alias);
|
|
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" });
|
|
336
|
-
}
|
|
337
|
-
function normalizeStorageMode2(value, source) {
|
|
338
|
-
if (!value || !value.trim())
|
|
339
|
-
return null;
|
|
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}`);
|
|
346
|
-
}
|
|
347
|
-
if (normalized.deprecatedAlias) {
|
|
348
|
-
warnDeprecatedStorageMode(normalized.deprecatedAlias);
|
|
349
|
-
}
|
|
350
|
-
return normalized.mode;
|
|
351
|
-
}
|
|
352
416
|
function readConfigFile() {
|
|
353
417
|
if (!existsSync(STORAGE_CONFIG_PATH)) {
|
|
354
418
|
return {};
|
|
@@ -384,19 +448,15 @@ function getStorageDatabaseUrl() {
|
|
|
384
448
|
function getStorageDatabaseEnvName() {
|
|
385
449
|
return getStorageEnvName("databaseUrl");
|
|
386
450
|
}
|
|
387
|
-
function
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
}
|
|
393
|
-
return null;
|
|
451
|
+
function getStorageBackend(env = process.env) {
|
|
452
|
+
return resolveServerDataBackend("mementos", env).backend;
|
|
453
|
+
}
|
|
454
|
+
function getStorageBackendDatabaseUrl(env = process.env) {
|
|
455
|
+
return resolveDatabaseUrl("mementos", env);
|
|
394
456
|
}
|
|
395
457
|
function getStorageConfig() {
|
|
458
|
+
assertNoLegacyStorageMode2();
|
|
396
459
|
const fileConfig = readConfigFile();
|
|
397
|
-
const modeOverride = getStorageModeOverride();
|
|
398
|
-
const envConnectionString = getConfiguredConnectionString();
|
|
399
|
-
const fileMode = normalizeStorageMode2(fileConfig.mode, `${STORAGE_CONFIG_PATH} "mode"`);
|
|
400
460
|
const merged = {
|
|
401
461
|
...DEFAULT_STORAGE_CONFIG,
|
|
402
462
|
...fileConfig,
|
|
@@ -407,19 +467,10 @@ function getStorageConfig() {
|
|
|
407
467
|
sync: {
|
|
408
468
|
...DEFAULT_STORAGE_CONFIG.sync,
|
|
409
469
|
...fileConfig.sync ?? {}
|
|
410
|
-
}
|
|
411
|
-
mode: fileMode ?? DEFAULT_STORAGE_CONFIG.mode
|
|
470
|
+
}
|
|
412
471
|
};
|
|
413
|
-
if (modeOverride) {
|
|
414
|
-
merged.mode = modeOverride;
|
|
415
|
-
} else if (envConnectionString && merged.mode === "local") {
|
|
416
|
-
merged.mode = "cloud";
|
|
417
|
-
}
|
|
418
472
|
return merged;
|
|
419
473
|
}
|
|
420
|
-
function getStorageMode() {
|
|
421
|
-
return getStorageConfig().mode;
|
|
422
|
-
}
|
|
423
474
|
function isSecretQueryParam(key) {
|
|
424
475
|
const normalized = key.trim().toLowerCase();
|
|
425
476
|
return SECRET_QUERY_PARAMS.has(normalized) || /(?:secret|token|password|passphrase|credential|api[_-]?key|apikey|private[_-]?key|auth|session)/i.test(normalized);
|
|
@@ -490,7 +541,7 @@ function storageEnvStatus(key) {
|
|
|
490
541
|
configured: readEnv(activeName) !== null
|
|
491
542
|
};
|
|
492
543
|
}
|
|
493
|
-
function
|
|
544
|
+
function postgresBackendStatus(config) {
|
|
494
545
|
const env = getStorageDatabaseEnv();
|
|
495
546
|
const envUrl = env ? readEnv(env.name) : null;
|
|
496
547
|
if (env && envUrl) {
|
|
@@ -528,12 +579,8 @@ function remoteDatabaseConfigStatus(config) {
|
|
|
528
579
|
rds_compatible: configured
|
|
529
580
|
};
|
|
530
581
|
}
|
|
531
|
-
function runtimeKindFor(mode) {
|
|
532
|
-
return mode === "cloud" ? "cloud-postgres" : "local-sqlite";
|
|
533
|
-
}
|
|
534
582
|
function getSafeStorageConfigSummary(config = getStorageConfig()) {
|
|
535
583
|
return {
|
|
536
|
-
mode: config.mode,
|
|
537
584
|
auto_sync_interval_minutes: config.auto_sync_interval_minutes,
|
|
538
585
|
feedback_endpoint_configured: config.feedback_endpoint.trim() !== "",
|
|
539
586
|
sync: { ...config.sync },
|
|
@@ -548,29 +595,30 @@ function getSafeStorageConfigSummary(config = getStorageConfig()) {
|
|
|
548
595
|
};
|
|
549
596
|
}
|
|
550
597
|
function getStorageStatus() {
|
|
598
|
+
assertNoLegacyStorageMode2();
|
|
551
599
|
const config = getStorageConfig();
|
|
552
|
-
const
|
|
553
|
-
const
|
|
554
|
-
const
|
|
600
|
+
const backend = getStorageBackend();
|
|
601
|
+
const postgresRequested = backend === "postgresql";
|
|
602
|
+
const postgres = postgresBackendStatus(config);
|
|
555
603
|
const issues = [];
|
|
556
604
|
const warnings = [];
|
|
557
|
-
if (
|
|
558
|
-
issues.push(`
|
|
605
|
+
if (postgresRequested && !postgres.configured) {
|
|
606
|
+
issues.push(`PostgreSQL is selected (HASNA_MEMENTOS_DATABASE_URL) but not configured. ${postgres.issues.join(" ")}`);
|
|
559
607
|
}
|
|
560
|
-
if (
|
|
561
|
-
warnings.push(`
|
|
608
|
+
if (!postgresRequested && postgres.issues.length > 0 && postgres.source !== "none") {
|
|
609
|
+
warnings.push(`PostgreSQL configuration is present but invalid; the postgresql backend stays disabled until fixed. ${postgres.issues.join(" ")}`);
|
|
562
610
|
}
|
|
563
|
-
if (
|
|
564
|
-
warnings.push("
|
|
611
|
+
if (!postgresRequested && postgres.configured) {
|
|
612
|
+
warnings.push("PostgreSQL configuration is present, but the selected backend is sqlite; the postgresql backend stays disabled until HASNA_MEMENTOS_DATABASE_URL is set.");
|
|
565
613
|
}
|
|
566
|
-
const failClosed =
|
|
614
|
+
const failClosed = postgresRequested && !postgres.configured;
|
|
567
615
|
const runtime = {
|
|
568
|
-
contract: "mementos-
|
|
569
|
-
kind:
|
|
616
|
+
contract: "mementos-storage-runtime-v1",
|
|
617
|
+
kind: backend,
|
|
570
618
|
fail_closed: failClosed,
|
|
571
619
|
local: {
|
|
572
620
|
adapter: "sqlite",
|
|
573
|
-
primary_runtime:
|
|
621
|
+
primary_runtime: backend === "sqlite",
|
|
574
622
|
data_dir: LOCAL_DATA_DIR,
|
|
575
623
|
config_path: STORAGE_CONFIG_PATH,
|
|
576
624
|
local_file_sync: {
|
|
@@ -578,34 +626,22 @@ function getStorageStatus() {
|
|
|
578
626
|
reason: "Mementos stores local state in SQLite; it does not sync raw local data files."
|
|
579
627
|
}
|
|
580
628
|
},
|
|
581
|
-
|
|
629
|
+
backend: {
|
|
582
630
|
adapter: "postgres",
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
rds_compatible: remote.rds_compatible,
|
|
631
|
+
requested: postgresRequested,
|
|
632
|
+
configured: postgres.configured,
|
|
633
|
+
source: postgres.source,
|
|
634
|
+
env_name: postgres.env_name,
|
|
635
|
+
redacted_url: postgres.redacted_url,
|
|
636
|
+
rds_compatible: postgres.rds_compatible,
|
|
590
637
|
fail_closed: failClosed,
|
|
591
|
-
missing:
|
|
592
|
-
},
|
|
593
|
-
object_storage: {
|
|
594
|
-
s3: {
|
|
595
|
-
supported: false,
|
|
596
|
-
mutation_allowed: false,
|
|
597
|
-
reason: "No S3 object-storage adapter is part of this runtime."
|
|
598
|
-
},
|
|
599
|
-
aws: {
|
|
600
|
-
mutation_allowed: false,
|
|
601
|
-
reason: "Diagnostics do not store sensitive values, change AWS resources, deploy, or mutate production data."
|
|
602
|
-
}
|
|
638
|
+
missing: postgres.missing
|
|
603
639
|
},
|
|
604
640
|
migrations: {
|
|
605
641
|
target: "postgres-rds-compatible",
|
|
606
642
|
command: "mementos storage migrate",
|
|
607
643
|
dry_run_command: "mementos storage migrate --dry-run",
|
|
608
|
-
configured:
|
|
644
|
+
configured: postgres.configured,
|
|
609
645
|
mutates_remote_on_apply: true,
|
|
610
646
|
requires_approval_for_live_run: true
|
|
611
647
|
}
|
|
@@ -613,21 +649,19 @@ function getStorageStatus() {
|
|
|
613
649
|
return {
|
|
614
650
|
ok: issues.length === 0,
|
|
615
651
|
service: "mementos",
|
|
616
|
-
|
|
617
|
-
local_default:
|
|
618
|
-
remote_enabled: remoteRequested,
|
|
652
|
+
backend,
|
|
653
|
+
local_default: backend === "sqlite",
|
|
619
654
|
runtime,
|
|
620
655
|
database: {
|
|
621
|
-
configured:
|
|
622
|
-
redacted_url:
|
|
623
|
-
source:
|
|
624
|
-
env_name:
|
|
625
|
-
rds_compatible:
|
|
656
|
+
configured: postgres.configured,
|
|
657
|
+
redacted_url: postgres.redacted_url,
|
|
658
|
+
source: postgres.source,
|
|
659
|
+
env_name: postgres.env_name,
|
|
660
|
+
rds_compatible: postgres.rds_compatible
|
|
626
661
|
},
|
|
627
662
|
tables: MEMENTOS_STORAGE_TABLES,
|
|
628
663
|
env: {
|
|
629
|
-
databaseUrl: storageEnvStatus("databaseUrl")
|
|
630
|
-
mode: storageEnvStatus("mode")
|
|
664
|
+
databaseUrl: storageEnvStatus("databaseUrl")
|
|
631
665
|
},
|
|
632
666
|
issues,
|
|
633
667
|
warnings,
|
|
@@ -643,8 +677,9 @@ function getConfiguredConnectionString() {
|
|
|
643
677
|
return getStorageDatabaseUrl() ?? undefined;
|
|
644
678
|
}
|
|
645
679
|
function getStorageConnectionString(dbName = "mementos") {
|
|
680
|
+
assertNoLegacyStorageMode2();
|
|
646
681
|
if (!isServerContext()) {
|
|
647
|
-
throw new Error("Refusing to construct an RDS Postgres DSN outside the mementos-serve server. " + "The raw database DSN is NEVER distributed to client machines. " + "Clients must use the
|
|
682
|
+
throw new Error("Refusing to construct an RDS Postgres DSN outside the mementos-serve server. " + "The raw database DSN is NEVER distributed to client machines. " + "Clients must use the HTTP API: set HASNA_MEMENTOS_API_URL and " + "HASNA_MEMENTOS_API_KEY (and unset HASNA_MEMENTOS_DATABASE_URL).");
|
|
648
683
|
}
|
|
649
684
|
const envConnectionString = getConfiguredConnectionString();
|
|
650
685
|
if (envConnectionString) {
|
|
@@ -815,7 +850,7 @@ function resetAllSyncMeta(db) {
|
|
|
815
850
|
ensureSyncMetaTable(db);
|
|
816
851
|
db.run("DELETE FROM _sync_meta");
|
|
817
852
|
}
|
|
818
|
-
var _serverContext = false, PgSyncPool, MEMENTOS_STORAGE_TABLES, STORAGE_TABLES, MEMENTOS_STORAGE_ENV, MEMENTOS_STORAGE_FALLBACK_ENV, LOCAL_DATA_DIR, DEFAULT_STORAGE_CONFIG, STORAGE_CONFIG_DIR, STORAGE_CONFIG_PATH, DATABASE_ENV_NAMES,
|
|
853
|
+
var _serverContext = false, PgSyncPool, MEMENTOS_STORAGE_TABLES, STORAGE_TABLES, MEMENTOS_STORAGE_ENV, MEMENTOS_STORAGE_FALLBACK_ENV, LOCAL_DATA_DIR, DEFAULT_STORAGE_CONFIG, STORAGE_CONFIG_DIR, STORAGE_CONFIG_PATH, DATABASE_ENV_NAMES, SECRET_QUERY_PARAMS, getMementosStorageStatus, SYNC_EXCLUDED_TABLE_PATTERNS, SYNC_META_TABLE_SQL = `
|
|
819
854
|
CREATE TABLE IF NOT EXISTS _sync_meta (
|
|
820
855
|
table_name TEXT PRIMARY KEY,
|
|
821
856
|
last_synced_at TEXT,
|
|
@@ -823,7 +858,8 @@ CREATE TABLE IF NOT EXISTS _sync_meta (
|
|
|
823
858
|
direction TEXT DEFAULT 'push'
|
|
824
859
|
)`;
|
|
825
860
|
var init_storage = __esm(() => {
|
|
826
|
-
|
|
861
|
+
init_backend();
|
|
862
|
+
init_retired_storage_mode();
|
|
827
863
|
PgSyncPool = class PgSyncPool {
|
|
828
864
|
worker;
|
|
829
865
|
status;
|
|
@@ -910,12 +946,10 @@ var init_storage = __esm(() => {
|
|
|
910
946
|
];
|
|
911
947
|
STORAGE_TABLES = MEMENTOS_STORAGE_TABLES;
|
|
912
948
|
MEMENTOS_STORAGE_ENV = {
|
|
913
|
-
databaseUrl: "HASNA_MEMENTOS_DATABASE_URL"
|
|
914
|
-
mode: "HASNA_MEMENTOS_STORAGE_MODE"
|
|
949
|
+
databaseUrl: "HASNA_MEMENTOS_DATABASE_URL"
|
|
915
950
|
};
|
|
916
951
|
MEMENTOS_STORAGE_FALLBACK_ENV = {
|
|
917
|
-
databaseUrl: "MEMENTOS_DATABASE_URL"
|
|
918
|
-
mode: "MEMENTOS_STORAGE_MODE"
|
|
952
|
+
databaseUrl: "MEMENTOS_DATABASE_URL"
|
|
919
953
|
};
|
|
920
954
|
LOCAL_DATA_DIR = join(homedir(), ".hasna", "mementos");
|
|
921
955
|
DEFAULT_STORAGE_CONFIG = {
|
|
@@ -926,7 +960,6 @@ var init_storage = __esm(() => {
|
|
|
926
960
|
password_env: "MEMENTOS_DATABASE_PASSWORD",
|
|
927
961
|
ssl: true
|
|
928
962
|
},
|
|
929
|
-
mode: "local",
|
|
930
963
|
auto_sync_interval_minutes: 0,
|
|
931
964
|
feedback_endpoint: "",
|
|
932
965
|
sync: {
|
|
@@ -939,11 +972,6 @@ var init_storage = __esm(() => {
|
|
|
939
972
|
{ name: MEMENTOS_STORAGE_ENV.databaseUrl, deprecated: false },
|
|
940
973
|
{ name: MEMENTOS_STORAGE_FALLBACK_ENV.databaseUrl, deprecated: false }
|
|
941
974
|
];
|
|
942
|
-
MODE_ENV_NAMES = [
|
|
943
|
-
{ name: MEMENTOS_STORAGE_ENV.mode, deprecated: false },
|
|
944
|
-
{ name: MEMENTOS_STORAGE_FALLBACK_ENV.mode, deprecated: false }
|
|
945
|
-
];
|
|
946
|
-
warnedDeprecatedModes = new Set;
|
|
947
975
|
SECRET_QUERY_PARAMS = new Set([
|
|
948
976
|
"password",
|
|
949
977
|
"pass",
|
|
@@ -968,7 +996,7 @@ import { tmpdir } from "os";
|
|
|
968
996
|
import { join as join2 } from "path";
|
|
969
997
|
import { writeFileSync as writeFileSync2, unlinkSync } from "fs";
|
|
970
998
|
import { randomUUID } from "crypto";
|
|
971
|
-
function
|
|
999
|
+
function firstEnv2(keys) {
|
|
972
1000
|
for (const k of keys) {
|
|
973
1001
|
const v = process.env[k]?.trim();
|
|
974
1002
|
if (v)
|
|
@@ -984,7 +1012,7 @@ function firstEnvKey(keys) {
|
|
|
984
1012
|
return null;
|
|
985
1013
|
}
|
|
986
1014
|
function hasDatabaseUrl() {
|
|
987
|
-
return Boolean(
|
|
1015
|
+
return Boolean(firstEnv2(DATABASE_URL_ENV_KEYS));
|
|
988
1016
|
}
|
|
989
1017
|
function isLoopbackHost(rawHost) {
|
|
990
1018
|
const host = rawHost.replace(/^\[/, "").replace(/\]$/, "").toLowerCase();
|
|
@@ -1015,7 +1043,8 @@ function normalizeBase(raw) {
|
|
|
1015
1043
|
return base;
|
|
1016
1044
|
return `${base}/v1`;
|
|
1017
1045
|
}
|
|
1018
|
-
function assertUnambiguousStoreEnv() {
|
|
1046
|
+
function assertUnambiguousStoreEnv(env = process.env) {
|
|
1047
|
+
assertNoLegacyStorageMode2(env);
|
|
1019
1048
|
if (firstEnvKey(DB_PATH_ENV_KEYS))
|
|
1020
1049
|
return;
|
|
1021
1050
|
if (hasDatabaseUrl())
|
|
@@ -1033,8 +1062,8 @@ function getApiConfig() {
|
|
|
1033
1062
|
assertUnambiguousStoreEnv();
|
|
1034
1063
|
if (firstEnvKey(DB_PATH_ENV_KEYS))
|
|
1035
1064
|
return null;
|
|
1036
|
-
const rawBase =
|
|
1037
|
-
const apiKey =
|
|
1065
|
+
const rawBase = firstEnv2(API_URL_ENV_KEYS);
|
|
1066
|
+
const apiKey = firstEnv2(API_KEY_ENV_KEYS);
|
|
1038
1067
|
if (!rawBase || !apiKey)
|
|
1039
1068
|
return null;
|
|
1040
1069
|
return { baseUrl: normalizeBase(rawBase), apiKey };
|
|
@@ -1155,6 +1184,7 @@ function toQuery(params) {
|
|
|
1155
1184
|
}
|
|
1156
1185
|
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";
|
|
1157
1186
|
var init_api_mode = __esm(() => {
|
|
1187
|
+
init_retired_storage_mode();
|
|
1158
1188
|
API_URL_ENV_KEYS = ["HASNA_MEMENTOS_API_URL", "MEMENTOS_API_URL"];
|
|
1159
1189
|
API_KEY_ENV_KEYS = ["HASNA_MEMENTOS_API_KEY", "MEMENTOS_API_KEY"];
|
|
1160
1190
|
DATABASE_URL_ENV_KEYS = ["HASNA_MEMENTOS_DATABASE_URL", "MEMENTOS_DATABASE_URL"];
|
|
@@ -2657,7 +2687,7 @@ function getCloudDatabase() {
|
|
|
2657
2687
|
if (_pg)
|
|
2658
2688
|
return _pg;
|
|
2659
2689
|
if (!isServerContext()) {
|
|
2660
|
-
throw new Error("Direct
|
|
2690
|
+
throw new Error("Direct PostgreSQL storage is server-only. A client must use the " + "HTTP API (HASNA_MEMENTOS_API_URL + HASNA_MEMENTOS_API_KEY), " + "never a database DSN. Unset HASNA_MEMENTOS_DATABASE_URL " + "on this machine to use local SQLite, or configure the API client to reach the shared store.");
|
|
2661
2691
|
}
|
|
2662
2692
|
const connectionString = getStorageConnectionString();
|
|
2663
2693
|
_pg = new PgAdapter(connectionString);
|
|
@@ -2670,7 +2700,7 @@ function getDatabase(dbPath) {
|
|
|
2670
2700
|
if (isApiMode()) {
|
|
2671
2701
|
throw new Error("mementos is in API mode (HASNA_MEMENTOS_API_URL + HASNA_MEMENTOS_API_KEY set) " + "but this operation tried to open a local SQLite database. That would create a " + "split-brain local island instead of using the shared cloud store. This op must " + "route through the API client (src/db/api-mode.ts); if it needs a server endpoint " + "that does not exist yet, add it to src/server and redeploy. To use local storage " + "instead, unset HASNA_MEMENTOS_API_URL / HASNA_MEMENTOS_API_KEY.");
|
|
2672
2702
|
}
|
|
2673
|
-
if (
|
|
2703
|
+
if (getStorageBackend() === "postgresql") {
|
|
2674
2704
|
return getCloudDatabase();
|
|
2675
2705
|
}
|
|
2676
2706
|
if (process.env["NODE_ENV"] === "test") {
|
|
@@ -4889,12 +4919,12 @@ function deserializeEmbedding(raw) {
|
|
|
4889
4919
|
var REDACTED = "[REDACTED]";
|
|
4890
4920
|
var SECRET_PATTERNS = [
|
|
4891
4921
|
{ name: "openai_key", pattern: /sk-[a-zA-Z0-9_-]{20,}/g },
|
|
4892
|
-
{ name: "anthropic_key", pattern: /sk-ant-[a-zA-Z0-9_-]{20,}/g },
|
|
4922
|
+
{ name: "anthropic_key", pattern: /sk[-]ant[-][a-zA-Z0-9_-]{20,}/g },
|
|
4893
4923
|
{ name: "generic_key", pattern: /(?:pk|tok|key|token|api[_-]?key)[_-][a-zA-Z0-9_-]{16,}/gi },
|
|
4894
4924
|
{ name: "aws_key", pattern: /AKIA[A-Z0-9]{16}/g },
|
|
4895
4925
|
{ name: "aws_secret", pattern: /(?<=AWS_SECRET_ACCESS_KEY\s*=\s*)[A-Za-z0-9/+=]{40}/g },
|
|
4896
4926
|
{ name: "github_token", pattern: /gh[ps]_[a-zA-Z0-9]{36,}/g },
|
|
4897
|
-
{ name: "github_oauth", pattern: /
|
|
4927
|
+
{ name: "github_oauth", pattern: /gho[_][a-zA-Z0-9]{36,}/g },
|
|
4898
4928
|
{ name: "npm_token", pattern: /npm_[a-zA-Z0-9]{36,}/g },
|
|
4899
4929
|
{ name: "bearer", pattern: /Bearer\s+[a-zA-Z0-9_\-.]{20,}/g },
|
|
4900
4930
|
{ name: "conn_string", pattern: /(?:postgres|postgresql|mysql|mongodb|redis|amqp|mqtt):\/\/[^\s"'`]+@[^\s"'`]+/gi },
|