TcvdbMemoryStore wraps Tencent Cloud VectorDB as a dense+sparse hybrid search backend, offloading embeddings server-side and combining dense vectors with client-side BM25 sparse encoding for ranked retrieval. The implementation is a thin HTTP client layer (TcvdbClient) that authenticates via bearer tokens, normalizes errors, handles retries, and exposes low-level API operations that TcvdbMemoryStore adapts into the IMemoryStore interface with fault tolerance and scalar filtering. RRFRerank (Reciprocal Rank Fusion) is a score-fusion algorithm that merges ranked lists from dense and sparse retrievers into a single ranked result without requiring score normalization.
TcvdbMemoryStore in src/core/store/tcvdb.ts implements IMemoryStore using Tencent Cloud VectorDB as the storage backend, supporting server-side dense embedding, client-side BM25 sparse vectors, native hybrid search (dense + sparse + RRFRerank), scalar filter expressions, and time fields stored as uint64 epoch milliseconds.[1] All methods on TcvdbMemoryStore are fault-tolerant: they return empty values or false on error and never throw exceptions to callers.[1]
TcvdbMemoryStoreConfig requires url, username, apiKey, database, embeddingModel, and timeout; optional fields include caPemPath (path to a CA certificate PEM file for HTTPS), logger, and bm25Encoder.[1] TcvdbClientConfig.username defaults semantically to "root" and TcvdbClientConfig.timeout defaults to 10000 ms.[2] TcvdbClient strips trailing slashes from the url config field when constructing baseUrl.[2]
TcvdbClient in src/core/store/tcvdb-client.ts is a thin HTTP wrapper around the Tencent Cloud VectorDB API, handling authentication, timeouts, retries, and error normalization.[2] TcvdbClient constructs its Authorization header as Bearer account=<username>&api_key=<apiKey>, combining the username and API key in a single header.[2] TcvdbApiError exposes the raw VectorDB API error code via the apiCode readonly property, allowing callers to branch on specific API error codes.[2] TcvdbClient.createDatabase() is idempotent: it lists existing databases and skips creation if the target database already exists.[2] TcvdbClient.upsert() always sends buildIndex: true to the /document/upsert endpoint.[2] TcvdbClient.search(), hybridSearch(), and query() all use readConsistency: "strongConsistency" in their API requests, eliminating read-after-write inconsistency.[2][3]
TcvdbMemoryStore.init() always returns { needsReindex: false } because embedding is managed server-side by TCVDB; re-indexing is never required from the client.[1] The VectorDB /document/query API page size is capped at 100 documents (QUERY_PAGE_SIZE = 100).[1]
L1 output fields returned by query/search are: id, text, type, priority, scene_name, session_key, session_id, timestamp_str, timestamp_start, timestamp_end, metadata_json, created_time_ms, and updated_time_ms; vector and sparse vector fields are excluded.[1] L0 output fields returned by query/search are: id, message_text, agent_id, session_key, session_id, role, recorded_at_ms, and timestamp.[1] The extractAgentId helper in src/core/store/tcvdb.ts parses an agent ID from session keys in the format agent:<agentId>:<channel>, returning an empty string if the format does not match.[1]
BM25LocalEncoder in src/core/store/bm25-local.ts is a pure TypeScript replacement for the old Python sidecar BM25 client, using the @tencentdb-agent-memory/tcvdb-text package (jieba-wasm) for tokenization and BM25 encoding.[4][3] BM25LocalConfig has two fields: enabled: boolean (whether sparse encoding is active) and optional language?: "zh" | "en" (pre-trained BM25 params language, default "zh").[4] BM25LocalEncoder constructor defaults language to "zh" when not specified, using BM25Encoder.default(language) from the @tencentdb-agent-memory/tcvdb-text package.[4] createBM25Encoder(config, logger?) returns undefined when config.enabled is false; callers must check for undefined before using the encoder.[4] BM25 (Best Match 25) is a term-frequency/inverse-document-frequency ranking algorithm that produces sparse vectors — non-zero weights only for terms present in a given text, with most dimensions remaining zero — enabling efficient keyword-based similarity scoring.
Sources