@shadowforge0/aquifer-memory 1.7.0 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +8 -0
- package/README.md +66 -0
- package/aquifer.config.example.json +19 -0
- package/consumers/cli.js +217 -14
- package/consumers/codex-active-checkpoint.js +186 -0
- package/consumers/codex-current-memory.js +106 -0
- package/consumers/codex-handoff.js +442 -3
- package/consumers/codex.js +164 -107
- package/consumers/mcp.js +144 -6
- package/consumers/shared/config.js +60 -1
- package/consumers/shared/factory.js +10 -3
- package/core/aquifer.js +351 -840
- package/core/backends/capabilities.js +89 -0
- package/core/backends/local.js +430 -0
- package/core/legacy-bootstrap.js +140 -0
- package/core/mcp-manifest.js +66 -2
- package/core/memory-promotion.js +157 -26
- package/core/memory-recall.js +341 -22
- package/core/memory-records.js +128 -8
- package/core/memory-serving.js +132 -0
- package/core/postgres-migrations.js +533 -0
- package/core/public-session-filter.js +40 -0
- package/core/recall-runtime.js +115 -0
- package/core/scope-attribution.js +279 -0
- package/core/session-checkpoint-producer.js +412 -0
- package/core/session-checkpoints.js +432 -0
- package/core/session-finalization.js +82 -1
- package/core/storage-checkpoints.js +546 -0
- package/core/storage.js +121 -8
- package/docs/setup.md +22 -0
- package/package.json +8 -4
- package/schema/014-v1-checkpoint-runs.sql +349 -0
- package/schema/015-v1-evidence-items.sql +92 -0
- package/schema/016-v1-evidence-ref-multi-item.sql +19 -0
- package/schema/017-v1-memory-record-embeddings.sql +25 -0
- package/schema/018-v1-finalization-candidate-envelope.sql +39 -0
- package/scripts/codex-checkpoint-commands.js +464 -0
- package/scripts/codex-checkpoint-runtime.js +520 -0
- package/scripts/codex-recovery.js +105 -0
|
@@ -8,6 +8,17 @@ const path = require('path');
|
|
|
8
8
|
// ---------------------------------------------------------------------------
|
|
9
9
|
|
|
10
10
|
const DEFAULTS = {
|
|
11
|
+
storage: {
|
|
12
|
+
backend: 'postgres',
|
|
13
|
+
postgres: {
|
|
14
|
+
url: null,
|
|
15
|
+
max: null,
|
|
16
|
+
idleTimeoutMs: null,
|
|
17
|
+
},
|
|
18
|
+
local: {
|
|
19
|
+
path: '.aquifer/aquifer.local.json',
|
|
20
|
+
},
|
|
21
|
+
},
|
|
11
22
|
db: { url: null, max: 10, idleTimeoutMs: 30000 },
|
|
12
23
|
schema: 'aquifer',
|
|
13
24
|
tenantId: 'default',
|
|
@@ -45,6 +56,16 @@ const DEFAULTS = {
|
|
|
45
56
|
activeScopeKey: null,
|
|
46
57
|
activeScopePath: null,
|
|
47
58
|
},
|
|
59
|
+
codex: {
|
|
60
|
+
checkpoint: {
|
|
61
|
+
checkIntervalMs: null,
|
|
62
|
+
checkIntervalMinutes: 10,
|
|
63
|
+
everyMessages: 20,
|
|
64
|
+
everyUserMessages: null,
|
|
65
|
+
quietMs: 3000,
|
|
66
|
+
claimTtlMs: 60000,
|
|
67
|
+
},
|
|
68
|
+
},
|
|
48
69
|
rerank: {
|
|
49
70
|
enabled: false,
|
|
50
71
|
provider: null, // 'tei' | 'jina' | 'openrouter' | 'custom'
|
|
@@ -69,6 +90,10 @@ const DEFAULTS = {
|
|
|
69
90
|
// ---------------------------------------------------------------------------
|
|
70
91
|
|
|
71
92
|
const ENV_MAP = [
|
|
93
|
+
['AQUIFER_BACKEND', 'storage.backend'],
|
|
94
|
+
['AQUIFER_STORAGE_BACKEND', 'storage.backend'],
|
|
95
|
+
['AQUIFER_POSTGRES_URL', 'storage.postgres.url'],
|
|
96
|
+
['AQUIFER_LOCAL_PATH', 'storage.local.path'],
|
|
72
97
|
['DATABASE_URL', 'db.url'],
|
|
73
98
|
['AQUIFER_DB_URL', 'db.url'],
|
|
74
99
|
['AQUIFER_DB_MAX', 'db.max', Number],
|
|
@@ -95,6 +120,12 @@ const ENV_MAP = [
|
|
|
95
120
|
['AQUIFER_MEMORY_SERVING_MODE', 'memory.servingMode'],
|
|
96
121
|
['AQUIFER_MEMORY_ACTIVE_SCOPE_KEY', 'memory.activeScopeKey'],
|
|
97
122
|
['AQUIFER_MEMORY_ACTIVE_SCOPE_PATH', 'memory.activeScopePath'],
|
|
123
|
+
['AQUIFER_CODEX_CHECKPOINT_CHECK_INTERVAL_MS', 'codex.checkpoint.checkIntervalMs', Number],
|
|
124
|
+
['AQUIFER_CODEX_CHECKPOINT_CHECK_INTERVAL_MINUTES', 'codex.checkpoint.checkIntervalMinutes', Number],
|
|
125
|
+
['AQUIFER_CODEX_CHECKPOINT_EVERY_MESSAGES', 'codex.checkpoint.everyMessages', Number],
|
|
126
|
+
['AQUIFER_CODEX_CHECKPOINT_EVERY_USER_MESSAGES', 'codex.checkpoint.everyUserMessages', Number],
|
|
127
|
+
['AQUIFER_CODEX_CHECKPOINT_QUIET_MS', 'codex.checkpoint.quietMs', Number],
|
|
128
|
+
['AQUIFER_CODEX_CHECKPOINT_CLAIM_TTL_MS', 'codex.checkpoint.claimTtlMs', Number],
|
|
98
129
|
['AQUIFER_RERANK_ENABLED', 'rerank.enabled', Boolean],
|
|
99
130
|
['AQUIFER_RERANK_PROVIDER', 'rerank.provider'],
|
|
100
131
|
['AQUIFER_RERANK_BASE_URL', 'rerank.baseUrl'],
|
|
@@ -141,6 +172,34 @@ function coerceEnvValue(raw, type) {
|
|
|
141
172
|
return raw;
|
|
142
173
|
}
|
|
143
174
|
|
|
175
|
+
function normalizeStorageConfig(config) {
|
|
176
|
+
const storage = config.storage && typeof config.storage === 'object' ? config.storage : {};
|
|
177
|
+
const backend = String(storage.backend || 'postgres').trim().toLowerCase();
|
|
178
|
+
if (backend !== 'postgres' && backend !== 'local') {
|
|
179
|
+
throw new Error(`Invalid Aquifer backend: "${storage.backend}". Must be one of: postgres, local`);
|
|
180
|
+
}
|
|
181
|
+
const postgres = {
|
|
182
|
+
...DEFAULTS.storage.postgres,
|
|
183
|
+
...(storage.postgres || {}),
|
|
184
|
+
};
|
|
185
|
+
const local = {
|
|
186
|
+
...DEFAULTS.storage.local,
|
|
187
|
+
...(storage.local || {}),
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
if (postgres.url) config.db.url = postgres.url;
|
|
191
|
+
if (config.db.url && !postgres.url) postgres.url = config.db.url;
|
|
192
|
+
if (postgres.max !== null && postgres.max !== undefined) config.db.max = postgres.max;
|
|
193
|
+
if (postgres.idleTimeoutMs !== null && postgres.idleTimeoutMs !== undefined) {
|
|
194
|
+
config.db.idleTimeoutMs = postgres.idleTimeoutMs;
|
|
195
|
+
}
|
|
196
|
+
postgres.max = config.db.max;
|
|
197
|
+
postgres.idleTimeoutMs = config.db.idleTimeoutMs;
|
|
198
|
+
|
|
199
|
+
config.storage = { backend, postgres, local };
|
|
200
|
+
return config;
|
|
201
|
+
}
|
|
202
|
+
|
|
144
203
|
// ---------------------------------------------------------------------------
|
|
145
204
|
// loadConfig
|
|
146
205
|
// ---------------------------------------------------------------------------
|
|
@@ -193,7 +252,7 @@ function loadConfig(opts = {}) {
|
|
|
193
252
|
};
|
|
194
253
|
}
|
|
195
254
|
|
|
196
|
-
return config;
|
|
255
|
+
return normalizeStorageConfig(config);
|
|
197
256
|
}
|
|
198
257
|
|
|
199
258
|
module.exports = { loadConfig, DEFAULTS };
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const {
|
|
4
|
-
const { createAquifer, createEmbedder } = require('../../index');
|
|
3
|
+
const { createLocalAquifer } = require('../../core/backends/local');
|
|
5
4
|
const { loadConfig } = require('./config');
|
|
6
5
|
const { createLlmFn } = require('./llm');
|
|
7
6
|
|
|
@@ -11,12 +10,18 @@ const { createLlmFn } = require('./llm');
|
|
|
11
10
|
|
|
12
11
|
function createAquiferFromConfig(overrides) {
|
|
13
12
|
const config = loadConfig({ overrides });
|
|
13
|
+
const backendKind = config.storage?.backend || 'postgres';
|
|
14
|
+
|
|
15
|
+
if (backendKind === 'local') {
|
|
16
|
+
return createLocalAquifer(config);
|
|
17
|
+
}
|
|
14
18
|
|
|
15
19
|
if (!config.db.url) {
|
|
16
|
-
throw new Error('Database URL is required (set DATABASE_URL or
|
|
20
|
+
throw new Error('Database URL is required for PostgreSQL backend (set DATABASE_URL, AQUIFER_DB_URL, or AQUIFER_POSTGRES_URL)');
|
|
17
21
|
}
|
|
18
22
|
|
|
19
23
|
// Pool
|
|
24
|
+
const { Pool } = require('pg');
|
|
20
25
|
const pool = new Pool({
|
|
21
26
|
connectionString: config.db.url,
|
|
22
27
|
max: config.db.max || 10,
|
|
@@ -26,6 +31,7 @@ function createAquiferFromConfig(overrides) {
|
|
|
26
31
|
// Embed function (optional — lazy validation in core)
|
|
27
32
|
let embedFn = null;
|
|
28
33
|
if (config.embed && config.embed.baseUrl && config.embed.model) {
|
|
34
|
+
const { createEmbedder } = require('../../index');
|
|
29
35
|
// Detect provider from baseUrl
|
|
30
36
|
const isOllama = config.embed.baseUrl.includes('11434') || config.embed.baseUrl.includes('ollama');
|
|
31
37
|
const embedder = isOllama
|
|
@@ -80,6 +86,7 @@ function createAquiferFromConfig(overrides) {
|
|
|
80
86
|
rerankOpts = rerankConfig;
|
|
81
87
|
}
|
|
82
88
|
|
|
89
|
+
const { createAquifer } = require('../../index');
|
|
83
90
|
const aquifer = createAquifer({
|
|
84
91
|
db: pool,
|
|
85
92
|
ownsPool: true,
|