Repository navigation
Description
Reproduction (published packages)
Fresh disposable npm project on macOS arm64 / Node 24.14.1:
{"dependencies":{"agentdb":"3.0.0-alpha.20"},"overrides":{"ruvector":"0.3.3","@ruvector/rvf":"0.3.4"}}Versions were verified using createRequire(require.resolve("agentdb")), not just the root manifest: AgentDB resolves RuVector 0.3.3 and RVF 0.3.4. The same async-search defect also reproduced with RuVector 0.2.41.
In a fresh temporary working directory:
import { RuVectorBackend } from './node_modules/agentdb/dist/src/backends/ruvector/RuVectorBackend.js';
const b = new RuVectorBackend({dimension: 4, metric: 'cosine'});
await b.initialize();
const vector = new Float32Array([1, 0, 0, 0]);
// Await native insertion to eliminate insertion timing as a cause.
await b.db.insert({id: 'fixture', vector, metadata: {label: 'keep'}});
console.log(await b.db.search({vector, k: 1})); // fixture, score: 0, metadata retained
console.log(b.search(vector, 1)); // []
console.log(b.getStats()); // throws: this.db.count is not a functionSeparately, b.remove('fixture') returns false, and await b.db.get('fixture') still finds the record.
Causes in RuVectorBackend
search()treats the Promise returned by VectorDB.search as an array;results.length | 0becomes zero and silently reports no matches.insert()ignores the returned Promise, so callers cannot reliably observe persistence/failure.- Native search returns
score(the fixture exact-match value is 0), while this adapter consumesdistance. - Native metadata is returned with search results, but this adapter uses only its local Map, which is empty after a process restart.
- The adapter calls
remove,count,save, andload; the current high-level VectorDB exposesdelete,len, and path-bound persistence instead. Its native binding also has no explicit close method. - Constructor config drops storagePath (tracked separately in AgentDB creates ruvector.db and agentdb.rvf in the process cwd instead of beside dbPath #28).
Adding one await is insufficient: AgentDB controllers including ReasoningBank, ReflexionMemory, SkillLibrary, CausalRecall, CausalMemoryGraph, HybridSearch, and attention consumers currently use the synchronous VectorBackend contract. The integration needs a reviewed async contract, awaited controller calls, correct native result mapping, honest lifecycle behavior, and compatible statistics.
Requested regression coverage
- Real native insert -> awaited retrieval with exact ID, finite distance/similarity, and exact metadata.
- Delete -> absence; count before/after.
- Metadata retention and retrieval in a second process, using an explicit storagePath.
- Controller-level pattern, episode, skill, and causal retrieval (not only direct backend tests).
- Native failures propagate instead of empty matches or fire-and-forget success.
- Preserve synchronous backend compatibility where applicable.
Separate RVF boundary
Switching to the latest RVF adapter is not a metadata-safe workaround. With AgentDB resolving RVF 0.3.4, RvfBackend.insertAsync(..., {label:'keep'}) rejects with Per-vector metadata is not yet supported by this SDK (see issue #704). Earlier SDKs silently accepted/dropped metadata. See ruvnet/RuVector#704. Do not strip metadata or introduce a lossy migration to make adapter tests pass.
All reproduction stores were disposable fixtures; no project database or sidecars were modified.
Activity