Files
memind/scripts/check-memory-v2-health.mjs
T
2026-07-03 09:46:03 +08:00

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;
});
}