Merge Memory V2 runtime facade
This commit is contained in:
@@ -0,0 +1,195 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const BACKEND_SPECS = [
|
||||
{
|
||||
name: 'pgvector',
|
||||
env: ['MEMORY_ENABLED', 'MEMORY_BACKEND', 'MEMORY_VECTOR_ENABLED', 'MEMORY_PGVECTOR_DATABASE_URL', 'MEMORY_PGVECTOR_EMBEDDING_MODULE'],
|
||||
recommended: {
|
||||
MEMORY_ENABLED: '1',
|
||||
MEMORY_BACKEND: 'pgvector',
|
||||
MEMORY_VECTOR_ENABLED: '1',
|
||||
MEMORY_PGVECTOR_DATABASE_URL: 'postgresql://john@127.0.0.1:5432/memind_memory',
|
||||
MEMORY_PGVECTOR_EMBEDDING_MODULE: './scripts/embed-memory-v2-local-hash.mjs',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'qdrant',
|
||||
env: ['MEMORY_ENABLED', 'MEMORY_BACKEND', 'MEMORY_QDRANT_ENABLED', 'MEMORY_QDRANT_URL', 'MEMORY_QDRANT_EMBEDDING_MODULE'],
|
||||
recommended: {
|
||||
MEMORY_ENABLED: '1',
|
||||
MEMORY_BACKEND: 'qdrant',
|
||||
MEMORY_QDRANT_ENABLED: '1',
|
||||
MEMORY_QDRANT_URL: 'http://127.0.0.1:6333',
|
||||
MEMORY_QDRANT_EMBEDDING_MODULE: './scripts/embed-memory-v2-local-hash.mjs',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'weaviate',
|
||||
env: ['MEMORY_ENABLED', 'MEMORY_BACKEND', 'MEMORY_WEAVIATE_ENABLED', 'MEMORY_WEAVIATE_URL', 'MEMORY_WEAVIATE_EMBEDDING_MODULE'],
|
||||
recommended: {
|
||||
MEMORY_ENABLED: '1',
|
||||
MEMORY_BACKEND: 'weaviate',
|
||||
MEMORY_WEAVIATE_ENABLED: '1',
|
||||
MEMORY_WEAVIATE_URL: 'http://127.0.0.1:8080',
|
||||
MEMORY_WEAVIATE_EMBEDDING_MODULE: './scripts/embed-memory-v2-local-hash.mjs',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'mem0',
|
||||
env: ['MEMORY_ENABLED', 'MEMORY_BACKEND', 'MEMORY_MEM0_ENABLED', 'MEMORY_MEM0_API_KEY'],
|
||||
recommended: {
|
||||
MEMORY_ENABLED: '1',
|
||||
MEMORY_BACKEND: 'mem0',
|
||||
MEMORY_MEM0_ENABLED: '1',
|
||||
MEMORY_MEM0_API_KEY: 'replace-me',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'letta',
|
||||
env: ['MEMORY_ENABLED', 'MEMORY_BACKEND', 'MEMORY_LETTA_ENABLED', 'MEMORY_LETTA_API_KEY', 'MEMORY_LETTA_AGENT_ID'],
|
||||
recommended: {
|
||||
MEMORY_ENABLED: '1',
|
||||
MEMORY_BACKEND: 'letta',
|
||||
MEMORY_LETTA_ENABLED: '1',
|
||||
MEMORY_LETTA_API_KEY: 'replace-me',
|
||||
MEMORY_LETTA_AGENT_ID: 'agent_1',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'neo4j',
|
||||
env: ['MEMORY_ENABLED', 'MEMORY_BACKEND', 'MEMORY_NEO4J_ENABLED', 'MEMORY_NEO4J_HTTP_URL', 'MEMORY_NEO4J_USER', 'MEMORY_NEO4J_PASSWORD'],
|
||||
recommended: {
|
||||
MEMORY_ENABLED: '1',
|
||||
MEMORY_BACKEND: 'neo4j',
|
||||
MEMORY_NEO4J_ENABLED: '1',
|
||||
MEMORY_NEO4J_HTTP_URL: 'http://127.0.0.1:7474',
|
||||
MEMORY_NEO4J_USER: 'neo4j',
|
||||
MEMORY_NEO4J_PASSWORD: 'replace-me',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'redis-streams',
|
||||
env: ['MEMORY_ENABLED', 'MEMORY_BACKEND', 'MEMORY_REDIS_STREAMS_ENABLED', 'MEMORY_REDIS_STREAMS_URL'],
|
||||
recommended: {
|
||||
MEMORY_ENABLED: '1',
|
||||
MEMORY_BACKEND: 'redis-streams',
|
||||
MEMORY_REDIS_STREAMS_ENABLED: '1',
|
||||
MEMORY_REDIS_STREAMS_URL: 'redis://127.0.0.1:6379',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'langgraph',
|
||||
env: ['MEMORY_ENABLED', 'MEMORY_BACKEND', 'MEMORY_LANGGRAPH_ENABLED', 'MEMORY_LANGGRAPH_URL'],
|
||||
recommended: {
|
||||
MEMORY_ENABLED: '1',
|
||||
MEMORY_BACKEND: 'langgraph',
|
||||
MEMORY_LANGGRAPH_ENABLED: '1',
|
||||
MEMORY_LANGGRAPH_URL: 'http://127.0.0.1:2024',
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
function usage() {
|
||||
return `Usage:
|
||||
node scripts/check-memory-v2-config-gaps.mjs [options]
|
||||
|
||||
Options:
|
||||
--backend <name> Limit output to one backend.
|
||||
--format <type> json | shell. Default: json.
|
||||
-h, --help Show this help.
|
||||
`;
|
||||
}
|
||||
|
||||
export function parseMemoryV2ConfigGapArgs(argv = []) {
|
||||
const options = {
|
||||
backend: null,
|
||||
format: 'json',
|
||||
help: false,
|
||||
};
|
||||
for (let i = 0; i < argv.length; i += 1) {
|
||||
const arg = argv[i];
|
||||
if (arg === '--backend') {
|
||||
options.backend = argv[++i] ?? '';
|
||||
} else if (arg === '--format') {
|
||||
options.format = argv[++i] ?? '';
|
||||
} else if (arg === '-h' || arg === '--help') {
|
||||
options.help = true;
|
||||
} else {
|
||||
throw new Error(`Unknown argument: ${arg}`);
|
||||
}
|
||||
}
|
||||
if (options.backend && !BACKEND_SPECS.some((item) => item.name === options.backend)) {
|
||||
throw new Error(`--backend must be one of: ${BACKEND_SPECS.map((item) => item.name).join(', ')}`);
|
||||
}
|
||||
if (!['json', 'shell'].includes(options.format)) {
|
||||
throw new Error('--format must be json or shell');
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
function inspectBackend(spec, env = process.env) {
|
||||
const present = {};
|
||||
const missing = [];
|
||||
for (const key of spec.env) {
|
||||
const value = String(env[key] ?? '').trim();
|
||||
if (value) present[key] = value;
|
||||
else missing.push(key);
|
||||
}
|
||||
return {
|
||||
backend: spec.name,
|
||||
ready: missing.length === 0,
|
||||
missing,
|
||||
presentKeys: Object.keys(present),
|
||||
recommended: spec.recommended,
|
||||
};
|
||||
}
|
||||
|
||||
function renderShell(reports) {
|
||||
const chunks = [];
|
||||
for (const report of reports) {
|
||||
chunks.push(`# ${report.backend}`);
|
||||
for (const [key, value] of Object.entries(report.recommended)) {
|
||||
chunks.push(`export ${key}='${String(value).replaceAll("'", "'\\''")}'`);
|
||||
}
|
||||
chunks.push('');
|
||||
}
|
||||
return chunks.join('\n').trimEnd();
|
||||
}
|
||||
|
||||
export async function runMemoryV2ConfigGapCli({
|
||||
argv = process.argv.slice(2),
|
||||
env = process.env,
|
||||
stdout = process.stdout,
|
||||
} = {}) {
|
||||
const options = parseMemoryV2ConfigGapArgs(argv);
|
||||
if (options.help) {
|
||||
stdout.write(usage());
|
||||
return 0;
|
||||
}
|
||||
|
||||
const reports = BACKEND_SPECS
|
||||
.filter((spec) => !options.backend || spec.name === options.backend)
|
||||
.map((spec) => inspectBackend(spec, env));
|
||||
|
||||
if (options.format === 'shell') {
|
||||
stdout.write(`${renderShell(reports)}\n`);
|
||||
return reports.every((item) => item.ready) ? 0 : 1;
|
||||
}
|
||||
|
||||
const output = {
|
||||
ok: reports.every((item) => item.ready),
|
||||
checkedAt: new Date().toISOString(),
|
||||
reports,
|
||||
};
|
||||
stdout.write(`${JSON.stringify(output, null, 2)}\n`);
|
||||
return output.ok ? 0 : 1;
|
||||
}
|
||||
|
||||
if (import.meta.url === `file://${process.argv[1]}`) {
|
||||
runMemoryV2ConfigGapCli().then((code) => {
|
||||
process.exitCode = code;
|
||||
}).catch((err) => {
|
||||
console.error(err instanceof Error ? err.message : err);
|
||||
process.exitCode = 1;
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user