131 lines
3.6 KiB
JavaScript
131 lines
3.6 KiB
JavaScript
#!/usr/bin/env node
|
|
import fs from 'node:fs';
|
|
import path from 'node:path';
|
|
import { createMemoryV2Runtime } from '../memory-v2-runtime.mjs';
|
|
import { evaluateMemoryV2Health } from '../memory-v2-health.mjs';
|
|
|
|
function loadEnvFile(filePath, env = process.env) {
|
|
if (!fs.existsSync(filePath)) return;
|
|
for (const line of fs.readFileSync(filePath, 'utf8').split('\n')) {
|
|
const trimmed = line.trim();
|
|
if (!trimmed || trimmed.startsWith('#')) continue;
|
|
const idx = trimmed.indexOf('=');
|
|
if (idx < 0) continue;
|
|
const key = trimmed.slice(0, idx).trim();
|
|
const value = trimmed.slice(idx + 1).trim();
|
|
if (!env[key]) env[key] = value;
|
|
}
|
|
}
|
|
|
|
export function parseMemoryV2HealthArgs(argv = []) {
|
|
const options = {
|
|
requireEnabled: false,
|
|
expectedBackend: null,
|
|
envFile: process.env.MEMIND_ENV_FILE || path.join(process.cwd(), '.env'),
|
|
};
|
|
for (let i = 0; i < argv.length; i += 1) {
|
|
const arg = argv[i];
|
|
if (arg === '--require-enabled') {
|
|
options.requireEnabled = true;
|
|
} else if (arg === '--expect-backend') {
|
|
options.expectedBackend = argv[++i] ?? '';
|
|
} else if (arg === '--no-env-file') {
|
|
options.envFile = '';
|
|
} else if (arg === '--env-file') {
|
|
options.envFile = argv[++i] ?? '';
|
|
} else if (arg === '-h' || arg === '--help') {
|
|
options.help = true;
|
|
} else {
|
|
throw new Error(`Unknown argument: ${arg}`);
|
|
}
|
|
}
|
|
return options;
|
|
}
|
|
|
|
function usage() {
|
|
return `Usage:
|
|
node scripts/check-memory-v2-health.mjs [options]
|
|
|
|
Options:
|
|
--require-enabled Fail unless Memory V2 is enabled.
|
|
--expect-backend <name> Fail unless MEMORY_BACKEND equals this value.
|
|
--env-file <path> Env file to load. Defaults to MEMIND_ENV_FILE or .env.
|
|
--no-env-file Do not load an env file.
|
|
`;
|
|
}
|
|
|
|
function createSyntheticLegacyMemoryService() {
|
|
return {
|
|
async listMemories() {
|
|
return [{ label: 'health', text: 'synthetic memory-v2 health check' }];
|
|
},
|
|
async saveAndAnalyze() {
|
|
return { saved: 1, analyzed: 1, memories: 1 };
|
|
},
|
|
async analyzeUser() {
|
|
return { analyzed: 1, memories: 1 };
|
|
},
|
|
};
|
|
}
|
|
|
|
export async function runMemoryV2HealthCli({
|
|
argv = process.argv.slice(2),
|
|
env = process.env,
|
|
stdout = process.stdout,
|
|
stderr = process.stderr,
|
|
importPg,
|
|
importModule,
|
|
} = {}) {
|
|
const options = parseMemoryV2HealthArgs(argv);
|
|
if (options.help) {
|
|
stdout.write(usage());
|
|
return 0;
|
|
}
|
|
if (options.envFile) loadEnvFile(options.envFile, env);
|
|
|
|
const memory = await createMemoryV2Runtime({
|
|
legacyMemoryService: createSyntheticLegacyMemoryService(),
|
|
env,
|
|
logger: {
|
|
warn(message) {
|
|
stderr.write(`${message}\n`);
|
|
},
|
|
},
|
|
...(importPg ? { importPg } : {}),
|
|
...(importModule ? { importModule } : {}),
|
|
});
|
|
|
|
const status = memory.getStatus();
|
|
const writeResult = await memory.write({
|
|
userId: 'memory-v2-health-user',
|
|
sessionId: 'memory-v2-health-session',
|
|
messages: [],
|
|
});
|
|
const compactResult = await memory.compact({
|
|
userId: 'memory-v2-health-user',
|
|
sessionId: 'memory-v2-health-session',
|
|
});
|
|
|
|
await memory.close?.();
|
|
|
|
const report = evaluateMemoryV2Health({
|
|
status,
|
|
writeResult,
|
|
compactResult,
|
|
expectedBackend: options.expectedBackend || null,
|
|
requireEnabled: options.requireEnabled,
|
|
});
|
|
|
|
stdout.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
return report.ok ? 0 : 1;
|
|
}
|
|
|
|
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
runMemoryV2HealthCli().then((code) => {
|
|
process.exitCode = code;
|
|
}).catch((err) => {
|
|
console.error(err instanceof Error ? err.message : err);
|
|
process.exitCode = 1;
|
|
});
|
|
}
|