#!/usr/bin/env node import http from 'node:http'; import { URL } from 'node:url'; function readJson(req) { return new Promise((resolve, reject) => { let body = ''; req.setEncoding('utf8'); req.on('data', (chunk) => { body += chunk; }); req.on('end', () => { if (!body.trim()) { resolve({}); return; } try { resolve(JSON.parse(body)); } catch (err) { reject(err); } }); req.on('error', reject); }); } function sendJson(res, statusCode, payload) { res.writeHead(statusCode, { 'content-type': 'application/json; charset=utf-8' }); res.end(JSON.stringify(payload)); } export function createMockMemoryV2Service() { const state = { mem0: { writes: [], compacts: [], }, letta: { messages: [], compacts: [], }, langgraph: { resolves: [], }, }; function reset() { state.mem0.writes.length = 0; state.mem0.compacts.length = 0; state.letta.messages.length = 0; state.letta.compacts.length = 0; state.langgraph.resolves.length = 0; } async function handle(req, res) { const url = new URL(req.url, 'http://127.0.0.1'); const pathname = url.pathname; if (req.method === 'GET' && pathname === '/health') { sendJson(res, 200, { ok: true, service: 'mock-memory-v2-services' }); return; } if (req.method === 'POST' && pathname === '/__admin/reset') { reset(); sendJson(res, 200, { ok: true }); return; } if (req.method === 'GET' && pathname === '/__admin/state') { sendJson(res, 200, { ok: true, state, }); return; } if (req.method === 'POST' && pathname === '/mem0/v1/memories') { const body = await readJson(req); state.mem0.writes.push(body); sendJson(res, 200, { saved: 1, analyzed: 1, memory_count: Array.isArray(body.messages) ? body.messages.length : 0, }); return; } if (req.method === 'POST' && pathname === '/mem0/v1/memories/compact') { const body = await readJson(req); state.mem0.compacts.push(body); sendJson(res, 200, { analyzed: 1, memory_count: state.mem0.writes.filter((item) => item.user_id === body.user_id).length, }); return; } if (req.method === 'POST' && /^\/letta\/v1\/agents\/[^/]+\/messages$/.test(pathname)) { const body = await readJson(req); const agentId = pathname.split('/')[4]; state.letta.messages.push({ agentId, ...body }); sendJson(res, 200, { saved: 1, analyzed: 0, memory_count: Array.isArray(body.messages) ? body.messages.length : 0, }); return; } if (req.method === 'POST' && /^\/letta\/v1\/agents\/[^/]+\/memory\/compact$/.test(pathname)) { const body = await readJson(req); const agentId = pathname.split('/')[4]; state.letta.compacts.push({ agentId, ...body }); sendJson(res, 200, { analyzed: 1, memory_count: state.letta.messages.filter((item) => item.user_id === body.user_id).length, }); return; } if (req.method === 'POST' && /^\/letta\/v1\/agents\/[^/]+\/memory$/.test(pathname)) { const body = await readJson(req); const agentId = pathname.split('/')[4]; const messages = state.letta.messages .filter((item) => item.agentId === agentId && item.user_id === body.user_id) .flatMap((item) => Array.isArray(item.messages) ? item.messages : []) .map((item, index) => ({ id: `letta-${index + 1}`, label: 'lifecycle', text: String(item.text ?? item.content ?? '').trim() || `letta-memory-${index + 1}`, })) .filter((item) => item.text); sendJson(res, 200, { memories: messages.length ? messages : ['letta lifecycle memory'], activeGoals: ['memory-v2'], }); return; } if (req.method === 'POST' && pathname === '/langgraph/memory/resolve') { const body = await readJson(req); state.langgraph.resolves.push(body); sendJson(res, 200, { memories: [{ id: 'langgraph-1', label: 'policy', text: `langgraph route for ${body.user_id ?? 'unknown-user'}`, }], activeGoals: ['route-memory'], behaviorSummary: null, }); return; } sendJson(res, 404, { ok: false, message: 'not found' }); } return { state, reset, createServer() { return http.createServer((req, res) => { Promise.resolve(handle(req, res)).catch((err) => { sendJson(res, 500, { ok: false, message: err instanceof Error ? err.message : String(err), }); }); }); }, }; } export async function startMockMemoryV2Service({ port = Number(process.env.MEMORY_V2_MOCK_PORT ?? 19400) || 19400, host = process.env.MEMORY_V2_MOCK_HOST ?? '127.0.0.1', stdout = process.stdout, } = {}) { const service = createMockMemoryV2Service(); const server = service.createServer(); await new Promise((resolve, reject) => { server.once('error', reject); server.listen(port, host, resolve); }); stdout.write(`${JSON.stringify({ ok: true, host, port }, null, 2)}\n`); return { service, server, host, port }; } if (import.meta.url === `file://${process.argv[1]}`) { startMockMemoryV2Service().catch((err) => { console.error(err instanceof Error ? err.message : err); process.exitCode = 1; }); }