176 lines
4.8 KiB
JavaScript
176 lines
4.8 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
import {
|
|
parseMemoryV2ExternalSmokeArgs,
|
|
runMemoryV2ExternalSmokeCli,
|
|
} from './smoke-memory-v2-external.mjs';
|
|
|
|
function writableBuffer() {
|
|
let value = '';
|
|
return {
|
|
write(chunk) {
|
|
value += String(chunk);
|
|
},
|
|
value() {
|
|
return value;
|
|
},
|
|
};
|
|
}
|
|
|
|
test('parseMemoryV2ExternalSmokeArgs validates backend and defaults operation', () => {
|
|
assert.deepEqual(
|
|
parseMemoryV2ExternalSmokeArgs(['--backend', 'redis-streams']),
|
|
{
|
|
backend: 'redis-streams',
|
|
operation: 'write',
|
|
query: 'memory-chain smoke',
|
|
limit: 1,
|
|
vector: null,
|
|
userId: 'memory-v2-smoke-user',
|
|
sessionId: 'memory-v2-smoke-session',
|
|
help: false,
|
|
},
|
|
);
|
|
assert.deepEqual(
|
|
parseMemoryV2ExternalSmokeArgs([
|
|
'--backend',
|
|
'weaviate',
|
|
'--operation',
|
|
'resolve',
|
|
'--vector',
|
|
'0.1,0.2',
|
|
'--limit',
|
|
'2',
|
|
]).vector,
|
|
[0.1, 0.2],
|
|
);
|
|
assert.throws(
|
|
() => parseMemoryV2ExternalSmokeArgs(['--backend', 'unknown']),
|
|
/--backend must be one of/,
|
|
);
|
|
});
|
|
|
|
test('runMemoryV2ExternalSmokeCli smokes Qdrant through runtime HTTP wiring', async () => {
|
|
const stdout = writableBuffer();
|
|
const report = await runMemoryV2ExternalSmokeCli({
|
|
argv: ['--backend', 'qdrant', '--operation', 'resolve', '--limit', '2'],
|
|
env: {
|
|
MEMORY_QDRANT_ENABLED: '1',
|
|
MEMORY_QDRANT_URL: 'http://qdrant.local',
|
|
MEMORY_QDRANT_COLLECTION: 'memind_memory',
|
|
MEMORY_QDRANT_EMBEDDING_MODULE: './embed.mjs',
|
|
},
|
|
stdout,
|
|
async importModule() {
|
|
return { async embedQuery() { return [0.1, 0.2, 0.3]; } };
|
|
},
|
|
async fetchImpl(url, options) {
|
|
assert.equal(url, 'http://qdrant.local/collections/memind_memory/points/search');
|
|
assert.equal(JSON.parse(options.body).limit, 2);
|
|
return {
|
|
ok: true,
|
|
async json() {
|
|
return {
|
|
result: [
|
|
{
|
|
id: 'q1',
|
|
score: 0.9,
|
|
payload: { content: 'semantic memory', type: 'semantic' },
|
|
},
|
|
],
|
|
};
|
|
},
|
|
};
|
|
},
|
|
});
|
|
const output = JSON.parse(stdout.value());
|
|
|
|
assert.equal(report.backendAvailable, true);
|
|
assert.equal(output.selectedBackend, 'qdrant');
|
|
assert.equal(output.result.source, 'qdrant');
|
|
});
|
|
|
|
test('runMemoryV2ExternalSmokeCli smokes Weaviate through runtime HTTP wiring', async () => {
|
|
const stdout = writableBuffer();
|
|
const report = await runMemoryV2ExternalSmokeCli({
|
|
argv: ['--backend', 'weaviate', '--operation', 'resolve', '--limit', '2'],
|
|
env: {
|
|
MEMORY_WEAVIATE_ENABLED: '1',
|
|
MEMORY_WEAVIATE_URL: 'https://weaviate.local',
|
|
MEMORY_WEAVIATE_EMBEDDING_MODULE: './embed.mjs',
|
|
},
|
|
stdout,
|
|
async importModule() {
|
|
return { async embedQuery() { return [0.1, 0.2]; } };
|
|
},
|
|
async fetchImpl(url, options) {
|
|
assert.equal(url, 'https://weaviate.local/v1/graphql');
|
|
assert.equal(JSON.parse(options.body).variables.limit, 2);
|
|
return {
|
|
ok: true,
|
|
async json() {
|
|
return {
|
|
data: {
|
|
Get: {
|
|
MemindMemory: [{ content: 'semantic memory', _additional: { id: 'w1' } }],
|
|
},
|
|
},
|
|
};
|
|
},
|
|
};
|
|
},
|
|
});
|
|
const output = JSON.parse(stdout.value());
|
|
|
|
assert.equal(report.backendAvailable, true);
|
|
assert.equal(output.selectedBackend, 'weaviate');
|
|
assert.equal(output.result.source, 'weaviate');
|
|
});
|
|
|
|
test('runMemoryV2ExternalSmokeCli smokes Redis Streams with injected redis module', async () => {
|
|
const stdout = writableBuffer();
|
|
const xAdds = [];
|
|
let quitCalled = false;
|
|
const report = await runMemoryV2ExternalSmokeCli({
|
|
argv: ['--backend', 'redis-streams'],
|
|
env: {
|
|
MEMORY_REDIS_STREAMS_ENABLED: '1',
|
|
MEMORY_REDIS_STREAMS_URL: 'redis://localhost:6379',
|
|
},
|
|
stdout,
|
|
async importRedis() {
|
|
return {
|
|
createClient() {
|
|
return {
|
|
async connect() {},
|
|
async xAdd(stream, id, fields) {
|
|
xAdds.push({ stream, id, fields });
|
|
},
|
|
async quit() {
|
|
quitCalled = true;
|
|
},
|
|
};
|
|
},
|
|
};
|
|
},
|
|
});
|
|
|
|
assert.equal(report.backendAvailable, true);
|
|
assert.equal(report.result.source, 'redis-streams');
|
|
assert.equal(xAdds[0].stream, 'memind:memory-events');
|
|
assert.equal(quitCalled, true);
|
|
});
|
|
|
|
test('runMemoryV2ExternalSmokeCli reports fallback when backend is not configured', async () => {
|
|
const stdout = writableBuffer();
|
|
const report = await runMemoryV2ExternalSmokeCli({
|
|
argv: ['--backend', 'langgraph'],
|
|
env: {},
|
|
stdout,
|
|
});
|
|
|
|
assert.equal(report.backendAvailable, false);
|
|
assert.equal(report.selectedBackend, 'legacy-conversation-memory');
|
|
assert.equal(report.backendReason, 'not_configured');
|
|
});
|