diff --git a/scripts/build-portal-runtime.mjs b/scripts/build-portal-runtime.mjs index ec8b9c3..571cb1c 100755 --- a/scripts/build-portal-runtime.mjs +++ b/scripts/build-portal-runtime.mjs @@ -312,6 +312,10 @@ async function writeMetadata() { path.join(root, 'scripts', 'runtime-slo-report.mjs'), path.join(runtimeRoot, 'scripts', 'runtime-slo-report.mjs'), ); + await fs.copyFile( + path.join(root, 'scripts', 'embed-memory-v2-local-hash.mjs'), + path.join(runtimeRoot, 'scripts', 'embed-memory-v2-local-hash.mjs'), + ); await fs.copyFile( path.join(root, 'scripts', 'install-runtime-metrics-agent.sh'), path.join(runtimeRoot, 'scripts', 'install-runtime-metrics-agent.sh'), diff --git a/scripts/mock-memory-v2-services.mjs b/scripts/mock-memory-v2-services.mjs index d6967e1..b2934c7 100644 --- a/scripts/mock-memory-v2-services.mjs +++ b/scripts/mock-memory-v2-services.mjs @@ -42,6 +42,15 @@ export function createMockMemoryV2Service() { langgraph: { resolves: [], }, + qdrant: { + searches: [], + }, + weaviate: { + searches: [], + }, + neo4j: { + statements: [], + }, }; function reset() { @@ -50,6 +59,9 @@ export function createMockMemoryV2Service() { state.letta.messages.length = 0; state.letta.compacts.length = 0; state.langgraph.resolves.length = 0; + state.qdrant.searches.length = 0; + state.weaviate.searches.length = 0; + state.neo4j.statements.length = 0; } async function handle(req, res) { @@ -153,6 +165,79 @@ export function createMockMemoryV2Service() { return; } + if (req.method === 'GET' && pathname === '/healthz') { + sendJson(res, 200, { ok: true, service: 'mock-qdrant' }); + return; + } + + if (req.method === 'GET' && pathname === '/collections') { + sendJson(res, 200, { result: { collections: [{ name: 'memind_memory' }] } }); + return; + } + + if (req.method === 'POST' && /^\/collections\/[^/]+\/points\/search$/.test(pathname)) { + const body = await readJson(req); + const collection = pathname.split('/')[2]; + state.qdrant.searches.push({ collection, ...body }); + sendJson(res, 200, { + result: [{ + id: 'qdrant-1', + score: 0.91, + payload: { + id: 'qdrant-1', + label: 'semantic', + content: `qdrant memory for ${body?.filter?.must?.[0]?.match?.value ?? 'unknown-user'}`, + created_at: Date.now(), + }, + }], + }); + return; + } + + if (req.method === 'GET' && pathname === '/v1/.well-known/ready') { + sendJson(res, 200, { status: 'READY' }); + return; + } + + if (req.method === 'POST' && pathname === '/v1/graphql') { + const body = await readJson(req); + state.weaviate.searches.push(body); + sendJson(res, 200, { + data: { + Get: { + MemoryItem: [{ + id: 'weaviate-1', + label: 'semantic', + text: 'weaviate memory item', + _additional: { certainty: 0.9 }, + }], + }, + }, + }); + return; + } + + if (req.method === 'POST' && /^\/db\/[^/]+\/tx\/commit$/.test(pathname)) { + const body = await readJson(req); + state.neo4j.statements.push(body); + const firstStatement = body?.statements?.[0]?.statement ?? ''; + if (/RETURN e\.summary AS behaviorSummary/i.test(firstStatement)) { + sendJson(res, 200, { + results: [{ + columns: ['behaviorSummary'], + data: [{ row: ['neo4j behavior summary'] }], + }], + errors: [], + }); + return; + } + sendJson(res, 200, { + results: [{ columns: ['id(e)'], data: [{ row: [1] }] }], + errors: [], + }); + return; + } + sendJson(res, 404, { ok: false, message: 'not found' }); }