From f39d420cb49751f46ff009351a4f4426734441be Mon Sep 17 00:00:00 2001 From: David Snelling Date: Tue, 9 Jun 2026 13:07:56 -0700 Subject: [PATCH] =?UTF-8?q?refactor(8.0):=20rename=20HNSWIndex=20class=20?= =?UTF-8?q?=E2=86=92=20JsHnswVectorIndex=20(scaffold=20step=203)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Step 3 of the brainy 8.0 rename scaffolding. The class name now matches its role: the JS HNSW implementation of the VectorIndexProvider contract. Per planning § 2.3: this is NOT cosmetic — leaving HNSWIndex when the public contract is VectorIndexProvider creates a confusing read at the implementation layer. CHANGES Repo-wide mechanical rename: HNSWIndex → JsHnswVectorIndex across 52 references in src/ + 5 references in tests/ via sed. Class declaration, imports, JSDoc, comments, and identifiers all updated. src/index.ts - Primary public export: JsHnswVectorIndex (the new name). - Backwards-compat alias: `export const HNSWIndex = JsHnswVectorIndex` with @deprecated note. Removed in the final 8.0 cleanup commit. NO-OP scope No behavioural change. The class is exactly the same; only the name moved. Tests + build green. VERIFICATION - npx tsc --noEmit: clean - npm test: 1468 / 1468 unit --- src/brainy.ts | 26 +++++++++---------- src/hnsw/hnswIndex.ts | 14 +++++----- src/hnsw/mmapVectorBackend.ts | 8 +++--- src/hnsw/typeAwareHNSWIndex.ts | 16 ++++++------ src/index.ts | 16 +++++++++--- src/plugin.ts | 12 ++++----- src/transaction/operations/IndexOperations.ts | 12 ++++----- src/triple/TripleIntelligenceSystem.ts | 6 ++--- src/utils/periodicCleanup.ts | 6 ++--- tests/unit/hnsw/lazy-vectors.test.ts | 18 ++++++------- tests/unit/hnsw/quantization.test.ts | 16 ++++++------ 11 files changed, 80 insertions(+), 70 deletions(-) diff --git a/src/brainy.ts b/src/brainy.ts index 55aaefe4..f998336a 100644 --- a/src/brainy.ts +++ b/src/brainy.ts @@ -6,8 +6,8 @@ */ import { v4 as uuidv4 } from './universal/uuid.js' -import { HNSWIndex } from './hnsw/hnswIndex.js' -// TypeAwareHNSWIndex removed from default path — single unified HNSWIndex is faster +import { JsHnswVectorIndex } from './hnsw/hnswIndex.js' +// TypeAwareHNSWIndex removed from default path — single unified JsHnswVectorIndex is faster // for the 99% of queries that don't filter by type (avoids searching 42 separate graphs) import { createStorage } from './storage/storageFactory.js' import { BaseStorage } from './storage/baseStorage.js' @@ -156,7 +156,7 @@ export class Brainy implements BrainyInterface { private static instances: Brainy[] = [] // Core components - private index!: HNSWIndex + private index!: JsHnswVectorIndex private storage!: BaseStorage private metadataIndex!: MetadataIndexManager private graphIndex!: GraphAdjacencyIndex @@ -606,8 +606,8 @@ export class Brainy implements BrainyInterface { // Wire the mmap-vector backend (2.4.0 #2). When the vectorStore:mmap // provider is registered AND the storage adapter resolves a real local // path via getBinaryBlobPath(), open the mmap file there and inject the - // backend into HNSWIndex. Cloud adapters return null and skip silently; - // HNSWIndex's behaviour is then identical to pre-2.4.0 (per-entity reads + // backend into JsHnswVectorIndex. Cloud adapters return null and skip silently; + // JsHnswVectorIndex's behaviour is then identical to pre-2.4.0 (per-entity reads // from canonical storage). Failures are non-fatal — the index still // works, just without the zero-copy fast path. await this.wireMmapVectorBackend() @@ -8324,7 +8324,7 @@ export class Brainy implements BrainyInterface { * @param candidateIds Optional pre-resolved metadata filter IDs for metadata-first search. * When provided, HNSW search is restricted to these candidates: * - NativeHNSWWrapper: uses native searchWithCandidates (Rust bitmap filtering) - * - JS HNSWIndex: converts to filter function with O(1) Set lookups + * - JS JsHnswVectorIndex: converts to filter function with O(1) Set lookups */ private async executeVectorSearch(params: FindParams, candidateIds?: string[]): Promise[]> { const vector = params.vector || (await this.embed(params.query!)) @@ -9070,7 +9070,7 @@ export class Brainy implements BrainyInterface { * - Cloud storage (GCS/S3/R2/Azure): 'deferred' for 30-50x faster adds * - Local storage (FileSystem/Memory/OPFS): 'immediate' (already fast) */ - private setupIndex(): HNSWIndex { + private setupIndex(): JsHnswVectorIndex { const indexConfig = { ...this.config.index, distanceFunction: this.distance, @@ -9085,7 +9085,7 @@ export class Brainy implements BrainyInterface { const persistMode = this.resolveHNSWPersistMode() - return new HNSWIndex(indexConfig as any, this.distance, { + return new JsHnswVectorIndex(indexConfig as any, this.distance, { storage: this.storage, useParallelization: true, persistMode @@ -9106,11 +9106,11 @@ export class Brainy implements BrainyInterface { * - The metadata index has a stable `idMapper`. * - `config.index.type !== 'hnsw'` (no explicit opt-out). * 3. `'hnsw'` provider if registered (cortex's native HNSW). - * 4. Brainy's built-in TS HNSWIndex (the always-available fallback). + * 4. Brainy's built-in TS JsHnswVectorIndex (the always-available fallback). * * See ADR-002 in the cortex repo for the engagement rationale. */ - private createIndex(): HNSWIndex { + private createIndex(): JsHnswVectorIndex { const persistMode = this.resolveHNSWPersistMode() const indexType = (this.config.index as any)?.type as 'hnsw' | 'diskann' | undefined @@ -9170,7 +9170,7 @@ export class Brainy implements BrainyInterface { private instantiateDiskAnn( factory: (config: any, distance: DistanceFunction, options: any) => any, persistMode: 'immediate' | 'deferred' - ): HNSWIndex { + ): JsHnswVectorIndex { const storageWithBlob = this.storage as unknown as { getBinaryBlobPath?: (key: string) => string | null } @@ -9377,7 +9377,7 @@ export class Brainy implements BrainyInterface { } /** - * @description Open the mmap-vector backend and inject it into HNSWIndex. + * @description Open the mmap-vector backend and inject it into JsHnswVectorIndex. * Called once during init after plugin activation, metadataIndex init, and * graphIndex setup — so the idMapper is available and providers are wired. * @@ -9397,7 +9397,7 @@ export class Brainy implements BrainyInterface { * (or a re-open) sees the correct value. * * Failures here are non-fatal: a debug-level log records the reason, and - * HNSWIndex continues without the mmap fast path. + * JsHnswVectorIndex continues without the mmap fast path. */ private async wireMmapVectorBackend(): Promise { const provider = this.pluginRegistry.getProvider('vectorStore:mmap') diff --git a/src/hnsw/hnswIndex.ts b/src/hnsw/hnswIndex.ts index 10cb69f8..5908d7a0 100644 --- a/src/hnsw/hnswIndex.ts +++ b/src/hnsw/hnswIndex.ts @@ -31,10 +31,10 @@ const DEFAULT_CONFIG: HNSWConfig = { /** * Implements {@link VectorIndexProvider}: the vector-index surface Brainy calls - * on whatever the `'vector'` factory returns (its own `HNSWIndex`, or a native + * on whatever the `'vector'` factory returns (its own `JsHnswVectorIndex`, or a native * acceleration provider). */ -export class HNSWIndex implements VectorIndexProvider { +export class JsHnswVectorIndex implements VectorIndexProvider { private nouns: Map = new Map() private entryPointId: string | null = null private maxLevel = 0 @@ -71,7 +71,7 @@ export class HNSWIndex implements VectorIndexProvider { // COW (Copy-on-Write) support private cowEnabled: boolean = false private cowModifiedNodes: Set = new Set() - private cowParent: HNSWIndex | null = null + private cowParent: JsHnswVectorIndex | null = null // Deferred HNSW persistence for cloud storage performance // In deferred mode, HNSW connections are only persisted on flush/close @@ -130,7 +130,7 @@ export class HNSWIndex implements VectorIndexProvider { * Lifecycle: brainy.ts wires this after plugin activation when (a) the * `vectorStore:mmap` provider is registered AND (b) the storage adapter * resolves a real local path via `getBinaryBlobPath()`. Cloud adapters - * leave it null; HNSWIndex's behaviour is then identical to pre-2.4.0. + * leave it null; JsHnswVectorIndex's behaviour is then identical to pre-2.4.0. */ public setVectorBackend(backend: MmapVectorBackend | null): void { this.vectorBackend = backend @@ -340,10 +340,10 @@ export class HNSWIndex implements VectorIndexProvider { * * @example * ```typescript - * const parent = new HNSWIndex(config) + * const parent = new JsHnswVectorIndex(config) * // ... parent has 1M nodes ... * - * const fork = new HNSWIndex(config) + * const fork = new JsHnswVectorIndex(config) * fork.enableCOW(parent) // <10ms - instant! * * // Reads share data @@ -353,7 +353,7 @@ export class HNSWIndex implements VectorIndexProvider { * await fork.addItem(newItem) // Deep copies only modified nodes * ``` */ - public enableCOW(parent: HNSWIndex): void { + public enableCOW(parent: JsHnswVectorIndex): void { this.cowEnabled = true this.cowParent = parent diff --git a/src/hnsw/mmapVectorBackend.ts b/src/hnsw/mmapVectorBackend.ts index fa9d4e37..0e5cba71 100644 --- a/src/hnsw/mmapVectorBackend.ts +++ b/src/hnsw/mmapVectorBackend.ts @@ -1,10 +1,10 @@ /** * @module hnsw/mmapVectorBackend - * @description Disk-resident vector cache backing HNSWIndex, wrapping the + * @description Disk-resident vector cache backing JsHnswVectorIndex, wrapping the * `vectorStore:mmap` provider (cortex's NativeMmapVectorStore in production). * * **Why this exists.** Brainy's per-entity vector storage hits two ceilings as - * datasets grow: (1) every `HNSWIndex.preloadVectors` does a sequential + * datasets grow: (1) every `JsHnswVectorIndex.preloadVectors` does a sequential * `storage.getNounVector` per id (no batch), and (2) cloud and FS storage both * serialize each vector through JSON / msgpack, blocking zero-copy reads. An * mmap-backed single-file vector store, addressed by the stable int from @@ -20,7 +20,7 @@ * * **Local-FS only in 2.4.0.** Activated when the storage adapter exposes a * real local path via `getBinaryBlobPath()`. Cloud adapters (S3 / R2 / GCS) - * return null and the backend is not constructed, so HNSWIndex falls back to + * return null and the backend is not constructed, so JsHnswVectorIndex falls back to * the existing per-entity read path. Chunked vector segments for remote * storage are the planned 2.4.0 #2 follow-up. */ @@ -38,7 +38,7 @@ import type { * @description Bridge between brainy's UUID-keyed vector API and cortex's * int-slot mmap vector store. Translates UUIDs to stable int slots via the * `EntityIdMapper`, grows the file on demand, and handles read misses by - * surfacing `null` (HNSWIndex's caller does the lazy storage fallback + + * surfacing `null` (JsHnswVectorIndex's caller does the lazy storage fallback + * write-back). The class never touches per-entity storage directly — it owns * only the mmap layer. */ diff --git a/src/hnsw/typeAwareHNSWIndex.ts b/src/hnsw/typeAwareHNSWIndex.ts index 3c17676c..af529608 100644 --- a/src/hnsw/typeAwareHNSWIndex.ts +++ b/src/hnsw/typeAwareHNSWIndex.ts @@ -7,13 +7,13 @@ * - Storage: Already type-first from Phase 1a * * Architecture: - * - One HNSWIndex per NounType (42 total) + * - One JsHnswVectorIndex per NounType (42 total) * - Lazy initialization (indexes created on first use) * - Type routing for optimal performance * - Falls back to multi-type search when type unknown */ -import { HNSWIndex } from './hnswIndex.js' +import { JsHnswVectorIndex } from './hnswIndex.js' import { DistanceFunction, HNSWConfig, @@ -25,7 +25,7 @@ import { euclideanDistance } from '../utils/index.js' import type { BaseStorage } from '../storage/baseStorage.js' import { prodLog } from '../utils/logger.js' -// Default HNSW parameters (same as HNSWIndex) +// Default HNSW parameters (same as JsHnswVectorIndex) const DEFAULT_CONFIG: HNSWConfig = { M: 16, efConstruction: 200, @@ -58,7 +58,7 @@ export interface TypeAwareHNSWStats { */ export class TypeAwareHNSWIndex { // One HNSW index per noun type (lazy initialization) - private indexes: Map = new Map() + private indexes: Map = new Map() // Configuration private config: HNSWConfig @@ -105,7 +105,7 @@ export class TypeAwareHNSWIndex { // Enable COW on each underlying type-specific index for (const [type, parentIndex] of parent.indexes.entries()) { - const childIndex = new HNSWIndex(this.config, this.distanceFunction, { + const childIndex = new JsHnswVectorIndex(this.config, this.distanceFunction, { useParallelization: this.useParallelization, storage: this.storage || undefined, persistMode: this.persistMode @@ -183,9 +183,9 @@ export class TypeAwareHNSWIndex { * Only types with entities get an index. * * @param type The noun type - * @returns HNSWIndex for this type + * @returns JsHnswVectorIndex for this type */ - private getIndexForType(type: NounType): HNSWIndex { + private getIndexForType(type: NounType): JsHnswVectorIndex { // Validate type is a valid NounType const typeIndex = TypeUtils.getNounIndex(type) if (typeIndex === undefined || typeIndex === null || typeIndex < 0) { @@ -197,7 +197,7 @@ export class TypeAwareHNSWIndex { if (!this.indexes.has(type)) { prodLog.info(`Creating HNSW index for type: ${type}`) - const index = new HNSWIndex(this.config, this.distanceFunction, { + const index = new JsHnswVectorIndex(this.config, this.distanceFunction, { useParallelization: this.useParallelization, storage: this.storage || undefined, persistMode: this.persistMode diff --git a/src/index.ts b/src/index.ts index bacd8c5b..b84722df 100644 --- a/src/index.ts +++ b/src/index.ts @@ -296,10 +296,20 @@ import type { StorageAdapter } from './coreTypes.js' -// Export HNSW index -import { HNSWIndex } from './hnsw/hnswIndex.js' +// Export vector index implementation (the JS HNSW path) +import { JsHnswVectorIndex } from './hnsw/hnswIndex.js' -export { HNSWIndex } +export { JsHnswVectorIndex } + +/** + * @deprecated Renamed to {@link JsHnswVectorIndex} in Brainy 8.0. The + * implementation is unchanged — the new name disambiguates the JS HNSW + * path from any native vector-index provider (DiskANN, etc.) that may be + * loaded via the `'vector'` provider key. This alias is provided as a + * compatibility shim for code mid-migration and is removed in the 8.0 + * final cleanup commit. + */ +export const HNSWIndex = JsHnswVectorIndex export type { Vector, diff --git a/src/plugin.ts b/src/plugin.ts index 4efaed8e..4a6caa9c 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -62,7 +62,7 @@ export interface BrainyPluginContext { * - 'graphIndex' — GraphAdjacencyIndex replacement * - 'entityIdMapper' — EntityIdMapper replacement * - 'cache' — UnifiedCache replacement - * - 'hnsw' — HNSWIndex replacement + * - 'hnsw' — JsHnswVectorIndex replacement * - 'roaring' — RoaringBitmap32 replacement * - 'embeddings' — Embedding engine replacement (single text) * - 'embedBatch' — Batch embedding engine (texts[] → vectors[]) @@ -88,7 +88,7 @@ export interface BrainyPluginContext { // (Cortex) that declares `implements MetadataIndexProvider` gets a compile // error the moment a method Brainy depends on is dropped or its signature // drifts. Brainy's own baseline classes (`MetadataIndexManager`, -// `GraphAdjacencyIndex`, `HNSWIndex`, `EntityIdMapper`, `UnifiedCache`) +// `GraphAdjacencyIndex`, `JsHnswVectorIndex`, `EntityIdMapper`, `UnifiedCache`) // implement them too, so the contract can never silently diverge from the // thing Brainy ships. // @@ -281,11 +281,11 @@ export interface CacheProvider { * connection lists as compact delta-varint byte sequences (cortex's * `encodeConnections` / `decodeConnections`). * - * Brainy's `HNSWIndex` consumes this via a `ConnectionsCodec` that translates + * Brainy's `JsHnswVectorIndex` consumes this via a `ConnectionsCodec` that translates * UUIDs to stable int slots via the `EntityIdMapper`, encodes, and persists * the compressed bytes through the binary-blob primitive. On load, the blob * is fetched + decoded back into UUID sets — `setConnectionsCodec()` on - * `HNSWIndex` is the injection point. Read path is dual-format: when no blob + * `JsHnswVectorIndex` is the injection point. Read path is dual-format: when no blob * exists for a node, the connections fall back to the legacy JSON-array path * embedded in `saveHNSWData`, so pre-2.4.0 indexes keep loading unchanged * and convergence to the compressed form happens lazily on next save. @@ -304,7 +304,7 @@ export interface GraphCompressionProvider { /** * The `'vectorStore:mmap'` provider — a static factory class for an mmap-backed - * vector file. Brainy's HNSWIndex uses the static `.create()` / `.open()` + * vector file. Brainy's JsHnswVectorIndex uses the static `.create()` / `.open()` * factories to open a single-file store at a derived path on disk-resident * storage adapters; non-FS adapters with no local-path support skip the mmap * layer and fall back to per-entity vector reads. @@ -325,7 +325,7 @@ export interface VectorStoreMmapProvider { } /** - * An open mmap-vector-store instance — the surface brainy's HNSWIndex consumes + * An open mmap-vector-store instance — the surface brainy's JsHnswVectorIndex consumes * for batch vector reads + lazy migration from per-entity storage on miss. */ export interface VectorStoreMmapInstance { diff --git a/src/transaction/operations/IndexOperations.ts b/src/transaction/operations/IndexOperations.ts index 37db6227..932c93ec 100644 --- a/src/transaction/operations/IndexOperations.ts +++ b/src/transaction/operations/IndexOperations.ts @@ -2,14 +2,14 @@ * Index Operations with Rollback Support * * Provides transactional operations for all indexes: - * - HNSWIndex (unified vector index) + * - JsHnswVectorIndex (unified vector index) * - MetadataIndexManager (roaring bitmap filtering) * - GraphAdjacencyIndex (LSM-tree graph storage) * * Each operation can be executed and rolled back atomically. */ -import type { HNSWIndex } from '../../hnsw/hnswIndex.js' +import type { JsHnswVectorIndex } from '../../hnsw/hnswIndex.js' import type { MetadataIndexManager } from '../../utils/metadataIndex.js' import type { GraphAdjacencyIndex } from '../../graph/graphAdjacencyIndex.js' import type { GraphVerb } from '../../coreTypes.js' @@ -21,13 +21,13 @@ import type { Operation, RollbackAction } from '../types.js' * Rollback strategy: * - Remove item from index * - * Note: Works with both HNSWIndex and TypeAwareHNSWIndex + * Note: Works with both JsHnswVectorIndex and TypeAwareHNSWIndex */ export class AddToHNSWOperation implements Operation { readonly name = 'AddToHNSW' constructor( - private readonly index: HNSWIndex, + private readonly index: JsHnswVectorIndex, private readonly id: string, private readonly vector: number[] ) {} @@ -76,7 +76,7 @@ export class RemoveFromHNSWOperation implements Operation { readonly name = 'RemoveFromHNSW' constructor( - private readonly index: HNSWIndex, + private readonly index: JsHnswVectorIndex, private readonly id: string, private readonly vector: number[] // Required for rollback ) {} @@ -211,7 +211,7 @@ export class BatchAddToHNSWOperation implements Operation { private operations: AddToHNSWOperation[] constructor( - index: HNSWIndex, + index: JsHnswVectorIndex, items: Array<{ id: string; vector: number[] }> ) { this.operations = items.map( diff --git a/src/triple/TripleIntelligenceSystem.ts b/src/triple/TripleIntelligenceSystem.ts index 44691d4e..8b20dbe0 100644 --- a/src/triple/TripleIntelligenceSystem.ts +++ b/src/triple/TripleIntelligenceSystem.ts @@ -13,7 +13,7 @@ * - Fusion: O(k log k) where k = result count */ -import { HNSWIndex } from '../hnsw/hnswIndex.js' +import { JsHnswVectorIndex } from '../hnsw/hnswIndex.js' import { MetadataIndexManager } from '../utils/metadataIndex.js' import { Vector } from '../coreTypes.js' import { NounType } from '../types/graphTypes.js' @@ -230,7 +230,7 @@ class QueryPlanner { */ export class TripleIntelligenceSystem { private metadataIndex: MetadataIndexManager - private hnswIndex: HNSWIndex + private hnswIndex: JsHnswVectorIndex private graphIndex: GraphAdjacencyIndex private metrics: PerformanceMetrics private planner: QueryPlanner @@ -239,7 +239,7 @@ export class TripleIntelligenceSystem { constructor( metadataIndex: MetadataIndexManager, - hnswIndex: HNSWIndex, + hnswIndex: JsHnswVectorIndex, graphIndex: GraphAdjacencyIndex, embedder: (text: string) => Promise, storage: any diff --git a/src/utils/periodicCleanup.ts b/src/utils/periodicCleanup.ts index 0b7ebbc0..66e28cc2 100644 --- a/src/utils/periodicCleanup.ts +++ b/src/utils/periodicCleanup.ts @@ -11,7 +11,7 @@ import { prodLog } from './logger.js' import { DELETED_FIELD, isDeleted } from './metadataNamespace.js' import type { StorageAdapter } from '../coreTypes.js' -import type { HNSWIndex } from '../hnsw/hnswIndex.js' +import type { JsHnswVectorIndex } from '../hnsw/hnswIndex.js' import type { MetadataIndexManager } from './metadataIndex.js' export interface CleanupConfig { @@ -44,7 +44,7 @@ export interface CleanupStats { */ export class PeriodicCleanup { private storage: StorageAdapter - private hnswIndex: HNSWIndex + private hnswIndex: JsHnswVectorIndex private metadataIndex: MetadataIndexManager | null private config: CleanupConfig private stats: CleanupStats @@ -53,7 +53,7 @@ export class PeriodicCleanup { constructor( storage: StorageAdapter, - hnswIndex: HNSWIndex, + hnswIndex: JsHnswVectorIndex, metadataIndex: MetadataIndexManager | null, config: Partial = {} ) { diff --git a/tests/unit/hnsw/lazy-vectors.test.ts b/tests/unit/hnsw/lazy-vectors.test.ts index d7ed9fee..2fff6786 100644 --- a/tests/unit/hnsw/lazy-vectors.test.ts +++ b/tests/unit/hnsw/lazy-vectors.test.ts @@ -11,7 +11,7 @@ import { describe, it, expect, beforeEach } from 'vitest' import { v4 as uuidv4 } from 'uuid' -import { HNSWIndex } from '../../../src/hnsw/hnswIndex.js' +import { JsHnswVectorIndex } from '../../../src/hnsw/hnswIndex.js' import { euclideanDistance } from '../../../src/utils/index.js' import { MemoryStorage } from '../../../src/storage/adapters/memoryStorage.js' @@ -43,12 +43,12 @@ describe('Lazy Vector Loading (B2)', () => { // 1. LAZY MODE: VECTOR EVICTION // ================================================================= describe('vector eviction in lazy mode', () => { - let index: HNSWIndex + let index: JsHnswVectorIndex let storage: MemoryStorage beforeEach(async () => { storage = new MemoryStorage() - index = new HNSWIndex( + index = new JsHnswVectorIndex( { M: 8, efConstruction: 100, @@ -116,7 +116,7 @@ describe('Lazy Vector Loading (B2)', () => { describe('memory mode retains vectors (default)', () => { it('should keep vectors in memory by default', async () => { const storage = new MemoryStorage() - const index = new HNSWIndex( + const index = new JsHnswVectorIndex( { M: 4, efConstruction: 50, efSearch: 20 }, euclideanDistance, { useParallelization: false, storage } @@ -135,7 +135,7 @@ describe('Lazy Vector Loading (B2)', () => { it('should work without storage adapter in memory mode', async () => { // No storage adapter provided - const index = new HNSWIndex( + const index = new JsHnswVectorIndex( { M: 4, efConstruction: 50, efSearch: 20 }, euclideanDistance, { useParallelization: false } @@ -157,7 +157,7 @@ describe('Lazy Vector Loading (B2)', () => { describe('lazy mode without storage', () => { it('should not evict vectors when no storage adapter is configured', async () => { // vectorStorage: 'lazy' but no storage — vectors should stay in memory - const index = new HNSWIndex( + const index = new JsHnswVectorIndex( { M: 4, efConstruction: 50, @@ -185,7 +185,7 @@ describe('Lazy Vector Loading (B2)', () => { describe('lazy mode with quantization', () => { it('should use SQ8 for traversal and load full vectors for rerank', async () => { const storage = new MemoryStorage() - const index = new HNSWIndex( + const index = new JsHnswVectorIndex( { M: 8, efConstruction: 100, @@ -221,7 +221,7 @@ describe('Lazy Vector Loading (B2)', () => { it('should return results sorted by exact distance after rerank', async () => { const storage = new MemoryStorage() - const index = new HNSWIndex( + const index = new JsHnswVectorIndex( { M: 8, efConstruction: 100, @@ -257,7 +257,7 @@ describe('Lazy Vector Loading (B2)', () => { describe('multiple searches in lazy mode', () => { it('should handle repeated searches correctly', async () => { const storage = new MemoryStorage() - const index = new HNSWIndex( + const index = new JsHnswVectorIndex( { M: 8, efConstruction: 100, diff --git a/tests/unit/hnsw/quantization.test.ts b/tests/unit/hnsw/quantization.test.ts index 8ea50d63..d3bb7143 100644 --- a/tests/unit/hnsw/quantization.test.ts +++ b/tests/unit/hnsw/quantization.test.ts @@ -21,7 +21,7 @@ import { serializeSQ8, deserializeSQ8 } from '../../../src/utils/vectorQuantization.js' -import { HNSWIndex } from '../../../src/hnsw/hnswIndex.js' +import { JsHnswVectorIndex } from '../../../src/hnsw/hnswIndex.js' import { euclideanDistance } from '../../../src/utils/index.js' import { MemoryStorage } from '../../../src/storage/adapters/memoryStorage.js' @@ -286,14 +286,14 @@ describe('SQ8 Quantization', () => { // 4. HNSW SEARCH WITH QUANTIZATION // ================================================================= describe('HNSW search with quantization', () => { - let index: HNSWIndex + let index: JsHnswVectorIndex let storage: MemoryStorage const dim = 32 // Small dimension for fast tests let ids: string[] beforeEach(async () => { storage = new MemoryStorage() - index = new HNSWIndex( + index = new JsHnswVectorIndex( { M: 8, efConstruction: 100, @@ -365,7 +365,7 @@ describe('SQ8 Quantization', () => { describe('two-phase rerank', () => { it('should accept rerank options in search', async () => { const storage = new MemoryStorage() - const index = new HNSWIndex( + const index = new JsHnswVectorIndex( { M: 8, efConstruction: 100, @@ -399,7 +399,7 @@ describe('SQ8 Quantization', () => { it('reranked results should be sorted by exact distance', async () => { const storage = new MemoryStorage() - const index = new HNSWIndex( + const index = new JsHnswVectorIndex( { M: 8, efConstruction: 100, @@ -432,7 +432,7 @@ describe('SQ8 Quantization', () => { describe('configuration defaults', () => { it('should disable quantization by default', async () => { const storage = new MemoryStorage() - const defaultIndex = new HNSWIndex( + const defaultIndex = new JsHnswVectorIndex( { M: 4, efConstruction: 50, efSearch: 20 }, euclideanDistance, { useParallelization: false, storage } @@ -456,7 +456,7 @@ describe('SQ8 Quantization', () => { it('should use default rerankMultiplier of 3', async () => { const storage = new MemoryStorage() - const index = new HNSWIndex( + const index = new JsHnswVectorIndex( { M: 4, efConstruction: 50, @@ -480,7 +480,7 @@ describe('SQ8 Quantization', () => { it('should default vectorStorage to memory mode', async () => { const storage = new MemoryStorage() - const index = new HNSWIndex( + const index = new JsHnswVectorIndex( { M: 4, efConstruction: 50, efSearch: 20 }, euclideanDistance, { useParallelization: false, storage }