@hasna/mementos 0.14.46 → 0.14.48

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.
Files changed (39) hide show
  1. package/Dockerfile.package +30 -0
  2. package/bun.lock +405 -0
  3. package/dist/cli/index.js +2196 -857
  4. package/dist/db/database.d.ts.map +1 -1
  5. package/dist/db/pg-migrations.d.ts.map +1 -1
  6. package/dist/generated/storage-kit/health.d.ts +20 -0
  7. package/dist/generated/storage-kit/health.d.ts.map +1 -0
  8. package/dist/generated/storage-kit/index.d.ts +8 -0
  9. package/dist/generated/storage-kit/index.d.ts.map +1 -0
  10. package/dist/generated/storage-kit/migrations.d.ts +48 -0
  11. package/dist/generated/storage-kit/migrations.d.ts.map +1 -0
  12. package/dist/generated/storage-kit/mode.d.ts +48 -0
  13. package/dist/generated/storage-kit/mode.d.ts.map +1 -0
  14. package/dist/generated/storage-kit/pool.d.ts +34 -0
  15. package/dist/generated/storage-kit/pool.d.ts.map +1 -0
  16. package/dist/generated/storage-kit/query.d.ts +36 -0
  17. package/dist/generated/storage-kit/query.d.ts.map +1 -0
  18. package/dist/generated/storage-kit/tls.d.ts +26 -0
  19. package/dist/generated/storage-kit/tls.d.ts.map +1 -0
  20. package/dist/index.js +1892 -804
  21. package/dist/mcp/index.js +1933 -803
  22. package/dist/pg-sync-worker.d.ts +2 -0
  23. package/dist/pg-sync-worker.d.ts.map +1 -0
  24. package/dist/pg-sync-worker.js +47 -0
  25. package/dist/sdk/index.d.ts +27 -0
  26. package/dist/sdk/index.d.ts.map +1 -1
  27. package/dist/sdk/index.js +25 -6
  28. package/dist/server/auth.d.ts +11 -0
  29. package/dist/server/auth.d.ts.map +1 -0
  30. package/dist/server/index.d.ts.map +1 -1
  31. package/dist/server/index.js +2367 -847
  32. package/dist/server/openapi.d.ts +2 -0
  33. package/dist/server/openapi.d.ts.map +1 -0
  34. package/dist/storage.d.ts +59 -4
  35. package/dist/storage.d.ts.map +1 -1
  36. package/dist/storage.js +147 -70
  37. package/docker-entrypoint.sh +46 -0
  38. package/hasna.contract.json +16 -0
  39. package/package.json +7 -3
@@ -0,0 +1,2 @@
1
+ export declare function buildOpenApiDocument(version: string): Record<string, unknown>;
2
+ //# sourceMappingURL=openapi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openapi.d.ts","sourceRoot":"","sources":["../../src/server/openapi.ts"],"names":[],"mappings":"AAeA,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAsE7E"}
package/dist/storage.d.ts CHANGED
@@ -32,20 +32,58 @@ export declare class SqliteAdapter implements DbAdapter {
32
32
  transaction<T>(fn: () => T): T;
33
33
  get raw(): Database;
34
34
  }
35
+ export declare function translateSql(sql: string): string;
35
36
  export declare function shouldUsePgSsl(connectionString: string): boolean;
37
+ /** Build a pg Pool with adapter-controlled SSL from a connection string. */
38
+ export declare function makePool(connectionString: string): Pool;
39
+ interface SyncQueryResult {
40
+ rows: any[];
41
+ rowCount: number;
42
+ }
43
+ /**
44
+ * Synchronous Postgres access backed by a worker thread (see
45
+ * `pg-sync-worker.ts`). The worker owns one long-lived `pg.Client` and runs
46
+ * queries on its own event loop; the main thread blocks on `Atomics.wait`
47
+ * against a SharedArrayBuffer until the worker writes the response. This is the
48
+ * only way to expose a truly synchronous API (which the entire mementos data
49
+ * layer requires) over async pg I/O without deadlocking the main event loop.
50
+ */
51
+ export declare class PgSyncPool {
52
+ private readonly worker;
53
+ private readonly status;
54
+ private readonly data;
55
+ private closed;
56
+ private lastError;
57
+ private static readonly DATA_BYTES;
58
+ private static readonly QUERY_TIMEOUT_MS;
59
+ /**
60
+ * Resolve the worker entry file. `storage` is bundled into several entry
61
+ * points at different depths (dist/cli, dist/mcp, dist/server) as well as run
62
+ * directly from source, so probe candidate locations relative to this module.
63
+ */
64
+ private static resolveWorkerPath;
65
+ constructor(connectionString: string);
66
+ query(sql: string, params: any[]): SyncQueryResult;
67
+ end(): void;
68
+ }
36
69
  export declare class PgAdapter implements DbAdapter {
37
70
  private readonly pool;
38
71
  constructor(connectionString: string);
39
- constructor(pool: Pool);
40
- private runSync;
72
+ constructor(pool: PgSyncPool);
41
73
  run(sql: string, ...params: any[]): RunResult;
42
74
  get(sql: string, ...params: any[]): any;
43
75
  all(sql: string, ...params: any[]): any[];
44
76
  exec(sql: string): void;
45
77
  prepare(sql: string): PreparedStatement;
78
+ /**
79
+ * Bun-sqlite-style `query()` shim so the CLI/MCP/server call sites that do
80
+ * `db.query(sql).get(...)` / `.all(...)` / `.run(...)` work unchanged against
81
+ * Postgres in cloud mode. Behaves like {@link prepare}.
82
+ */
83
+ query(sql: string): PreparedStatement;
46
84
  close(): void;
47
85
  transaction<T>(fn: () => T): T;
48
- get raw(): Pool;
86
+ get raw(): PgSyncPool;
49
87
  }
50
88
  export declare class PgAdapterAsync {
51
89
  private readonly pool;
@@ -59,7 +97,23 @@ export declare class PgAdapterAsync {
59
97
  transaction<T>(fn: (client: PoolClient) => Promise<T>): Promise<T>;
60
98
  get raw(): Pool;
61
99
  }
62
- export type StorageMode = "local" | "remote" | "hybrid";
100
+ /**
101
+ * Canonical storage-mode axis (aligned with the shared cloud-runtime contract).
102
+ *
103
+ * - `local` — SQLite on disk. Default. Unchanged behavior.
104
+ * - `cloud` — pure remote: reads AND writes go directly to cloud Postgres.
105
+ *
106
+ * The legacy values `remote` and `hybrid` are still accepted as INPUT (env or
107
+ * config file) for backwards compatibility, but they are DEPRECATED aliases
108
+ * that normalize to `cloud`. See {@link DeprecatedStorageMode}. The historical
109
+ * local<->remote sync engine (the "hybrid sync path") is retained only for
110
+ * back-compat and is explicitly NOT the fleet cutover path.
111
+ */
112
+ export type StorageMode = "local" | "cloud";
113
+ /** Deprecated storage-mode aliases accepted as input; all map to `cloud`. */
114
+ export type DeprecatedStorageMode = "remote" | "hybrid";
115
+ /** Any value accepted from env/config for the storage mode. */
116
+ export type StorageModeInput = StorageMode | DeprecatedStorageMode;
63
117
  export declare const MEMENTOS_STORAGE_TABLES: readonly ["projects", "agents", "machines", "sessions", "entities", "memories", "relations", "entity_memories", "memory_tags", "memory_versions", "memory_embeddings", "tool_events", "resource_locks", "memory_ratings"];
64
118
  export declare const STORAGE_TABLES: readonly ["projects", "agents", "machines", "sessions", "entities", "memories", "relations", "entity_memories", "memory_tags", "memory_versions", "memory_embeddings", "tool_events", "resource_locks", "memory_ratings"];
65
119
  export type MementosStorageTable = (typeof MEMENTOS_STORAGE_TABLES)[number];
@@ -154,4 +208,5 @@ export declare function getSyncMetaAll(db: DbAdapter): SyncMeta[];
154
208
  export declare function getSyncMetaForTable(db: DbAdapter, table: string): SyncMeta | null;
155
209
  export declare function resetSyncMeta(db: DbAdapter, table: string): void;
156
210
  export declare function resetAllSyncMeta(db: DbAdapter): void;
211
+ export {};
157
212
  //# sourceMappingURL=storage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"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"}
package/dist/storage.js CHANGED
@@ -51,6 +51,8 @@ import { Database } from "bun:sqlite";
51
51
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
52
52
  import { homedir } from "os";
53
53
  import { join } from "path";
54
+ import { fileURLToPath } from "url";
55
+ import { Worker } from "worker_threads";
54
56
  import pg from "pg";
55
57
  function normalizeParams(params) {
56
58
  const flat = params.length === 1 && Array.isArray(params[0]) ? params[0] : params;
@@ -113,13 +115,15 @@ class SqliteAdapter {
113
115
  function translateSql(sql) {
114
116
  let parameterIndex = 0;
115
117
  let translated = sql.replace(/\?/g, () => `$${++parameterIndex}`);
116
- translated = translated.replace(/datetime\s*\(\s*'now'\s*\)/gi, "NOW()");
118
+ const ISO_FMT = `'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"'`;
119
+ translated = translated.replace(/datetime\s*\(\s*'now'\s*\)/gi, `to_char(now() AT TIME ZONE 'UTC', ${ISO_FMT})`);
117
120
  translated = translated.replace(/datetime\s*\(\s*'now'\s*,\s*'(-?\d+)\s+(minutes?|hours?|days?|seconds?)'\s*\)/gi, (_match, amount, unit) => {
118
121
  const parsed = parseInt(String(amount), 10);
119
122
  const absolute = Math.abs(parsed);
120
123
  const normalizedUnit = String(unit).toLowerCase().replace(/s$/, "");
121
124
  const pluralUnit = absolute === 1 ? normalizedUnit : `${normalizedUnit}s`;
122
- return parsed < 0 ? `NOW() - INTERVAL '${absolute} ${pluralUnit}'` : `NOW() + INTERVAL '${absolute} ${pluralUnit}'`;
125
+ const op = parsed < 0 ? "-" : "+";
126
+ return `to_char((now() ${op} INTERVAL '${absolute} ${pluralUnit}') AT TIME ZONE 'UTC', ${ISO_FMT})`;
123
127
  });
124
128
  translated = translated.replace(/lower\s*\(\s*hex\s*\(\s*randomblob\s*\(\s*\d+\s*\)\s*\)\s*\)/gi, "gen_random_uuid()::text");
125
129
  translated = translated.replace(/\bIFNULL\s*\(/gi, "COALESCE(");
@@ -128,6 +132,7 @@ function translateSql(sql) {
128
132
  translated = translated.replace(/;?\s*$/, " ON CONFLICT DO NOTHING");
129
133
  }
130
134
  translated = translated.replace(/INSERT\s+OR\s+REPLACE\s+INTO/gi, "INSERT INTO");
135
+ translated = translated.replace(/COALESCE\s*\(\s*pinned\s*,\s*0\s*\)/gi, "COALESCE(pinned, FALSE)");
131
136
  return translated;
132
137
  }
133
138
  function shouldUsePgSsl(connectionString) {
@@ -142,62 +147,57 @@ function shouldUsePgSsl(connectionString) {
142
147
  return ["1", "true", "yes", "on", "require"].includes(ssl ?? "") || ["require", "verify-ca", "verify-full"].includes(sslMode ?? "");
143
148
  }
144
149
  function sslConfigFor(connectionString) {
145
- return shouldUsePgSsl(connectionString) || undefined;
150
+ if (!shouldUsePgSsl(connectionString))
151
+ return;
152
+ let sslMode;
153
+ try {
154
+ sslMode = new URL(connectionString).searchParams.get("sslmode")?.trim().toLowerCase() ?? undefined;
155
+ } catch {
156
+ sslMode = new URLSearchParams(connectionString.split("?", 2)[1] ?? "").get("sslmode")?.trim().toLowerCase() ?? undefined;
157
+ }
158
+ if (sslMode === "verify-ca" || sslMode === "verify-full") {
159
+ return { rejectUnauthorized: true };
160
+ }
161
+ return { rejectUnauthorized: false };
162
+ }
163
+ function stripSslParams(connectionString) {
164
+ try {
165
+ const url = new URL(connectionString);
166
+ url.searchParams.delete("ssl");
167
+ url.searchParams.delete("sslmode");
168
+ return url.toString();
169
+ } catch {
170
+ return connectionString;
171
+ }
172
+ }
173
+ function makePool(connectionString) {
174
+ return new pg.Pool({
175
+ connectionString: stripSslParams(connectionString),
176
+ ssl: sslConfigFor(connectionString)
177
+ });
146
178
  }
147
179
 
148
180
  class PgAdapter {
149
181
  pool;
150
182
  constructor(input) {
151
- this.pool = typeof input === "string" ? new pg.Pool({ connectionString: input, ssl: sslConfigFor(input) }) : input;
152
- }
153
- runSync(fn) {
154
- let result;
155
- let error;
156
- let done = false;
157
- fn().then((value) => {
158
- result = value;
159
- done = true;
160
- }).catch((caught) => {
161
- error = caught;
162
- done = true;
163
- });
164
- const deadline = Date.now() + 30000;
165
- while (!done && Date.now() < deadline) {
166
- Bun.sleepSync(1);
167
- }
168
- if (error) {
169
- throw error;
170
- }
171
- if (!done) {
172
- throw new Error("PostgreSQL query timed out after 30s");
173
- }
174
- return result;
183
+ this.pool = typeof input === "string" ? new PgSyncPool(input) : input;
175
184
  }
176
185
  run(sql, ...params) {
177
- return this.runSync(async () => {
178
- const result = await this.pool.query(translateSql(sql), normalizeParams(params));
179
- return {
180
- changes: result.rowCount ?? 0,
181
- lastInsertRowid: result.rows?.[0]?.id ?? 0
182
- };
183
- });
186
+ const result = this.pool.query(translateSql(sql), normalizeParams(params));
187
+ return {
188
+ changes: result.rowCount ?? 0,
189
+ lastInsertRowid: result.rows?.[0]?.id ?? 0
190
+ };
184
191
  }
185
192
  get(sql, ...params) {
186
- return this.runSync(async () => {
187
- const result = await this.pool.query(translateSql(sql), normalizeParams(params));
188
- return result.rows[0] ?? null;
189
- });
193
+ const result = this.pool.query(translateSql(sql), normalizeParams(params));
194
+ return result.rows[0] ?? null;
190
195
  }
191
196
  all(sql, ...params) {
192
- return this.runSync(async () => {
193
- const result = await this.pool.query(translateSql(sql), normalizeParams(params));
194
- return result.rows;
195
- });
197
+ return this.pool.query(translateSql(sql), normalizeParams(params)).rows;
196
198
  }
197
199
  exec(sql) {
198
- this.runSync(async () => {
199
- await this.pool.query(sql);
200
- });
200
+ this.pool.query(sql, []);
201
201
  }
202
202
  prepare(sql) {
203
203
  return {
@@ -207,29 +207,24 @@ class PgAdapter {
207
207
  finalize: () => {}
208
208
  };
209
209
  }
210
+ query(sql) {
211
+ return this.prepare(sql);
212
+ }
210
213
  close() {
211
- this.runSync(async () => {
212
- await this.pool.end();
213
- });
214
+ this.pool.end();
214
215
  }
215
216
  transaction(fn) {
216
- return this.runSync(async () => {
217
- const client = await this.pool.connect();
218
- const originalQuery = this.pool.query.bind(this.pool);
217
+ this.pool.query("BEGIN", []);
218
+ try {
219
+ const value = fn();
220
+ this.pool.query("COMMIT", []);
221
+ return value;
222
+ } catch (error) {
219
223
  try {
220
- await client.query("BEGIN");
221
- this.pool.query = client.query.bind(client);
222
- const value = fn();
223
- await client.query("COMMIT");
224
- return value;
225
- } catch (error) {
226
- await client.query("ROLLBACK");
227
- throw error;
228
- } finally {
229
- this.pool.query = originalQuery;
230
- client.release();
231
- }
232
- });
224
+ this.pool.query("ROLLBACK", []);
225
+ } catch {}
226
+ throw error;
227
+ }
233
228
  }
234
229
  get raw() {
235
230
  return this.pool;
@@ -239,7 +234,7 @@ class PgAdapter {
239
234
  class PgAdapterAsync {
240
235
  pool;
241
236
  constructor(input) {
242
- this.pool = typeof input === "string" ? new pg.Pool({ connectionString: input, ssl: sslConfigFor(input) }) : input;
237
+ this.pool = typeof input === "string" ? makePool(input) : input;
243
238
  }
244
239
  async run(sql, ...params) {
245
240
  const result = await this.pool.query(translateSql(sql), normalizeParams(params));
@@ -284,13 +279,23 @@ function readEnv(name) {
284
279
  const value = process.env[name]?.trim();
285
280
  return value ? value : null;
286
281
  }
282
+ function warnDeprecatedStorageMode(alias) {
283
+ if (warnedDeprecatedModes.has(alias))
284
+ return;
285
+ warnedDeprecatedModes.add(alias);
286
+ 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" });
287
+ }
287
288
  function normalizeStorageMode(value) {
288
289
  if (!value)
289
290
  return null;
290
291
  const normalized = value.trim().toLowerCase();
291
- if (normalized === "local" || normalized === "remote" || normalized === "hybrid") {
292
+ if (normalized === "local" || normalized === "cloud") {
292
293
  return normalized;
293
294
  }
295
+ if (normalized === "remote" || normalized === "hybrid") {
296
+ warnDeprecatedStorageMode(normalized);
297
+ return "cloud";
298
+ }
294
299
  return null;
295
300
  }
296
301
  function readConfigFile() {
@@ -357,7 +362,7 @@ function getStorageConfig() {
357
362
  if (modeOverride) {
358
363
  merged.mode = modeOverride;
359
364
  } else if (envConnectionString && merged.mode === "local") {
360
- merged.mode = "hybrid";
365
+ merged.mode = "cloud";
361
366
  }
362
367
  return merged;
363
368
  }
@@ -379,7 +384,7 @@ function getStorageStatus() {
379
384
  const mode = getStorageConfig().mode;
380
385
  const databaseUrl = getStorageDatabaseUrl();
381
386
  const issues = [];
382
- if ((mode === "remote" || mode === "hybrid") && !databaseUrl) {
387
+ if (mode === "cloud" && !databaseUrl) {
383
388
  issues.push(`Missing ${MEMENTOS_STORAGE_ENV.databaseUrl}`);
384
389
  }
385
390
  return {
@@ -387,7 +392,7 @@ function getStorageStatus() {
387
392
  service: "mementos",
388
393
  mode,
389
394
  local_default: mode === "local",
390
- remote_enabled: mode === "remote" || mode === "hybrid",
395
+ remote_enabled: mode === "cloud",
391
396
  database: {
392
397
  configured: Boolean(databaseUrl),
393
398
  redacted_url: redactDatabaseUrl(databaseUrl)
@@ -569,7 +574,7 @@ function resetAllSyncMeta(db) {
569
574
  ensureSyncMetaTable(db);
570
575
  db.run("DELETE FROM _sync_meta");
571
576
  }
572
- var MEMENTOS_STORAGE_TABLES, STORAGE_TABLES, MEMENTOS_STORAGE_ENV, MEMENTOS_STORAGE_FALLBACK_ENV, DEFAULT_STORAGE_CONFIG, STORAGE_CONFIG_DIR, STORAGE_CONFIG_PATH, DATABASE_ENV_NAMES, MODE_ENV_NAMES, getMementosStorageStatus, SYNC_EXCLUDED_TABLE_PATTERNS, SYNC_META_TABLE_SQL = `
577
+ var PgSyncPool, MEMENTOS_STORAGE_TABLES, STORAGE_TABLES, MEMENTOS_STORAGE_ENV, MEMENTOS_STORAGE_FALLBACK_ENV, DEFAULT_STORAGE_CONFIG, STORAGE_CONFIG_DIR, STORAGE_CONFIG_PATH, DATABASE_ENV_NAMES, MODE_ENV_NAMES, warnedDeprecatedModes, getMementosStorageStatus, SYNC_EXCLUDED_TABLE_PATTERNS, SYNC_META_TABLE_SQL = `
573
578
  CREATE TABLE IF NOT EXISTS _sync_meta (
574
579
  table_name TEXT PRIMARY KEY,
575
580
  last_synced_at TEXT,
@@ -577,6 +582,74 @@ CREATE TABLE IF NOT EXISTS _sync_meta (
577
582
  direction TEXT DEFAULT 'push'
578
583
  )`;
579
584
  var init_storage = __esm(() => {
585
+ PgSyncPool = class PgSyncPool {
586
+ worker;
587
+ status;
588
+ data;
589
+ closed = false;
590
+ lastError = null;
591
+ static DATA_BYTES = 128 * 1024 * 1024;
592
+ static QUERY_TIMEOUT_MS = 60000;
593
+ static resolveWorkerPath() {
594
+ const ext = import.meta.url.endsWith(".ts") ? ".ts" : ".js";
595
+ const here = fileURLToPath(new URL(".", import.meta.url));
596
+ const candidates = [
597
+ join(here, `pg-sync-worker${ext}`),
598
+ join(here, "..", `pg-sync-worker${ext}`),
599
+ join(here, "..", "..", `pg-sync-worker${ext}`)
600
+ ];
601
+ for (const candidate of candidates) {
602
+ if (existsSync(candidate))
603
+ return candidate;
604
+ }
605
+ return candidates[0];
606
+ }
607
+ constructor(connectionString) {
608
+ const control = new SharedArrayBuffer(8);
609
+ const dataSab = new SharedArrayBuffer(PgSyncPool.DATA_BYTES);
610
+ this.status = new Int32Array(control);
611
+ this.data = new Uint8Array(dataSab);
612
+ this.worker = new Worker(PgSyncPool.resolveWorkerPath(), {
613
+ workerData: {
614
+ dsn: stripSslParams(connectionString),
615
+ ssl: sslConfigFor(connectionString),
616
+ control,
617
+ data: dataSab
618
+ }
619
+ });
620
+ this.worker.unref();
621
+ this.worker.on("error", (err) => {
622
+ this.lastError = err;
623
+ });
624
+ }
625
+ query(sql, params) {
626
+ if (this.closed)
627
+ throw new Error("PgSyncPool is closed");
628
+ if (this.lastError)
629
+ throw this.lastError;
630
+ Atomics.store(this.status, 0, 0);
631
+ this.worker.postMessage({ sql, params });
632
+ const waitResult = Atomics.wait(this.status, 0, 0, PgSyncPool.QUERY_TIMEOUT_MS);
633
+ const code = Atomics.load(this.status, 0);
634
+ if (code === 0 || waitResult === "timed-out") {
635
+ if (this.lastError)
636
+ throw this.lastError;
637
+ throw new Error("PostgreSQL query timed out after 60s");
638
+ }
639
+ const len = Atomics.load(this.status, 1);
640
+ const payload = JSON.parse(new TextDecoder().decode(this.data.subarray(0, len)));
641
+ if (code === 2) {
642
+ throw new Error(payload.message ?? "PostgreSQL error");
643
+ }
644
+ return payload;
645
+ }
646
+ end() {
647
+ if (this.closed)
648
+ return;
649
+ this.closed = true;
650
+ this.worker.terminate();
651
+ }
652
+ };
580
653
  MEMENTOS_STORAGE_TABLES = [
581
654
  "projects",
582
655
  "agents",
@@ -627,6 +700,7 @@ var init_storage = __esm(() => {
627
700
  { name: MEMENTOS_STORAGE_ENV.mode, deprecated: false },
628
701
  { name: MEMENTOS_STORAGE_FALLBACK_ENV.mode, deprecated: false }
629
702
  ];
703
+ warnedDeprecatedModes = new Set;
630
704
  getMementosStorageStatus = getStorageStatus;
631
705
  SYNC_EXCLUDED_TABLE_PATTERNS = [
632
706
  /^sqlite_/,
@@ -639,10 +713,12 @@ var init_storage = __esm(() => {
639
713
  init_storage();
640
714
 
641
715
  export {
716
+ translateSql,
642
717
  shouldUsePgSsl,
643
718
  saveStorageConfig,
644
719
  resetSyncMeta,
645
720
  resetAllSyncMeta,
721
+ makePool,
646
722
  listSqliteTables,
647
723
  isSyncExcludedTable,
648
724
  incrementalSyncPush,
@@ -663,6 +739,7 @@ export {
663
739
  SqliteAdapter,
664
740
  SYNC_EXCLUDED_TABLE_PATTERNS,
665
741
  STORAGE_TABLES,
742
+ PgSyncPool,
666
743
  PgAdapterAsync,
667
744
  PgAdapter,
668
745
  MEMENTOS_STORAGE_TABLES,
@@ -0,0 +1,46 @@
1
+ #!/bin/sh
2
+ # =============================================================================
3
+ # mementos container entrypoint
4
+ # -----------------------------------------------------------------------------
5
+ # Bridges the hasna-app Terraform module's injected env (DATABASE_URL,
6
+ # API_KEY_SIGNING_SECRET, PORT) to mementos' native env, forces pure-remote
7
+ # cloud storage, and binds to all interfaces so the ALB target group is
8
+ # reachable. Migrations run against the OWNER DSN (DDL); the long-running
9
+ # service runs against the least-privilege APP DSN.
10
+ # =============================================================================
11
+ set -e
12
+
13
+ # Bind on 0.0.0.0 inside the container (default is 127.0.0.1 for local dev).
14
+ export MEMENTOS_HOST="${MEMENTOS_HOST:-0.0.0.0}"
15
+
16
+ # Amendment A1 — serve/CLI read+write RDS directly.
17
+ export HASNA_MEMENTOS_STORAGE_MODE="${HASNA_MEMENTOS_STORAGE_MODE:-cloud}"
18
+
19
+ # Select the DSN by workload: migrations need the owner role (DDL); everything
20
+ # else uses the app role. MIGRATION_DATABASE_URL is optional; falls back to
21
+ # DATABASE_URL when unset.
22
+ case " $* " in
23
+ *" migrate "*)
24
+ export HASNA_MEMENTOS_DATABASE_URL="${HASNA_MEMENTOS_DATABASE_URL:-${MIGRATION_DATABASE_URL:-${DATABASE_URL}}}"
25
+ ;;
26
+ *)
27
+ export HASNA_MEMENTOS_DATABASE_URL="${HASNA_MEMENTOS_DATABASE_URL:-${DATABASE_URL}}"
28
+ ;;
29
+ esac
30
+
31
+ # Contracts auth reads API_KEY_SIGNING_SECRET directly; also expose the
32
+ # app-scoped alias for the issuer/CLI.
33
+ export HASNA_MEMENTOS_API_SIGNING_KEY="${HASNA_MEMENTOS_API_SIGNING_KEY:-${API_KEY_SIGNING_SECRET}}"
34
+
35
+ # Map published bin names to their dist entrypoints.
36
+ cmd="${1:-mementos-serve}"
37
+ [ "$#" -gt 0 ] && shift || true
38
+ case "$cmd" in
39
+ mementos-serve) set -- bun /app/dist/server/index.js "$@" ;;
40
+ mementos-mcp) set -- bun /app/dist/mcp/index.js "$@" ;;
41
+ mementos) set -- bun /app/dist/cli/index.js "$@" ;;
42
+ bun|/*) set -- "$cmd" "$@" ;;
43
+ *) set -- "$cmd" "$@" ;;
44
+ esac
45
+
46
+ exec "$@"
@@ -0,0 +1,16 @@
1
+ {
2
+ "$schema": "./node_modules/@hasna/contracts/dist/hasna.contract.schema.json",
3
+ "schema": "hasna.service_contract.v1",
4
+ "name": "mementos",
5
+ "class": "service",
6
+ "contractVersion": "v1",
7
+ "kitVersion": "0.4.1",
8
+ "description": "Universal memory system for AI agents — CLI + MCP server + REST serve API + typed SDK. self_hosted service backed by pure-remote Postgres (Amendment A1).",
9
+ "bins": ["mementos", "mementos-mcp", "mementos-serve"],
10
+ "storage": {
11
+ "mode": "cloud",
12
+ "envPrefix": "HASNA_MEMENTOS_",
13
+ "aliasEnvPrefix": "MEMENTOS_",
14
+ "databaseUrlSecretRef": "hasna/oss/mementos/database-url"
15
+ }
16
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/mementos",
3
- "version": "0.14.46",
3
+ "version": "0.14.48",
4
4
  "description": "Universal memory system for AI agents - CLI + MCP server + library API",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -27,12 +27,16 @@
27
27
  "files": [
28
28
  "dist",
29
29
  "dashboard/dist",
30
+ "Dockerfile.package",
31
+ "docker-entrypoint.sh",
32
+ "bun.lock",
33
+ "hasna.contract.json",
30
34
  "LICENSE",
31
35
  "README.md"
32
36
  ],
33
37
  "scripts": {
34
38
  "clean": "rm -rf dist",
35
- "build": "bun run clean && bun build src/cli/index.tsx --outdir dist/cli --target bun --external ink --external react --external chalk --external @modelcontextprotocol/sdk --external @hasna/contracts --external @hasna/contracts/schemas --external pg && bun build src/mcp/index.ts --outdir dist/mcp --target bun --external @modelcontextprotocol/sdk --external @hasna/contracts --external @hasna/contracts/schemas --external pg && bun build src/server/index.ts --outdir dist/server --target bun --external @hasna/contracts --external @hasna/contracts/schemas --external pg && bun build src/index.ts src/storage.ts --outdir dist --target bun --external @hasna/contracts --external @hasna/contracts/schemas --external pg && bun build src/sdk/index.ts --outdir dist/sdk --target bun && tsc --emitDeclarationOnly --outDir dist",
39
+ "build": "bun run clean && bun build src/cli/index.tsx --outdir dist/cli --target bun --external ink --external react --external chalk --external @modelcontextprotocol/sdk --external @hasna/contracts --external @hasna/contracts/schemas --external @hasna/contracts/auth --external pg && bun build src/mcp/index.ts --outdir dist/mcp --target bun --external @modelcontextprotocol/sdk --external @hasna/contracts --external @hasna/contracts/schemas --external @hasna/contracts/auth --external pg && bun build src/server/index.ts --outdir dist/server --target bun --external @hasna/contracts --external @hasna/contracts/schemas --external @hasna/contracts/auth --external pg && bun build src/index.ts src/storage.ts src/pg-sync-worker.ts --outdir dist --target bun --external @hasna/contracts --external @hasna/contracts/schemas --external @hasna/contracts/auth --external pg && bun build src/sdk/index.ts --outdir dist/sdk --target bun && tsc --emitDeclarationOnly --outDir dist",
36
40
  "prepare": "bun run build",
37
41
  "prepublishOnly": "bun run typecheck && bun run test",
38
42
  "typecheck": "tsc --noEmit",
@@ -75,7 +79,7 @@
75
79
  "@ai-sdk/anthropic": "^3.0.82",
76
80
  "@ai-sdk/openai": "^3.0.69",
77
81
  "@ai-sdk/openai-compatible": "^2.0.48",
78
- "@hasna/contracts": "^0.2.2",
82
+ "@hasna/contracts": "0.4.1",
79
83
  "@hasna/events": "^0.1.6",
80
84
  "@modelcontextprotocol/sdk": "^1.12.1",
81
85
  "ai": "^6.0.199",