MCPcopy
hub / github.com/CaviraOSS/OpenMemory / ValkeyVectorStore

Class ValkeyVectorStore

backend/src/core/vector/valkey.ts:6–261  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

4import { vectorToBuffer, bufferToVector } from "../../memory/embed";
5
6export class ValkeyVectorStore implements VectorStore {
7 private client: Redis;
8
9 constructor() {
10 this.client = new Redis({
11 host: env.valkey_host || "localhost",
12 port: env.valkey_port || 6379,
13 password: env.valkey_password,
14 });
15 }
16
17 private getKey(id: string, sector: string): string {
18 return `vec:${sector}:${id}`;
19 }
20
21 async storeVector(id: string, sector: string, vector: number[], dim: number, user_id?: string): Promise<void> {
22 const key = this.getKey(id, sector);
23 const buf = vectorToBuffer(vector);
24 // Store as Hash: v (blob), dim (int), user_id (string)
25 await this.client.hset(key, {
26 v: buf,
27 dim: dim,
28 user_id: user_id || "anonymous",
29 id: id,
30 sector: sector
31 });
32 }
33
34 async deleteVector(id: string, sector: string): Promise<void> {
35 const key = this.getKey(id, sector);
36 await this.client.del(key);
37 }
38
39 async deleteVectors(id: string): Promise<void> {
40 // This is inefficient in Redis without an index on ID across sectors.
41 // We might need to track which sectors an ID has.
42 // For now, we can scan or just assume we know the sectors?
43 // The interface implies we delete ALL vectors for this ID.
44 // In Postgres we did `delete from vectors where id=$1`.
45 // In Redis, we might need to know the sectors.
46 // Or we can use `keys vec:*:${id}` which is slow.
47 // Better approach: maintain a set of sectors for each ID?
48 // Or just iterate over known sectors (from hsg.ts sectors list).
49 // I'll import `sectors` from `../../memory/hsg`? No, circular dependency risk.
50 // I'll use a scan for now as it's safer, or just accept it might be slow.
51 // Actually, `keys` is blocking. `scan` is better.
52 // But `id` is at the end of the key `vec:{sector}:{id}`.
53 // Pattern: `vec:*:${id}`.
54
55 let cursor = "0";
56 do {
57 const res = await this.client.scan(cursor, "MATCH", `vec:*:${id}`, "COUNT", 100);
58 cursor = res[0];
59 const keys = res[1];
60 if (keys.length) await this.client.del(...keys);
61 } while (cursor !== "0");
62 }
63

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected