Merge Memory V2 runtime facade
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import { inspectMemoryV2Backend } from './memory-v2-backend-contract.mjs';
|
||||
import { createMem0HttpClient, createMem0MemoryBackend } from './memory-v2-mem0.mjs';
|
||||
|
||||
test('mem0 backend is disabled by default and passes contract gate', async () => {
|
||||
const backend = createMem0MemoryBackend();
|
||||
const report = inspectMemoryV2Backend(backend);
|
||||
|
||||
assert.equal(backend.name, 'mem0');
|
||||
assert.equal(backend.category, 'extraction');
|
||||
assert.equal(backend.role, 'automatic-memory-generation');
|
||||
assert.equal(backend.flag, 'MEMORY_MEM0_ENABLED');
|
||||
assert.equal(backend.isAvailable(), false);
|
||||
assert.equal(backend.getUnavailableReason(), 'not_configured');
|
||||
assert.equal(report.ok, true);
|
||||
assert.deepEqual(await backend.write({}), { saved: 0, analyzed: 0, memories: 0 });
|
||||
assert.deepEqual(await backend.compact({}), { analyzed: 0, memories: 0 });
|
||||
});
|
||||
|
||||
test('mem0 backend reports api key and client configuration reasons', () => {
|
||||
assert.equal(
|
||||
createMem0MemoryBackend({ enabled: true }).getUnavailableReason(),
|
||||
'api_key_not_configured',
|
||||
);
|
||||
assert.equal(
|
||||
createMem0MemoryBackend({
|
||||
enabled: true,
|
||||
apiKey: 'secret',
|
||||
projectId: 'memind_project',
|
||||
}).getUnavailableReason(),
|
||||
'client_not_configured',
|
||||
);
|
||||
});
|
||||
|
||||
test('mem0 backend validates project id', () => {
|
||||
assert.throws(
|
||||
() => createMem0MemoryBackend({ projectId: 'bad project id' }),
|
||||
/Invalid MEMORY_MEM0_PROJECT_ID/,
|
||||
);
|
||||
});
|
||||
|
||||
test('mem0 backend can become available only with explicit client skeleton', () => {
|
||||
const backend = createMem0MemoryBackend({
|
||||
enabled: true,
|
||||
apiKey: 'secret',
|
||||
projectId: 'memind_project',
|
||||
client: {
|
||||
async write() {
|
||||
return {};
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
assert.equal(backend.isAvailable(), true);
|
||||
assert.equal(backend.getUnavailableReason(), null);
|
||||
});
|
||||
|
||||
test('mem0 HTTP client writes and compacts with bearer auth', async () => {
|
||||
const calls = [];
|
||||
const client = createMem0HttpClient({
|
||||
apiKey: 'secret',
|
||||
projectId: 'memind_project',
|
||||
baseUrl: 'https://mem0.local',
|
||||
modelProviderKeyId: 'key_mem0',
|
||||
model: 'gpt-4.1-mini',
|
||||
modelApiType: 'response',
|
||||
async fetchImpl(url, options) {
|
||||
calls.push({ url, headers: options.headers, body: JSON.parse(options.body) });
|
||||
return {
|
||||
ok: true,
|
||||
async json() {
|
||||
return { saved: 1, analyzed: 1, memories: 1 };
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
assert.deepEqual(await client.write({
|
||||
userId: 'u1',
|
||||
sessionId: 's1',
|
||||
messages: [{ text: 'hello' }],
|
||||
}), { saved: 1, analyzed: 1, memories: 1 });
|
||||
assert.deepEqual(await client.compact({ userId: 'u1' }), {
|
||||
analyzed: 1,
|
||||
memories: 1,
|
||||
});
|
||||
assert.deepEqual(calls.map((call) => call.url), [
|
||||
'https://mem0.local/v1/memories',
|
||||
'https://mem0.local/v1/memories/compact',
|
||||
]);
|
||||
assert.equal(calls[0].headers.authorization, 'Bearer secret');
|
||||
assert.equal(calls[0].body.project_id, 'memind_project');
|
||||
assert.equal(calls[0].body.model_provider_key_id, 'key_mem0');
|
||||
assert.equal(calls[0].body.model, 'gpt-4.1-mini');
|
||||
assert.equal(calls[0].body.model_api_type, 'response');
|
||||
assert.equal(calls[1].body.model_provider_key_id, 'key_mem0');
|
||||
});
|
||||
Reference in New Issue
Block a user