kirograph 0.20.1 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -3
- package/dist/bin/commands/data.js +52 -0
- package/dist/bin/commands/data.js.map +2 -2
- package/dist/bin/commands/docs.js +2 -1
- package/dist/bin/commands/docs.js.map +2 -2
- package/dist/bin/commands/gain.js +21 -1
- package/dist/bin/commands/gain.js.map +2 -2
- package/dist/bin/commands/status.js +23 -1
- package/dist/bin/commands/status.js.map +2 -2
- package/dist/bin/installer/config-prompt.js +30 -1
- package/dist/bin/installer/config-prompt.js.map +2 -2
- package/dist/bin/installer/index.js +108 -0
- package/dist/bin/installer/index.js.map +2 -2
- package/dist/bin/kirograph.js +1 -1
- package/dist/config.js +19 -2
- package/dist/config.js.map +2 -2
- package/dist/core/pipeline.js +3 -1
- package/dist/core/pipeline.js.map +2 -2
- package/dist/data/indexer.js +4 -4
- package/dist/data/indexer.js.map +2 -2
- package/dist/data/linker.js +9 -5
- package/dist/data/linker.js.map +2 -2
- package/dist/data/linker.test.js +60 -0
- package/dist/data/linker.test.js.map +7 -0
- package/dist/data/parsers/__fixtures__/pdf-inspector-stub.js +41 -0
- package/dist/data/parsers/__fixtures__/pdf-inspector-stub.js.map +7 -0
- package/dist/data/parsers/index.js +3 -1
- package/dist/data/parsers/index.js.map +2 -2
- package/dist/data/parsers/pdf.js +95 -0
- package/dist/data/parsers/pdf.js.map +7 -0
- package/dist/data/parsers/pdf.test.js +125 -0
- package/dist/data/parsers/pdf.test.js.map +7 -0
- package/dist/data/queries.js +39 -2
- package/dist/data/queries.js.map +2 -2
- package/dist/data/types.js.map +1 -1
- package/dist/db/data-schema.sql +2 -1
- package/dist/db/database.js +7 -0
- package/dist/db/database.js.map +2 -2
- package/dist/docs/indexer.js +2 -1
- package/dist/docs/indexer.js.map +2 -2
- package/dist/docs/queries.js +2 -1
- package/dist/docs/queries.js.map +2 -2
- package/dist/docs/vectors.js +46 -5
- package/dist/docs/vectors.js.map +2 -2
- package/dist/index.js +1 -0
- package/dist/index.js.map +2 -2
- package/dist/mcp/tools.js +1 -1
- package/dist/mcp/tools.js.map +2 -2
- package/dist/memory/index.js +2 -1
- package/dist/memory/index.js.map +2 -2
- package/dist/memory/vectors.js +52 -8
- package/dist/memory/vectors.js.map +3 -3
- package/dist/types.js.map +2 -2
- package/dist/vectors/index.js +66 -3
- package/dist/vectors/index.js.map +2 -2
- package/dist/vectors/turbovec-index.js +189 -0
- package/dist/vectors/turbovec-index.js.map +7 -0
- package/package.json +7 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/vectors/index.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * KiroGraph Vector Manager\n *\n * Semantic search via configurable local embedding models using @huggingface/transformers v3.\n * Mirrors CodeGraph src/vectors/ (embedder.ts + manager.ts) adapted for KiroGraph:\n * - Cache dir: ~/.kirograph/models/ (not ~/.codegraph/models/)\n * - Embeddings stored in the `vectors` SQLite table\n * - Cosine similarity search done in-process by default (no extra deps)\n * - ANN search via sqlite-vec opt-in: set config.useVecIndex = true\n * (requires `npm install better-sqlite3 sqlite-vec`)\n * - Disabled by default; opt-in via config.enableEmbeddings = true\n */\n\nimport * as path from 'path';\nimport * as fs from 'fs';\nimport { homedir } from 'os';\nimport { logDebug, logWarn, logError } from '../errors';\nimport type { KiroGraphConfig } from '../config';\nimport type { Node } from '../types';\nimport type { GraphDatabase } from '../db/database';\nimport { VecIndex } from './vec-index';\nimport { OramaIndex } from './orama-index';\nimport { PGliteIndex } from './pglite-index';\nimport { LanceDBIndex } from './lancedb-index';\nimport { QdrantIndex } from './qdrant-index';\nimport { TypesenseIndex } from './typesense-index';\n\n// \u2500\u2500 Constants \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst DEFAULT_MODEL = 'nomic-ai/nomic-embed-text-v1.5';\nconst DEFAULT_EMBEDDING_DIM = 768;\nconst GLOBAL_MODELS_DIR = path.join(homedir(), '.kirograph', 'models');\nconst BATCH_SIZE = 32;\nconst MIN_BATCH_SIZE = 4;\nconst MAX_TOKEN_CHARS = 2000;\n\n/** Node kinds worth embedding \u2014 high information density */\nconst EMBEDDABLE_KINDS = new Set<Node['kind']>([\n 'function', 'method', 'class', 'interface', 'type_alias', 'component', 'module',\n]);\n\n// \u2500\u2500 Embedder \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ntype Pipeline = any;\nlet transformers: typeof import('@huggingface/transformers') | null = null;\n\nasync function getTransformers() {\n if (!transformers) {\n transformers = await import('@huggingface/transformers');\n }\n return transformers;\n}\n\n/**\n * Build a searchable text representation of a node.\n * Mirrors CodeGraph TextEmbedder.createNodeText().\n * Truncated to MAX_TOKEN_CHARS to stay within the model's memory-safe token limit.\n * Priority: kind + name > qualified name > file path > signature > docstring.\n * This ensures the most important search signal is always preserved.\n */\nfunction nodeToText(node: Node): string {\n const parts = [`${node.kind}: ${node.name}`];\n if (node.qualifiedName && node.qualifiedName !== node.name) {\n parts.push(`path: ${node.qualifiedName}`);\n }\n parts.push(`file: ${node.filePath}`);\n if (node.signature) parts.push(`signature: ${node.signature}`);\n if (node.docstring) parts.push(`documentation: ${node.docstring}`);\n const text = parts.join('\\n');\n if (text.length > MAX_TOKEN_CHARS) {\n logDebug(`nodeToText: truncated ${node.id} from ${text.length} to ${MAX_TOKEN_CHARS} chars`);\n return text.slice(0, MAX_TOKEN_CHARS);\n }\n return text;\n}\n\n/** Cosine similarity between two equal-length Float32Arrays. */\nfunction cosine(a: Float32Array, b: Float32Array): number {\n let dot = 0, na = 0, nb = 0;\n for (let i = 0; i < a.length; i++) {\n dot += a[i]! * b[i]!;\n na += a[i]! * a[i]!;\n nb += b[i]! * b[i]!;\n }\n const denom = Math.sqrt(na) * Math.sqrt(nb);\n return denom === 0 ? 0 : dot / denom;\n}\n\n/** Extract a flat Float32Array from the transformer pipeline output. */\nfunction toFloat32Array(data: unknown): Float32Array {\n if (data instanceof Float32Array) return data;\n if (Array.isArray(data)) return new Float32Array(data);\n if (data && typeof data === 'object' && 'length' in data) {\n return Float32Array.from(Array.from(data as ArrayLike<number>));\n }\n throw new Error('Unsupported embedding data format');\n}\n\n// \u2500\u2500 VectorManager \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport class VectorManager {\n private pipeline: Pipeline | null = null;\n private _initialized = false;\n private vecIndex: VecIndex | null = null;\n private oramaIndex: OramaIndex | null = null;\n private pgliteIndex: PGliteIndex | null = null;\n private lancedbIndex: LanceDBIndex | null = null;\n private qdrantIndex: QdrantIndex | null = null;\n private typesenseIndex: TypesenseIndex | null = null;\n private _engineFallback: string | null = null;\n\n constructor(\n private readonly db: GraphDatabase,\n private readonly config: KiroGraphConfig,\n private readonly projectRoot?: string,\n ) {}\n\n isInitialized(): boolean {\n return this.config.enableEmbeddings === true && this._initialized;\n }\n\n /** Non-null when the configured engine failed to load and cosine is being used instead. */\n getEngineFallback(): string | null {\n return this._engineFallback;\n }\n\n /**\n * Load the embedding model. No-op when embeddings are disabled.\n * Fails silently so callers can continue without semantic search.\n * When config.useVecIndex is true, also initializes the sqlite-vec ANN index.\n */\n async initialize(onProgress?: (file: string, loaded: number, total: number, done: boolean) => void): Promise<void> {\n if (!this.config.enableEmbeddings) {\n logDebug('VectorManager: embeddings disabled');\n return;\n }\n if (this._initialized) return;\n\n const rawModel = this.config.embeddingModel || DEFAULT_MODEL;\n // Guard against an invalid model ID (e.g. 'y' typed by mistake in the installer)\n const modelId = rawModel.includes('/') ? rawModel : DEFAULT_MODEL;\n if (rawModel !== modelId) {\n logWarn(`VectorManager: invalid embeddingModel \"${rawModel}\", using default instead`, { default: DEFAULT_MODEL });\n }\n const cacheDir = GLOBAL_MODELS_DIR;\n\n try {\n const { pipeline, env } = await getTransformers();\n env.cacheDir = cacheDir;\n\n if (!fs.existsSync(cacheDir)) {\n fs.mkdirSync(cacheDir, { recursive: true });\n }\n\n // Skip remote check if model already cached (HuggingFace uses '--' as path separator)\n // HuggingFace transformers v3 stores models as <org>/<model>/ (v2 used <org>--<model>)\n const cached = fs.existsSync(path.join(cacheDir, modelId));\n if (cached) env.allowRemoteModels = false;\n\n let lastFile = '';\n this.pipeline = await pipeline('feature-extraction', modelId, {\n dtype: 'auto',\n ...(!cached && onProgress ? {\n progress_callback: (p: { status: string; file?: string; loaded?: number; total?: number }) => {\n if (p.status === 'progress' && p.file) {\n lastFile = p.file;\n onProgress(p.file, p.loaded ?? 0, p.total ?? 0, false);\n } else if (p.status === 'done' && lastFile) {\n onProgress(lastFile, 1, 1, true);\n lastFile = '';\n }\n },\n } : {}),\n });\n\n // Validate embeddingDim against the model's actual output shape.\n // Run a single test embedding and compare dims[1] to config.embeddingDim.\n // If they differ, warn and update the runtime dim so downstream engines\n // are initialised with the correct size (config.json is not rewritten here).\n try {\n const testOut = await this.pipeline('test', { pooling: 'mean', normalize: true });\n const actualDim: number = testOut.dims?.[1] ?? (testOut.data?.length as number);\n const configuredDim = this.config.embeddingDim ?? DEFAULT_EMBEDDING_DIM;\n if (actualDim && actualDim !== configuredDim) {\n logWarn(\n `VectorManager: embeddingDim mismatch \u2014 config says ${configuredDim} but model outputs ${actualDim}. Using actual dim.`,\n { model: modelId, configuredDim, actualDim },\n );\n // Patch the runtime config so all engine constructors below use the correct dim\n (this.config as unknown as Record<string, unknown>).embeddingDim = actualDim;\n }\n } catch { /* test embedding failed \u2014 proceed with configured dim */ }\n\n this._initialized = true;\n logDebug('VectorManager: model loaded', { modelId, embeddingDim: this.config.embeddingDim ?? DEFAULT_EMBEDDING_DIM });\n } catch (err) {\n logError('VectorManager: failed to load embedding model', {\n model: modelId,\n error: String(err),\n });\n this._initialized = false;\n return;\n }\n\n // Initialize the selected search engine\n const engine = this.config.semanticEngine ?? (this.config.useVecIndex ? 'sqlite-vec' : 'cosine');\n\n if (this.projectRoot && engine !== 'cosine') {\n const kirographDir = path.join(this.projectRoot, '.kirograph');\n\n const embeddingDim = this.config.embeddingDim ?? DEFAULT_EMBEDDING_DIM;\n\n if (engine === 'sqlite-vec') {\n this.vecIndex = new VecIndex(kirographDir, embeddingDim);\n await this.vecIndex.initialize();\n if (this.vecIndex.isAvailable()) {\n logDebug('VectorManager: sqlite-vec ANN index ready');\n } else {\n this._engineFallback = 'sqlite-vec unavailable \u2014 run: npm install better-sqlite3 sqlite-vec';\n logDebug('VectorManager: sqlite-vec unavailable, falling back to in-process cosine');\n }\n } else if (engine === 'orama') {\n this.oramaIndex = new OramaIndex(kirographDir, embeddingDim);\n await this.oramaIndex.initialize();\n if (this.oramaIndex.isAvailable()) {\n logDebug('VectorManager: Orama hybrid index ready');\n } else {\n this._engineFallback = 'orama unavailable \u2014 run: npm install @orama/orama @orama/plugin-data-persistence';\n logDebug('VectorManager: Orama unavailable, falling back to in-process cosine');\n }\n } else if (engine === 'pglite') {\n this.pgliteIndex = new PGliteIndex(kirographDir, embeddingDim);\n await this.pgliteIndex.initialize();\n if (this.pgliteIndex.isAvailable()) {\n logDebug('VectorManager: PGlite+pgvector hybrid index ready');\n } else {\n this._engineFallback = 'pglite unavailable \u2014 run: npm install @electric-sql/pglite';\n logDebug('VectorManager: PGlite unavailable, falling back to in-process cosine');\n }\n } else if (engine === 'lancedb') {\n this.lancedbIndex = new LanceDBIndex(kirographDir, embeddingDim);\n await this.lancedbIndex.initialize();\n if (this.lancedbIndex.isAvailable()) {\n logDebug('VectorManager: LanceDB ANN index ready');\n } else {\n this._engineFallback = 'lancedb unavailable \u2014 run: npm install @lancedb/lancedb';\n logDebug('VectorManager: LanceDB unavailable, falling back to in-process cosine');\n }\n } else if (engine === 'qdrant') {\n this.qdrantIndex = new QdrantIndex(kirographDir, embeddingDim);\n await this.qdrantIndex.initialize();\n if (this.qdrantIndex.isAvailable()) {\n logDebug('VectorManager: Qdrant ANN index ready');\n } else {\n this._engineFallback = 'qdrant unavailable \u2014 run: npm install qdrant-local';\n logDebug('VectorManager: Qdrant unavailable, falling back to in-process cosine');\n }\n } else if (engine === 'typesense') {\n this.typesenseIndex = new TypesenseIndex(kirographDir, embeddingDim);\n await this.typesenseIndex.initialize();\n if (this.typesenseIndex.isAvailable()) {\n logDebug('VectorManager: Typesense ANN index ready');\n } else {\n const reason = this.typesenseIndex.getFailReason();\n this._engineFallback = reason\n ? `typesense initialization failed: ${reason}`\n : 'typesense unavailable \u2014 run: npm install typesense';\n logDebug('VectorManager: Typesense unavailable, falling back to in-process cosine');\n }\n }\n }\n }\n\n /**\n * Embed a single node and persist to the vectors table.\n * Skips silently when disabled; logs on failure without throwing.\n */\n async embedNode(node: Node): Promise<void> {\n if (!this.config.enableEmbeddings) return;\n if (!this._initialized || !this.pipeline) {\n logError('Embedding model unavailable', { model: this.config.embeddingModel });\n return;\n }\n if (!EMBEDDABLE_KINDS.has(node.kind)) return;\n\n try {\n const text = `search_document: ${nodeToText(node)}`;\n const output = await this.pipeline(text, { pooling: 'mean', normalize: true });\n const embedding = toFloat32Array(output.data);\n // non-cosine engines are sole stores of record when active \u2014 skip the SQLite vectors table\n if (!this.vecIndex?.isAvailable() && !this.oramaIndex?.isAvailable() && !this.pgliteIndex?.isAvailable() && !this.lancedbIndex?.isAvailable() && !this.qdrantIndex?.isAvailable() && !this.typesenseIndex?.isAvailable()) {\n this.db.storeEmbedding(node.id, embedding, this.config.embeddingModel || DEFAULT_MODEL);\n }\n this.vecIndex?.upsert(node.id, embedding);\n if (this.oramaIndex?.isAvailable()) await this.oramaIndex.upsert(node, embedding);\n if (this.pgliteIndex?.isAvailable()) await this.pgliteIndex.upsert(node, embedding);\n if (this.lancedbIndex?.isAvailable()) await this.lancedbIndex.upsert(node, embedding);\n if (this.qdrantIndex?.isAvailable()) await this.qdrantIndex.upsert(node, embedding);\n if (this.typesenseIndex?.isAvailable()) await this.typesenseIndex.upsert(node, embedding);\n } catch (err) {\n logWarn('Failed to embed node', { nodeId: node.id, error: String(err) });\n }\n }\n\n /** Number of entries currently in the active ANN/hybrid index (0 when not in use). */\n async vecIndexCount(): Promise<number> {\n if (this.vecIndex?.isAvailable()) return this.vecIndex.count();\n if (this.oramaIndex?.isAvailable()) return this.oramaIndex.count();\n if (this.pgliteIndex?.isAvailable()) return this.pgliteIndex.count();\n if (this.lancedbIndex?.isAvailable()) return this.lancedbIndex.count();\n if (this.qdrantIndex?.isAvailable()) return this.qdrantIndex.count();\n if (this.typesenseIndex?.isAvailable()) return this.typesenseIndex.count();\n return 0;\n }\n\n /**\n * Remove embeddings for the given node IDs from the active index.\n * For cosine the `vectors` SQLite table is cleaned up automatically via FK cascade\n * when nodes are deleted. For sqlite-vec, orama, and pglite the engine itself is\n * the sole store of record, so we delete from it explicitly here.\n */\n async deleteEmbeddings(nodeIds: string[]): Promise<void> {\n for (const id of nodeIds) {\n this.vecIndex?.delete(id);\n if (this.oramaIndex?.isAvailable()) await this.oramaIndex.delete(id);\n if (this.pgliteIndex?.isAvailable()) await this.pgliteIndex.delete(id);\n if (this.lancedbIndex?.isAvailable()) await this.lancedbIndex.delete(id);\n if (this.qdrantIndex?.isAvailable()) await this.qdrantIndex.delete(id);\n if (this.typesenseIndex?.isAvailable()) await this.typesenseIndex.delete(id);\n }\n }\n\n /**\n * Embed all eligible nodes in the database that don't yet have embeddings.\n * Streams nodes in pages to avoid loading the entire node set into memory \u2014\n * critical for large codebases (100K+ symbols) where a single getAllNodes()\n * call can exhaust the Node.js heap or the WASM linear memory.\n *\n * Uses dynamic batch sizing: starts at BATCH_SIZE, halves on OOM errors,\n * and recovers back to full size after successful batches.\n *\n * Emits a pre-flight warning via onProgress when the embeddable node count\n * exceeds LARGE_CODEBASE_THRESHOLD so the CLI can surface it to the user.\n */\n async embedAll(onProgress?: (current: number, total: number) => void): Promise<number> {\n if (!this.isInitialized() || !this.pipeline) return 0;\n\n const modelId = this.config.embeddingModel || DEFAULT_MODEL;\n const EMBEDDABLE_KINDS_ARRAY = [...EMBEDDABLE_KINDS] as string[];\n\n // Pre-flight: count embeddable nodes without loading them\n const totalEmbeddable = this.db.countEmbeddableNodes(EMBEDDABLE_KINDS_ARRAY);\n const LARGE_CODEBASE_THRESHOLD = 100_000;\n if (totalEmbeddable > LARGE_CODEBASE_THRESHOLD) {\n // Signal the large-codebase warning via a special progress event.\n // current=-1 is the sentinel; the CLI renderer checks for it.\n onProgress?.(-1, totalEmbeddable);\n }\n\n // Collect already-embedded IDs (needed to skip nodes already in the index)\n const existingIds = new Set(\n this.typesenseIndex?.isAvailable()\n ? await this.typesenseIndex.getEmbeddedNodeIds()\n : this.qdrantIndex?.isAvailable()\n ? await this.qdrantIndex.getEmbeddedNodeIds()\n : this.lancedbIndex?.isAvailable()\n ? await this.lancedbIndex.getEmbeddedNodeIds()\n : this.pgliteIndex?.isAvailable()\n ? await this.pgliteIndex.getEmbeddedNodeIds()\n : this.oramaIndex?.isAvailable()\n ? await this.oramaIndex.getEmbeddedNodeIds()\n : this.vecIndex?.isAvailable()\n ? this.vecIndex.getEmbeddedNodeIds()\n : this.db.getEmbeddedNodeIds()\n );\n\n // Stream nodes in pages \u2014 never hold more than PAGE_SIZE nodes in memory at once\n const PAGE_SIZE = 2000;\n let pageOffset = 0;\n let processed = 0;\n let currentBatchSize = BATCH_SIZE;\n let consecutiveSuccesses = 0;\n\n // We need to know the total pending count for progress reporting.\n // Approximate: totalEmbeddable - existingIds.size (may be slightly off if\n // existingIds contains IDs for non-embeddable kinds, but close enough).\n const totalPending = Math.max(0, totalEmbeddable - existingIds.size);\n if (totalPending === 0) {\n if (this.oramaIndex?.isAvailable()) await this.oramaIndex.save();\n return 0;\n }\n\n logDebug(`VectorManager: embedding ~${totalPending} nodes (${existingIds.size} already embedded, streaming in pages of ${PAGE_SIZE})`);\n\n // Buffer of pending nodes from the current page\n let pageBuffer: Node[] = [];\n let pageBufferOffset = 0; // index within pageBuffer\n let pageExhausted = false;\n\n const fetchNextPage = () => {\n const page = this.db.getEmbeddableNodesPaged(EMBEDDABLE_KINDS_ARRAY, PAGE_SIZE, pageOffset);\n pageOffset += page.length;\n pageBuffer = page.filter(n => !existingIds.has(n.id));\n pageBufferOffset = 0;\n if (page.length < PAGE_SIZE) pageExhausted = true;\n };\n\n fetchNextPage();\n\n while (pageBuffer.length > 0 || (!pageExhausted && pageBufferOffset >= pageBuffer.length)) {\n // Refill page buffer when exhausted\n if (pageBufferOffset >= pageBuffer.length) {\n if (pageExhausted) break;\n fetchNextPage();\n if (pageBuffer.length === 0) break;\n }\n\n // Slice a batch from the current page buffer\n const batch = pageBuffer.slice(pageBufferOffset, pageBufferOffset + currentBatchSize);\n if (batch.length === 0) break;\n\n const texts = batch.map(n => `search_document: ${nodeToText(n)}`);\n\n try {\n const outputs = await this.pipeline(texts, { pooling: 'mean', normalize: true });\n const dims: number[] = outputs.dims;\n const dim = dims[1] ?? (this.config.embeddingDim ?? DEFAULT_EMBEDDING_DIM);\n const flat = toFloat32Array(outputs.data);\n\n const tsNodes: Node[] = [];\n const tsEmbeddings: Float32Array[] = [];\n const qdNodes: Node[] = [];\n const qdEmbeddings: Float32Array[] = [];\n\n for (let j = 0; j < batch.length; j++) {\n const node = batch[j]!;\n const embedding = flat.slice(j * dim, (j + 1) * dim);\n if (!this.vecIndex?.isAvailable() && !this.oramaIndex?.isAvailable() && !this.pgliteIndex?.isAvailable() && !this.lancedbIndex?.isAvailable() && !this.qdrantIndex?.isAvailable() && !this.typesenseIndex?.isAvailable()) {\n this.db.storeEmbedding(node.id, embedding, modelId);\n }\n this.vecIndex?.upsert(node.id, embedding);\n if (this.oramaIndex?.isAvailable()) await this.oramaIndex.upsert(node, embedding);\n if (this.pgliteIndex?.isAvailable()) await this.pgliteIndex.upsert(node, embedding);\n if (this.lancedbIndex?.isAvailable()) await this.lancedbIndex.upsert(node, embedding);\n if (this.qdrantIndex?.isAvailable()) { qdNodes.push(node); qdEmbeddings.push(embedding); }\n if (this.typesenseIndex?.isAvailable()) { tsNodes.push(node); tsEmbeddings.push(embedding); }\n }\n\n if (qdNodes.length > 0) await this.qdrantIndex!.bulkUpsert(qdNodes, qdEmbeddings);\n if (tsNodes.length > 0) await this.typesenseIndex!.bulkUpsert(tsNodes, tsEmbeddings);\n\n pageBufferOffset += batch.length;\n processed += batch.length;\n consecutiveSuccesses++;\n\n if (currentBatchSize < BATCH_SIZE && consecutiveSuccesses >= 5) {\n currentBatchSize = Math.min(currentBatchSize * 2, BATCH_SIZE);\n logDebug(`VectorManager: batch size recovered to ${currentBatchSize}`);\n consecutiveSuccesses = 0;\n }\n } catch (err) {\n const errMsg = String(err);\n const isOOM = errMsg.includes('bad allocation') || errMsg.includes('OOM') || errMsg.includes('out of memory');\n\n if (isOOM && currentBatchSize > MIN_BATCH_SIZE) {\n currentBatchSize = Math.max(Math.floor(currentBatchSize / 2), MIN_BATCH_SIZE);\n consecutiveSuccesses = 0;\n logWarn(`VectorManager: OOM at batch offset ${pageBufferOffset} \u2014 reducing batch size to ${currentBatchSize} and retrying`, {\n batchSize: currentBatchSize,\n nodeIds: batch.slice(0, 3).map(n => n.id),\n });\n // Don't advance pageBufferOffset \u2014 retry the same batch\n } else if (isOOM && currentBatchSize <= MIN_BATCH_SIZE) {\n logError(`VectorManager: OOM even at minimum batch size ${MIN_BATCH_SIZE} \u2014 skipping ${batch.length} nodes`, {\n batchStart: pageBufferOffset,\n skippedNodes: batch.map(n => `${n.kind}:${n.name} (${n.filePath})`).slice(0, 5),\n });\n pageBufferOffset += batch.length;\n processed += batch.length;\n consecutiveSuccesses = 0;\n } else {\n logWarn(`VectorManager: batch embedding failed at offset ${pageBufferOffset}`, {\n batchSize: currentBatchSize,\n error: errMsg,\n });\n pageBufferOffset += batch.length;\n processed += batch.length;\n consecutiveSuccesses = 0;\n }\n }\n\n onProgress?.(processed, totalPending);\n }\n\n if (this.oramaIndex?.isAvailable()) await this.oramaIndex.save();\n\n logDebug(`VectorManager: embedding complete \u2014 ${processed} processed, final batch size: ${currentBatchSize}`);\n\n return processed;\n }\n\n /**\n * Semantic search: embed the query and return top-N nodes by similarity.\n *\n * When sqlite-vec is available (useVecIndex: true), delegates ANN search to\n * VecIndex (fast, sub-linear). Otherwise falls back to in-process cosine\n * similarity over all stored embeddings (linear scan, no extra deps).\n *\n * Returns empty array when not initialized.\n */\n async search(query: string, topN = 10): Promise<Node[]> {\n if (!this.isInitialized() || !this.pipeline) return [];\n\n try {\n const text = `search_query: ${query}`;\n const output = await this.pipeline(text, { pooling: 'mean', normalize: true });\n const queryVec = toFloat32Array(output.data);\n\n let nodeIds: string[];\n\n if (this.pgliteIndex?.isAvailable()) {\n // Hybrid search via PGlite+pgvector \u2014 exact vector + full-text in one SQL query\n nodeIds = await this.pgliteIndex.search(query, queryVec, topN);\n } else if (this.oramaIndex?.isAvailable()) {\n // Hybrid search via Orama \u2014 full-text + vector combined\n nodeIds = await this.oramaIndex.search(query, queryVec, topN);\n } else if (this.lancedbIndex?.isAvailable()) {\n // ANN search via LanceDB \u2014 columnar Lance format, cosine metric\n nodeIds = await this.lancedbIndex.search(queryVec, topN);\n } else if (this.qdrantIndex?.isAvailable()) {\n // ANN search via Qdrant \u2014 HNSW index, cosine metric\n nodeIds = await this.qdrantIndex.search(queryVec, topN);\n } else if (this.typesenseIndex?.isAvailable()) {\n // ANN search via Typesense \u2014 HNSW index, cosine metric\n nodeIds = await this.typesenseIndex.search(queryVec, topN);\n } else if (this.vecIndex?.isAvailable()) {\n // ANN search via sqlite-vec \u2014 fast, sub-linear\n nodeIds = this.vecIndex.search(queryVec, topN);\n } else {\n // In-process cosine similarity \u2014 linear scan over all stored embeddings\n const allEmbeddings = this.db.getAllEmbeddings();\n nodeIds = allEmbeddings\n .map(({ nodeId, embedding }) => ({ nodeId, score: cosine(queryVec, embedding) }))\n .filter(r => r.score >= 0.3)\n .sort((a, b) => b.score - a.score)\n .slice(0, topN)\n .map(r => r.nodeId);\n }\n\n const results: Node[] = [];\n for (const nodeId of nodeIds) {\n const node = this.db.getNode(nodeId);\n if (node) results.push(node);\n }\n return results;\n } catch (err) {\n logWarn('VectorManager: search failed', { error: String(err) });\n return [];\n }\n }\n\n /** Release engine resources (e.g. kill Qdrant child process). */\n close(): void {\n this.qdrantIndex?.close();\n this.typesenseIndex?.close();\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["/**\n * KiroGraph Vector Manager\n *\n * Semantic search via configurable local embedding models using @huggingface/transformers v3.\n * Mirrors CodeGraph src/vectors/ (embedder.ts + manager.ts) adapted for KiroGraph:\n * - Cache dir: ~/.kirograph/models/ (not ~/.codegraph/models/)\n * - Embeddings stored in the `vectors` SQLite table\n * - Cosine similarity search done in-process by default (no extra deps)\n * - ANN search via sqlite-vec opt-in: set config.useVecIndex = true\n * (requires `npm install better-sqlite3 sqlite-vec`)\n * - Disabled by default; opt-in via config.enableEmbeddings = true\n */\n\nimport * as path from 'path';\nimport * as fs from 'fs';\nimport { homedir } from 'os';\nimport { logDebug, logWarn, logError } from '../errors';\nimport type { KiroGraphConfig } from '../config';\nimport type { Node } from '../types';\nimport type { GraphDatabase } from '../db/database';\nimport { VecIndex } from './vec-index';\nimport { OramaIndex } from './orama-index';\nimport { PGliteIndex } from './pglite-index';\nimport { LanceDBIndex } from './lancedb-index';\nimport { QdrantIndex } from './qdrant-index';\nimport { TypesenseIndex } from './typesense-index';\nimport { TurboQuantIndex, writeTurboQuantStats } from './turboquant-index';\nimport { TurboVecIndex } from './turbovec-index';\n\n// \u2500\u2500 Constants \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst DEFAULT_MODEL = 'nomic-ai/nomic-embed-text-v1.5';\nconst DEFAULT_EMBEDDING_DIM = 768;\nconst GLOBAL_MODELS_DIR = path.join(homedir(), '.kirograph', 'models');\nconst BATCH_SIZE = 32;\nconst MIN_BATCH_SIZE = 4;\nconst MAX_TOKEN_CHARS = 2000;\n\n/** Node kinds worth embedding \u2014 high information density */\nconst EMBEDDABLE_KINDS = new Set<Node['kind']>([\n 'function', 'method', 'class', 'interface', 'type_alias', 'component', 'module',\n]);\n\n// \u2500\u2500 Embedder \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ntype Pipeline = any;\nlet transformers: typeof import('@huggingface/transformers') | null = null;\n\nasync function getTransformers() {\n if (!transformers) {\n transformers = await import('@huggingface/transformers');\n }\n return transformers;\n}\n\n/**\n * Build a searchable text representation of a node.\n * Mirrors CodeGraph TextEmbedder.createNodeText().\n * Truncated to MAX_TOKEN_CHARS to stay within the model's memory-safe token limit.\n * Priority: kind + name > qualified name > file path > signature > docstring.\n * This ensures the most important search signal is always preserved.\n */\nfunction nodeToText(node: Node): string {\n const parts = [`${node.kind}: ${node.name}`];\n if (node.qualifiedName && node.qualifiedName !== node.name) {\n parts.push(`path: ${node.qualifiedName}`);\n }\n parts.push(`file: ${node.filePath}`);\n if (node.signature) parts.push(`signature: ${node.signature}`);\n if (node.docstring) parts.push(`documentation: ${node.docstring}`);\n const text = parts.join('\\n');\n if (text.length > MAX_TOKEN_CHARS) {\n logDebug(`nodeToText: truncated ${node.id} from ${text.length} to ${MAX_TOKEN_CHARS} chars`);\n return text.slice(0, MAX_TOKEN_CHARS);\n }\n return text;\n}\n\n/** Cosine similarity between two equal-length Float32Arrays. */\nfunction cosine(a: Float32Array, b: Float32Array): number {\n let dot = 0, na = 0, nb = 0;\n for (let i = 0; i < a.length; i++) {\n dot += a[i]! * b[i]!;\n na += a[i]! * a[i]!;\n nb += b[i]! * b[i]!;\n }\n const denom = Math.sqrt(na) * Math.sqrt(nb);\n return denom === 0 ? 0 : dot / denom;\n}\n\n/** Extract a flat Float32Array from the transformer pipeline output. */\nfunction toFloat32Array(data: unknown): Float32Array {\n if (data instanceof Float32Array) return data;\n if (Array.isArray(data)) return new Float32Array(data);\n if (data && typeof data === 'object' && 'length' in data) {\n return Float32Array.from(Array.from(data as ArrayLike<number>));\n }\n throw new Error('Unsupported embedding data format');\n}\n\n// \u2500\u2500 VectorManager \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport class VectorManager {\n private pipeline: Pipeline | null = null;\n private _initialized = false;\n private vecIndex: VecIndex | null = null;\n private oramaIndex: OramaIndex | null = null;\n private pgliteIndex: PGliteIndex | null = null;\n private lancedbIndex: LanceDBIndex | null = null;\n private qdrantIndex: QdrantIndex | null = null;\n private typesenseIndex: TypesenseIndex | null = null;\n private turboquantIndex: TurboQuantIndex | null = null;\n private turbovecIndex: TurboVecIndex | null = null;\n private _engineFallback: string | null = null;\n\n constructor(\n private readonly db: GraphDatabase,\n private readonly config: KiroGraphConfig,\n private readonly projectRoot?: string,\n ) {}\n\n isInitialized(): boolean {\n return this.config.enableEmbeddings === true && this._initialized;\n }\n\n /** Non-null when the configured engine failed to load and cosine is being used instead. */\n getEngineFallback(): string | null {\n return this._engineFallback;\n }\n\n /**\n * Load the embedding model. No-op when embeddings are disabled.\n * Fails silently so callers can continue without semantic search.\n * When config.useVecIndex is true, also initializes the sqlite-vec ANN index.\n */\n async initialize(onProgress?: (file: string, loaded: number, total: number, done: boolean) => void): Promise<void> {\n if (!this.config.enableEmbeddings) {\n logDebug('VectorManager: embeddings disabled');\n return;\n }\n if (this._initialized) return;\n\n const rawModel = this.config.embeddingModel || DEFAULT_MODEL;\n // Guard against an invalid model ID (e.g. 'y' typed by mistake in the installer)\n const modelId = rawModel.includes('/') ? rawModel : DEFAULT_MODEL;\n if (rawModel !== modelId) {\n logWarn(`VectorManager: invalid embeddingModel \"${rawModel}\", using default instead`, { default: DEFAULT_MODEL });\n }\n const cacheDir = GLOBAL_MODELS_DIR;\n\n try {\n const { pipeline, env } = await getTransformers();\n env.cacheDir = cacheDir;\n\n if (!fs.existsSync(cacheDir)) {\n fs.mkdirSync(cacheDir, { recursive: true });\n }\n\n // Skip remote check if model already cached (HuggingFace uses '--' as path separator)\n // HuggingFace transformers v3 stores models as <org>/<model>/ (v2 used <org>--<model>)\n const cached = fs.existsSync(path.join(cacheDir, modelId));\n if (cached) env.allowRemoteModels = false;\n\n let lastFile = '';\n this.pipeline = await pipeline('feature-extraction', modelId, {\n dtype: 'auto',\n ...(!cached && onProgress ? {\n progress_callback: (p: { status: string; file?: string; loaded?: number; total?: number }) => {\n if (p.status === 'progress' && p.file) {\n lastFile = p.file;\n onProgress(p.file, p.loaded ?? 0, p.total ?? 0, false);\n } else if (p.status === 'done' && lastFile) {\n onProgress(lastFile, 1, 1, true);\n lastFile = '';\n }\n },\n } : {}),\n });\n\n // Validate embeddingDim against the model's actual output shape.\n // Run a single test embedding and compare dims[1] to config.embeddingDim.\n // If they differ, warn and update the runtime dim so downstream engines\n // are initialised with the correct size (config.json is not rewritten here).\n try {\n const testOut = await this.pipeline('test', { pooling: 'mean', normalize: true });\n const actualDim: number = testOut.dims?.[1] ?? (testOut.data?.length as number);\n const configuredDim = this.config.embeddingDim ?? DEFAULT_EMBEDDING_DIM;\n if (actualDim && actualDim !== configuredDim) {\n logWarn(\n `VectorManager: embeddingDim mismatch \u2014 config says ${configuredDim} but model outputs ${actualDim}. Using actual dim.`,\n { model: modelId, configuredDim, actualDim },\n );\n // Patch the runtime config so all engine constructors below use the correct dim\n (this.config as unknown as Record<string, unknown>).embeddingDim = actualDim;\n }\n } catch { /* test embedding failed \u2014 proceed with configured dim */ }\n\n this._initialized = true;\n logDebug('VectorManager: model loaded', { modelId, embeddingDim: this.config.embeddingDim ?? DEFAULT_EMBEDDING_DIM });\n } catch (err) {\n logError('VectorManager: failed to load embedding model', {\n model: modelId,\n error: String(err),\n });\n this._initialized = false;\n return;\n }\n\n // Initialize the selected search engine\n const engine = this.config.semanticEngine ?? (this.config.useVecIndex ? 'sqlite-vec' : 'cosine');\n\n if (this.projectRoot && engine !== 'cosine') {\n const kirographDir = path.join(this.projectRoot, '.kirograph');\n\n const embeddingDim = this.config.embeddingDim ?? DEFAULT_EMBEDDING_DIM;\n\n if (engine === 'sqlite-vec') {\n this.vecIndex = new VecIndex(kirographDir, embeddingDim);\n await this.vecIndex.initialize();\n if (this.vecIndex.isAvailable()) {\n logDebug('VectorManager: sqlite-vec ANN index ready');\n } else {\n this._engineFallback = 'sqlite-vec unavailable \u2014 run: npm install better-sqlite3 sqlite-vec';\n logDebug('VectorManager: sqlite-vec unavailable, falling back to in-process cosine');\n }\n } else if (engine === 'orama') {\n this.oramaIndex = new OramaIndex(kirographDir, embeddingDim);\n await this.oramaIndex.initialize();\n if (this.oramaIndex.isAvailable()) {\n logDebug('VectorManager: Orama hybrid index ready');\n } else {\n this._engineFallback = 'orama unavailable \u2014 run: npm install @orama/orama @orama/plugin-data-persistence';\n logDebug('VectorManager: Orama unavailable, falling back to in-process cosine');\n }\n } else if (engine === 'pglite') {\n this.pgliteIndex = new PGliteIndex(kirographDir, embeddingDim);\n await this.pgliteIndex.initialize();\n if (this.pgliteIndex.isAvailable()) {\n logDebug('VectorManager: PGlite+pgvector hybrid index ready');\n } else {\n this._engineFallback = 'pglite unavailable \u2014 run: npm install @electric-sql/pglite';\n logDebug('VectorManager: PGlite unavailable, falling back to in-process cosine');\n }\n } else if (engine === 'lancedb') {\n this.lancedbIndex = new LanceDBIndex(kirographDir, embeddingDim);\n await this.lancedbIndex.initialize();\n if (this.lancedbIndex.isAvailable()) {\n logDebug('VectorManager: LanceDB ANN index ready');\n } else {\n this._engineFallback = 'lancedb unavailable \u2014 run: npm install @lancedb/lancedb';\n logDebug('VectorManager: LanceDB unavailable, falling back to in-process cosine');\n }\n } else if (engine === 'qdrant') {\n this.qdrantIndex = new QdrantIndex(kirographDir, embeddingDim);\n await this.qdrantIndex.initialize();\n if (this.qdrantIndex.isAvailable()) {\n logDebug('VectorManager: Qdrant ANN index ready');\n } else {\n this._engineFallback = 'qdrant unavailable \u2014 run: npm install qdrant-local';\n logDebug('VectorManager: Qdrant unavailable, falling back to in-process cosine');\n }\n } else if (engine === 'typesense') {\n this.typesenseIndex = new TypesenseIndex(kirographDir, embeddingDim);\n await this.typesenseIndex.initialize();\n if (this.typesenseIndex.isAvailable()) {\n logDebug('VectorManager: Typesense ANN index ready');\n } else {\n const reason = this.typesenseIndex.getFailReason();\n this._engineFallback = reason\n ? `typesense initialization failed: ${reason}`\n : 'typesense unavailable \u2014 run: npm install typesense';\n logDebug('VectorManager: Typesense unavailable, falling back to in-process cosine');\n }\n } else if (engine === 'turboquant') {\n const bits = this.config.turboquantBits ?? 3;\n this.turboquantIndex = new TurboQuantIndex(kirographDir, 'turboquant.bin', embeddingDim, bits);\n await this.turboquantIndex.initialize();\n if (this.turboquantIndex.isAvailable()) {\n logDebug('VectorManager: TurboQuant ANN index ready', { bits });\n } else {\n this._engineFallback = 'turboquant unavailable \u2014 run: npm install turboquant-js';\n logDebug('VectorManager: TurboQuant unavailable, falling back to in-process cosine');\n }\n } else if (engine === 'turbovec') {\n const bits = this.config.turbovecBits ?? 4;\n this.turbovecIndex = new TurboVecIndex(kirographDir, 'turbovec.tvim', embeddingDim, bits);\n await this.turbovecIndex.initialize();\n if (this.turbovecIndex.isAvailable()) {\n logDebug('VectorManager: TurboVec ANN index ready', { bits });\n } else {\n this._engineFallback = 'turbovec unavailable \u2014 build it: cd native/turbovec-node && npm install && npm run build';\n logDebug('VectorManager: TurboVec unavailable, falling back to in-process cosine');\n }\n }\n }\n }\n\n /**\n * Embed a single node and persist to the vectors table.\n * Skips silently when disabled; logs on failure without throwing.\n */\n async embedNode(node: Node): Promise<void> {\n if (!this.config.enableEmbeddings) return;\n if (!this._initialized || !this.pipeline) {\n logError('Embedding model unavailable', { model: this.config.embeddingModel });\n return;\n }\n if (!EMBEDDABLE_KINDS.has(node.kind)) return;\n\n try {\n const text = `search_document: ${nodeToText(node)}`;\n const output = await this.pipeline(text, { pooling: 'mean', normalize: true });\n const embedding = toFloat32Array(output.data);\n // non-cosine engines are sole stores of record when active \u2014 skip the SQLite vectors table\n if (!this.vecIndex?.isAvailable() && !this.oramaIndex?.isAvailable() && !this.pgliteIndex?.isAvailable() && !this.lancedbIndex?.isAvailable() && !this.qdrantIndex?.isAvailable() && !this.typesenseIndex?.isAvailable() && !this.turboquantIndex?.isAvailable() && !this.turbovecIndex?.isAvailable()) {\n this.db.storeEmbedding(node.id, embedding, this.config.embeddingModel || DEFAULT_MODEL);\n }\n this.vecIndex?.upsert(node.id, embedding);\n if (this.oramaIndex?.isAvailable()) await this.oramaIndex.upsert(node, embedding);\n if (this.pgliteIndex?.isAvailable()) await this.pgliteIndex.upsert(node, embedding);\n if (this.lancedbIndex?.isAvailable()) await this.lancedbIndex.upsert(node, embedding);\n if (this.qdrantIndex?.isAvailable()) await this.qdrantIndex.upsert(node, embedding);\n if (this.typesenseIndex?.isAvailable()) await this.typesenseIndex.upsert(node, embedding);\n this.turboquantIndex?.upsert(node.id, embedding);\n this.turbovecIndex?.upsert(node.id, embedding);\n } catch (err) {\n logWarn('Failed to embed node', { nodeId: node.id, error: String(err) });\n }\n }\n\n /** Number of entries currently in the active ANN/hybrid index (0 when not in use). */\n async vecIndexCount(): Promise<number> {\n if (this.turbovecIndex?.isAvailable()) return this.turbovecIndex.count();\n if (this.turboquantIndex?.isAvailable()) return this.turboquantIndex.count();\n if (this.vecIndex?.isAvailable()) return this.vecIndex.count();\n if (this.oramaIndex?.isAvailable()) return this.oramaIndex.count();\n if (this.pgliteIndex?.isAvailable()) return this.pgliteIndex.count();\n if (this.lancedbIndex?.isAvailable()) return this.lancedbIndex.count();\n if (this.qdrantIndex?.isAvailable()) return this.qdrantIndex.count();\n if (this.typesenseIndex?.isAvailable()) return this.typesenseIndex.count();\n return 0;\n }\n\n /**\n * Remove embeddings for the given node IDs from the active index.\n * For cosine the `vectors` SQLite table is cleaned up automatically via FK cascade\n * when nodes are deleted. For sqlite-vec, orama, and pglite the engine itself is\n * the sole store of record, so we delete from it explicitly here.\n */\n async deleteEmbeddings(nodeIds: string[]): Promise<void> {\n for (const id of nodeIds) {\n this.vecIndex?.delete(id);\n if (this.oramaIndex?.isAvailable()) await this.oramaIndex.delete(id);\n if (this.pgliteIndex?.isAvailable()) await this.pgliteIndex.delete(id);\n if (this.lancedbIndex?.isAvailable()) await this.lancedbIndex.delete(id);\n if (this.qdrantIndex?.isAvailable()) await this.qdrantIndex.delete(id);\n if (this.typesenseIndex?.isAvailable()) await this.typesenseIndex.delete(id);\n this.turboquantIndex?.delete(id);\n this.turbovecIndex?.delete(id);\n }\n }\n\n /**\n * Embed all eligible nodes in the database that don't yet have embeddings.\n * Streams nodes in pages to avoid loading the entire node set into memory \u2014\n * critical for large codebases (100K+ symbols) where a single getAllNodes()\n * call can exhaust the Node.js heap or the WASM linear memory.\n *\n * Uses dynamic batch sizing: starts at BATCH_SIZE, halves on OOM errors,\n * and recovers back to full size after successful batches.\n *\n * Emits a pre-flight warning via onProgress when the embeddable node count\n * exceeds LARGE_CODEBASE_THRESHOLD so the CLI can surface it to the user.\n */\n async embedAll(onProgress?: (current: number, total: number) => void): Promise<number> {\n if (!this.isInitialized() || !this.pipeline) return 0;\n\n const modelId = this.config.embeddingModel || DEFAULT_MODEL;\n const EMBEDDABLE_KINDS_ARRAY = [...EMBEDDABLE_KINDS] as string[];\n\n // Pre-flight: count embeddable nodes without loading them\n const totalEmbeddable = this.db.countEmbeddableNodes(EMBEDDABLE_KINDS_ARRAY);\n const LARGE_CODEBASE_THRESHOLD = 100_000;\n if (totalEmbeddable > LARGE_CODEBASE_THRESHOLD) {\n // Signal the large-codebase warning via a special progress event.\n // current=-1 is the sentinel; the CLI renderer checks for it.\n onProgress?.(-1, totalEmbeddable);\n }\n\n // Collect already-embedded IDs (needed to skip nodes already in the index)\n const existingIds = new Set(\n this.typesenseIndex?.isAvailable()\n ? await this.typesenseIndex.getEmbeddedNodeIds()\n : this.qdrantIndex?.isAvailable()\n ? await this.qdrantIndex.getEmbeddedNodeIds()\n : this.lancedbIndex?.isAvailable()\n ? await this.lancedbIndex.getEmbeddedNodeIds()\n : this.pgliteIndex?.isAvailable()\n ? await this.pgliteIndex.getEmbeddedNodeIds()\n : this.oramaIndex?.isAvailable()\n ? await this.oramaIndex.getEmbeddedNodeIds()\n : this.turbovecIndex?.isAvailable()\n ? this.turbovecIndex.getEmbeddedIds()\n : this.turboquantIndex?.isAvailable()\n ? this.turboquantIndex.getEmbeddedIds()\n : this.vecIndex?.isAvailable()\n ? this.vecIndex.getEmbeddedNodeIds()\n : this.db.getEmbeddedNodeIds()\n );\n\n // Stream nodes in pages \u2014 never hold more than PAGE_SIZE nodes in memory at once\n const PAGE_SIZE = 2000;\n let pageOffset = 0;\n let processed = 0;\n let currentBatchSize = BATCH_SIZE;\n let consecutiveSuccesses = 0;\n\n // We need to know the total pending count for progress reporting.\n // Approximate: totalEmbeddable - existingIds.size (may be slightly off if\n // existingIds contains IDs for non-embeddable kinds, but close enough).\n const totalPending = Math.max(0, totalEmbeddable - existingIds.size);\n if (totalPending === 0) {\n if (this.oramaIndex?.isAvailable()) await this.oramaIndex.save();\n return 0;\n }\n\n logDebug(`VectorManager: embedding ~${totalPending} nodes (${existingIds.size} already embedded, streaming in pages of ${PAGE_SIZE})`);\n\n // Buffer of pending nodes from the current page\n let pageBuffer: Node[] = [];\n let pageBufferOffset = 0; // index within pageBuffer\n let pageExhausted = false;\n\n const fetchNextPage = () => {\n const page = this.db.getEmbeddableNodesPaged(EMBEDDABLE_KINDS_ARRAY, PAGE_SIZE, pageOffset);\n pageOffset += page.length;\n pageBuffer = page.filter(n => !existingIds.has(n.id));\n pageBufferOffset = 0;\n if (page.length < PAGE_SIZE) pageExhausted = true;\n };\n\n fetchNextPage();\n\n while (pageBuffer.length > 0 || (!pageExhausted && pageBufferOffset >= pageBuffer.length)) {\n // Refill page buffer when exhausted\n if (pageBufferOffset >= pageBuffer.length) {\n if (pageExhausted) break;\n fetchNextPage();\n if (pageBuffer.length === 0) break;\n }\n\n // Slice a batch from the current page buffer\n const batch = pageBuffer.slice(pageBufferOffset, pageBufferOffset + currentBatchSize);\n if (batch.length === 0) break;\n\n const texts = batch.map(n => `search_document: ${nodeToText(n)}`);\n\n try {\n const outputs = await this.pipeline(texts, { pooling: 'mean', normalize: true });\n const dims: number[] = outputs.dims;\n const dim = dims[1] ?? (this.config.embeddingDim ?? DEFAULT_EMBEDDING_DIM);\n const flat = toFloat32Array(outputs.data);\n\n const tsNodes: Node[] = [];\n const tsEmbeddings: Float32Array[] = [];\n const qdNodes: Node[] = [];\n const qdEmbeddings: Float32Array[] = [];\n\n for (let j = 0; j < batch.length; j++) {\n const node = batch[j]!;\n const embedding = flat.slice(j * dim, (j + 1) * dim);\n if (!this.vecIndex?.isAvailable() && !this.oramaIndex?.isAvailable() && !this.pgliteIndex?.isAvailable() && !this.lancedbIndex?.isAvailable() && !this.qdrantIndex?.isAvailable() && !this.typesenseIndex?.isAvailable() && !this.turboquantIndex?.isAvailable() && !this.turbovecIndex?.isAvailable()) {\n this.db.storeEmbedding(node.id, embedding, modelId);\n }\n this.vecIndex?.upsert(node.id, embedding);\n if (this.oramaIndex?.isAvailable()) await this.oramaIndex.upsert(node, embedding);\n if (this.pgliteIndex?.isAvailable()) await this.pgliteIndex.upsert(node, embedding);\n if (this.lancedbIndex?.isAvailable()) await this.lancedbIndex.upsert(node, embedding);\n if (this.qdrantIndex?.isAvailable()) { qdNodes.push(node); qdEmbeddings.push(embedding); }\n if (this.typesenseIndex?.isAvailable()) { tsNodes.push(node); tsEmbeddings.push(embedding); }\n this.turboquantIndex?.upsert(node.id, embedding);\n this.turbovecIndex?.upsert(node.id, embedding);\n }\n\n if (qdNodes.length > 0) await this.qdrantIndex!.bulkUpsert(qdNodes, qdEmbeddings);\n if (tsNodes.length > 0) await this.typesenseIndex!.bulkUpsert(tsNodes, tsEmbeddings);\n\n pageBufferOffset += batch.length;\n processed += batch.length;\n consecutiveSuccesses++;\n\n if (currentBatchSize < BATCH_SIZE && consecutiveSuccesses >= 5) {\n currentBatchSize = Math.min(currentBatchSize * 2, BATCH_SIZE);\n logDebug(`VectorManager: batch size recovered to ${currentBatchSize}`);\n consecutiveSuccesses = 0;\n }\n } catch (err) {\n const errMsg = String(err);\n const isOOM = errMsg.includes('bad allocation') || errMsg.includes('OOM') || errMsg.includes('out of memory');\n\n if (isOOM && currentBatchSize > MIN_BATCH_SIZE) {\n currentBatchSize = Math.max(Math.floor(currentBatchSize / 2), MIN_BATCH_SIZE);\n consecutiveSuccesses = 0;\n logWarn(`VectorManager: OOM at batch offset ${pageBufferOffset} \u2014 reducing batch size to ${currentBatchSize} and retrying`, {\n batchSize: currentBatchSize,\n nodeIds: batch.slice(0, 3).map(n => n.id),\n });\n // Don't advance pageBufferOffset \u2014 retry the same batch\n } else if (isOOM && currentBatchSize <= MIN_BATCH_SIZE) {\n logError(`VectorManager: OOM even at minimum batch size ${MIN_BATCH_SIZE} \u2014 skipping ${batch.length} nodes`, {\n batchStart: pageBufferOffset,\n skippedNodes: batch.map(n => `${n.kind}:${n.name} (${n.filePath})`).slice(0, 5),\n });\n pageBufferOffset += batch.length;\n processed += batch.length;\n consecutiveSuccesses = 0;\n } else {\n logWarn(`VectorManager: batch embedding failed at offset ${pageBufferOffset}`, {\n batchSize: currentBatchSize,\n error: errMsg,\n });\n pageBufferOffset += batch.length;\n processed += batch.length;\n consecutiveSuccesses = 0;\n }\n }\n\n onProgress?.(processed, totalPending);\n }\n\n if (this.oramaIndex?.isAvailable()) await this.oramaIndex.save();\n\n if (this.turboquantIndex?.isAvailable()) {\n await this.turboquantIndex.save();\n if (this.projectRoot) {\n const kirographDir = path.join(this.projectRoot, '.kirograph');\n const stats = this.turboquantIndex.memoryStats();\n const count = this.turboquantIndex.count();\n const dim = this.config.embeddingDim ?? DEFAULT_EMBEDDING_DIM;\n const rawBytes = count * dim * 4;\n writeTurboQuantStats(kirographDir, {\n count,\n dim,\n bits: this.config.turboquantBits ?? 3,\n compressionRatio: stats.compressionRatio,\n actualBytes: stats.actualBytes,\n rawBytes,\n savedBytes: rawBytes - stats.actualBytes,\n });\n }\n }\n\n if (this.turbovecIndex?.isAvailable()) {\n await this.turbovecIndex.save();\n logDebug('VectorManager: TurboVec index saved', {\n count: this.turbovecIndex.count(),\n bits: this.config.turbovecBits ?? 4,\n });\n }\n\n logDebug(`VectorManager: embedding complete \u2014 ${processed} processed, final batch size: ${currentBatchSize}`);\n\n return processed;\n }\n\n /**\n * Semantic search: embed the query and return top-N nodes by similarity.\n *\n * When sqlite-vec is available (useVecIndex: true), delegates ANN search to\n * VecIndex (fast, sub-linear). Otherwise falls back to in-process cosine\n * similarity over all stored embeddings (linear scan, no extra deps).\n *\n * Returns empty array when not initialized.\n */\n async search(query: string, topN = 10): Promise<Node[]> {\n if (!this.isInitialized() || !this.pipeline) return [];\n\n try {\n const text = `search_query: ${query}`;\n const output = await this.pipeline(text, { pooling: 'mean', normalize: true });\n const queryVec = toFloat32Array(output.data);\n\n let nodeIds: string[];\n\n if (this.pgliteIndex?.isAvailable()) {\n // Hybrid search via PGlite+pgvector \u2014 exact vector + full-text in one SQL query\n nodeIds = await this.pgliteIndex.search(query, queryVec, topN);\n } else if (this.oramaIndex?.isAvailable()) {\n // Hybrid search via Orama \u2014 full-text + vector combined\n nodeIds = await this.oramaIndex.search(query, queryVec, topN);\n } else if (this.lancedbIndex?.isAvailable()) {\n // ANN search via LanceDB \u2014 columnar Lance format, cosine metric\n nodeIds = await this.lancedbIndex.search(queryVec, topN);\n } else if (this.qdrantIndex?.isAvailable()) {\n // ANN search via Qdrant \u2014 HNSW index, cosine metric\n nodeIds = await this.qdrantIndex.search(queryVec, topN);\n } else if (this.typesenseIndex?.isAvailable()) {\n // ANN search via Typesense \u2014 HNSW index, cosine metric\n nodeIds = await this.typesenseIndex.search(queryVec, topN);\n } else if (this.turbovecIndex?.isAvailable()) {\n // ANN search via TurboVec \u2014 Rust/SIMD NEON+AVX-512 quantized index\n nodeIds = this.turbovecIndex.search(queryVec, topN);\n } else if (this.turboquantIndex?.isAvailable()) {\n // ANN search via TurboQuant \u2014 compressed in-memory index, zero native deps\n nodeIds = this.turboquantIndex.search(queryVec, topN);\n } else if (this.vecIndex?.isAvailable()) {\n // ANN search via sqlite-vec \u2014 fast, sub-linear\n nodeIds = this.vecIndex.search(queryVec, topN);\n } else {\n // In-process cosine similarity \u2014 linear scan over all stored embeddings\n const allEmbeddings = this.db.getAllEmbeddings();\n nodeIds = allEmbeddings\n .map(({ nodeId, embedding }) => ({ nodeId, score: cosine(queryVec, embedding) }))\n .filter(r => r.score >= 0.3)\n .sort((a, b) => b.score - a.score)\n .slice(0, topN)\n .map(r => r.nodeId);\n }\n\n const results: Node[] = [];\n for (const nodeId of nodeIds) {\n const node = this.db.getNode(nodeId);\n if (node) results.push(node);\n }\n return results;\n } catch (err) {\n logWarn('VectorManager: search failed', { error: String(err) });\n return [];\n }\n }\n\n /** Release engine resources (e.g. kill Qdrant child process). */\n close(): void {\n this.qdrantIndex?.close();\n this.typesenseIndex?.close();\n this.turbovecIndex?.close();\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var turbovec_index_exports = {};
|
|
30
|
+
__export(turbovec_index_exports, {
|
|
31
|
+
TurboVecIndex: () => TurboVecIndex
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(turbovec_index_exports);
|
|
34
|
+
var path = __toESM(require("path"));
|
|
35
|
+
var fs = __toESM(require("fs"));
|
|
36
|
+
var import_errors = require("../errors");
|
|
37
|
+
class TurboVecIndex {
|
|
38
|
+
constructor(kirographDir, binName, dim, bits = 4) {
|
|
39
|
+
this.kirographDir = kirographDir;
|
|
40
|
+
this.binName = binName;
|
|
41
|
+
this.dim = dim;
|
|
42
|
+
this.bits = bits;
|
|
43
|
+
this.index = null;
|
|
44
|
+
this._available = false;
|
|
45
|
+
}
|
|
46
|
+
isAvailable() {
|
|
47
|
+
return this._available;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Load the native addon and restore the index from disk if the bin file
|
|
51
|
+
* exists. Silent no-op when the addon is not built.
|
|
52
|
+
*/
|
|
53
|
+
async initialize() {
|
|
54
|
+
if (this._available) return;
|
|
55
|
+
let TVModule;
|
|
56
|
+
try {
|
|
57
|
+
TVModule = require("turbovec-node");
|
|
58
|
+
} catch {
|
|
59
|
+
(0, import_errors.logDebug)("TurboVecIndex: turbovec-node not found \u2014 run: cd native/turbovec-node && npm install && npm run build");
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const TurboVecIndexClass = TVModule?.TurboVecIndex ?? TVModule?.default?.TurboVecIndex ?? null;
|
|
63
|
+
if (!TurboVecIndexClass || typeof TurboVecIndexClass !== "function") {
|
|
64
|
+
(0, import_errors.logWarn)("TurboVecIndex: unrecognised turbovec-node module shape \u2014 turbovec engine unavailable");
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
if (this.dim <= 0 || this.dim % 8 !== 0) {
|
|
68
|
+
(0, import_errors.logWarn)("TurboVecIndex: dim must be a positive multiple of 8", { dim: this.dim });
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const binPath = path.join(this.kirographDir, this.binName);
|
|
72
|
+
try {
|
|
73
|
+
if (fs.existsSync(binPath) && typeof TurboVecIndexClass.load === "function") {
|
|
74
|
+
this.index = TurboVecIndexClass.load(binPath);
|
|
75
|
+
(0, import_errors.logDebug)("TurboVecIndex: restored from disk", { binPath });
|
|
76
|
+
} else {
|
|
77
|
+
this.index = new TurboVecIndexClass(this.dim, this.bits);
|
|
78
|
+
(0, import_errors.logDebug)("TurboVecIndex: new index", { dim: this.dim, bits: this.bits });
|
|
79
|
+
}
|
|
80
|
+
this._available = true;
|
|
81
|
+
} catch (err) {
|
|
82
|
+
(0, import_errors.logError)("TurboVecIndex: initialization failed", { error: String(err) });
|
|
83
|
+
this._available = false;
|
|
84
|
+
this.index = null;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/** Insert or update a vector. */
|
|
88
|
+
upsert(id, vec) {
|
|
89
|
+
if (!this._available || !this.index) return;
|
|
90
|
+
try {
|
|
91
|
+
this.index.add(id, vec);
|
|
92
|
+
} catch (err) {
|
|
93
|
+
(0, import_errors.logWarn)("TurboVecIndex: upsert failed", { id, error: String(err) });
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/** Remove a vector from the index. */
|
|
97
|
+
delete(id) {
|
|
98
|
+
if (!this._available || !this.index) return;
|
|
99
|
+
try {
|
|
100
|
+
this.index.remove(id);
|
|
101
|
+
} catch (err) {
|
|
102
|
+
(0, import_errors.logWarn)("TurboVecIndex: delete failed", { id, error: String(err) });
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/** ANN search — returns IDs sorted by descending similarity. */
|
|
106
|
+
search(queryVec, topN = 10) {
|
|
107
|
+
return this.searchWithScores(queryVec, topN).map((r) => r.id);
|
|
108
|
+
}
|
|
109
|
+
/** ANN search — returns [{id, score}] sorted by descending similarity. */
|
|
110
|
+
searchWithScores(queryVec, topN = 10) {
|
|
111
|
+
if (!this._available || !this.index) return [];
|
|
112
|
+
try {
|
|
113
|
+
const results = this.index.search(queryVec, topN);
|
|
114
|
+
return results.slice(0, topN);
|
|
115
|
+
} catch (err) {
|
|
116
|
+
(0, import_errors.logWarn)("TurboVecIndex: search failed", { error: String(err) });
|
|
117
|
+
return [];
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Persist the index to disk atomically.
|
|
122
|
+
* Saves `<binName>` (turbovec binary) and `<binName>.ids` (JSON string-ID sidecar).
|
|
123
|
+
*/
|
|
124
|
+
async save() {
|
|
125
|
+
if (!this._available || !this.index) return;
|
|
126
|
+
const binPath = path.join(this.kirographDir, this.binName);
|
|
127
|
+
const tmpBin = binPath + ".tmp";
|
|
128
|
+
try {
|
|
129
|
+
this.index.save(tmpBin);
|
|
130
|
+
if (fs.existsSync(tmpBin)) {
|
|
131
|
+
fs.renameSync(tmpBin, binPath);
|
|
132
|
+
}
|
|
133
|
+
const tmpIds = tmpBin + ".ids";
|
|
134
|
+
if (fs.existsSync(tmpIds)) {
|
|
135
|
+
fs.renameSync(tmpIds, binPath + ".ids");
|
|
136
|
+
}
|
|
137
|
+
(0, import_errors.logDebug)("TurboVecIndex: saved", { binPath });
|
|
138
|
+
} catch (err) {
|
|
139
|
+
(0, import_errors.logWarn)("TurboVecIndex: save failed", { error: String(err) });
|
|
140
|
+
for (const f of [tmpBin, tmpBin + ".ids"]) {
|
|
141
|
+
try {
|
|
142
|
+
fs.unlinkSync(f);
|
|
143
|
+
} catch {
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/** Compression stats (formula-based, mirrors turboquant-index.ts). */
|
|
149
|
+
memoryStats() {
|
|
150
|
+
const n = this.count();
|
|
151
|
+
const rawBytes = n * this.dim * 4;
|
|
152
|
+
const actualBytes = Math.ceil(n * this.dim * this.bits / 8);
|
|
153
|
+
return {
|
|
154
|
+
totalBits: actualBytes * 8,
|
|
155
|
+
bitsPerVector: this.bits * this.dim,
|
|
156
|
+
compressionRatio: actualBytes > 0 ? rawBytes / actualBytes : 1,
|
|
157
|
+
actualBytes
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
count() {
|
|
161
|
+
if (!this._available || !this.index) return 0;
|
|
162
|
+
try {
|
|
163
|
+
return typeof this.index.len === "function" ? this.index.len() : 0;
|
|
164
|
+
} catch {
|
|
165
|
+
return 0;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
getEmbeddedIds() {
|
|
169
|
+
if (!this._available || !this.index) return [];
|
|
170
|
+
try {
|
|
171
|
+
return typeof this.index.getIds === "function" ? this.index.getIds() : [];
|
|
172
|
+
} catch {
|
|
173
|
+
return [];
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
close() {
|
|
177
|
+
try {
|
|
178
|
+
this.index?.close();
|
|
179
|
+
} catch {
|
|
180
|
+
}
|
|
181
|
+
this.index = null;
|
|
182
|
+
this._available = false;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
186
|
+
0 && (module.exports = {
|
|
187
|
+
TurboVecIndex
|
|
188
|
+
});
|
|
189
|
+
//# sourceMappingURL=turbovec-index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/vectors/turbovec-index.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * KiroGraph TurboVec ANN Index\n *\n * Wraps turbovec-node (napi-rs bindings for RyanCodrai/turbovec) as a\n * drop-in ANN index. Uses the same TurboQuant algorithm as turboquant-js\n * but backed by a Rust/SIMD implementation \u2014 NEON on ARM, AVX-512BW on\n * x86 \u2014 and supports 2, 3, or 4 bits per coordinate.\n *\n * Build the native addon once before use:\n * cd native/turbovec-node && npm install && npm run build\n *\n * Requires: Rust toolchain (rustup), plus openblas on Linux.\n * On macOS the Accelerate framework is used automatically (no extra dep).\n *\n * Falls back silently to cosine if turbovec-node is not built/installed.\n *\n * dim constraint: must be a positive multiple of 8 (768 \u2713, 384 \u2713).\n * bit_width: 2 (highest compression), 3 (balanced), 4 (highest quality).\n *\n * Upstream: https://github.com/RyanCodrai/turbovec\n */\n\nimport * as path from 'path';\nimport * as fs from 'fs';\nimport { logDebug, logWarn, logError } from '../errors';\n\n// \u2500\u2500 TurboVecIndex \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport class TurboVecIndex {\n private index: any = null;\n private _available = false;\n\n constructor(\n private readonly kirographDir: string,\n private readonly binName: string,\n private readonly dim: number,\n private readonly bits: number = 4,\n ) {}\n\n isAvailable(): boolean {\n return this._available;\n }\n\n /**\n * Load the native addon and restore the index from disk if the bin file\n * exists. Silent no-op when the addon is not built.\n */\n async initialize(): Promise<void> {\n if (this._available) return;\n\n let TVModule: any;\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n TVModule = require('turbovec-node');\n } catch {\n logDebug('TurboVecIndex: turbovec-node not found \u2014 run: cd native/turbovec-node && npm install && npm run build');\n return;\n }\n\n const TurboVecIndexClass =\n TVModule?.TurboVecIndex ??\n TVModule?.default?.TurboVecIndex ??\n null;\n\n if (!TurboVecIndexClass || typeof TurboVecIndexClass !== 'function') {\n logWarn('TurboVecIndex: unrecognised turbovec-node module shape \u2014 turbovec engine unavailable');\n return;\n }\n\n // turbovec requires dim to be a positive multiple of 8\n if (this.dim <= 0 || this.dim % 8 !== 0) {\n logWarn('TurboVecIndex: dim must be a positive multiple of 8', { dim: this.dim });\n return;\n }\n\n const binPath = path.join(this.kirographDir, this.binName);\n\n try {\n if (fs.existsSync(binPath) && typeof TurboVecIndexClass.load === 'function') {\n this.index = TurboVecIndexClass.load(binPath);\n logDebug('TurboVecIndex: restored from disk', { binPath });\n } else {\n this.index = new TurboVecIndexClass(this.dim, this.bits);\n logDebug('TurboVecIndex: new index', { dim: this.dim, bits: this.bits });\n }\n this._available = true;\n } catch (err) {\n logError('TurboVecIndex: initialization failed', { error: String(err) });\n this._available = false;\n this.index = null;\n }\n }\n\n /** Insert or update a vector. */\n upsert(id: string, vec: Float32Array): void {\n if (!this._available || !this.index) return;\n try {\n this.index.add(id, vec);\n } catch (err) {\n logWarn('TurboVecIndex: upsert failed', { id, error: String(err) });\n }\n }\n\n /** Remove a vector from the index. */\n delete(id: string): void {\n if (!this._available || !this.index) return;\n try {\n this.index.remove(id);\n } catch (err) {\n logWarn('TurboVecIndex: delete failed', { id, error: String(err) });\n }\n }\n\n /** ANN search \u2014 returns IDs sorted by descending similarity. */\n search(queryVec: Float32Array, topN = 10): string[] {\n return this.searchWithScores(queryVec, topN).map(r => r.id);\n }\n\n /** ANN search \u2014 returns [{id, score}] sorted by descending similarity. */\n searchWithScores(queryVec: Float32Array, topN = 10): Array<{ id: string; score: number }> {\n if (!this._available || !this.index) return [];\n try {\n const results: Array<{ id: string; score: number }> = this.index.search(queryVec, topN);\n return results.slice(0, topN);\n } catch (err) {\n logWarn('TurboVecIndex: search failed', { error: String(err) });\n return [];\n }\n }\n\n /**\n * Persist the index to disk atomically.\n * Saves `<binName>` (turbovec binary) and `<binName>.ids` (JSON string-ID sidecar).\n */\n async save(): Promise<void> {\n if (!this._available || !this.index) return;\n\n const binPath = path.join(this.kirographDir, this.binName);\n const tmpBin = binPath + '.tmp';\n\n try {\n this.index.save(tmpBin);\n // Rust saves to `tmpBin` and `tmpBin + \".ids\"` \u2014 atomically rename both\n if (fs.existsSync(tmpBin)) {\n fs.renameSync(tmpBin, binPath);\n }\n const tmpIds = tmpBin + '.ids';\n if (fs.existsSync(tmpIds)) {\n fs.renameSync(tmpIds, binPath + '.ids');\n }\n logDebug('TurboVecIndex: saved', { binPath });\n } catch (err) {\n logWarn('TurboVecIndex: save failed', { error: String(err) });\n for (const f of [tmpBin, tmpBin + '.ids']) {\n try { fs.unlinkSync(f); } catch { /* ignore */ }\n }\n }\n }\n\n /** Compression stats (formula-based, mirrors turboquant-index.ts). */\n memoryStats(): { totalBits: number; bitsPerVector: number; compressionRatio: number; actualBytes: number } {\n const n = this.count();\n const rawBytes = n * this.dim * 4;\n const actualBytes = Math.ceil(n * this.dim * this.bits / 8);\n return {\n totalBits: actualBytes * 8,\n bitsPerVector: this.bits * this.dim,\n compressionRatio: actualBytes > 0 ? rawBytes / actualBytes : 1,\n actualBytes,\n };\n }\n\n count(): number {\n if (!this._available || !this.index) return 0;\n try {\n return typeof this.index.len === 'function' ? (this.index.len() as number) : 0;\n } catch { return 0; }\n }\n\n getEmbeddedIds(): string[] {\n if (!this._available || !this.index) return [];\n try {\n return typeof this.index.getIds === 'function' ? (this.index.getIds() as string[]) : [];\n } catch { return []; }\n }\n\n close(): void {\n try { this.index?.close(); } catch { /* ignore */ }\n this.index = null;\n this._available = false;\n }\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAsBA,WAAsB;AACtB,SAAoB;AACpB,oBAA4C;AAIrC,MAAM,cAAc;AAAA,EAIzB,YACmB,cACA,SACA,KACA,OAAe,GAChC;AAJiB;AACA;AACA;AACA;AAPnB,SAAQ,QAAa;AACrB,SAAQ,aAAa;AAAA,EAOlB;AAAA,EAEH,cAAuB;AACrB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,aAA4B;AAChC,QAAI,KAAK,WAAY;AAErB,QAAI;AACJ,QAAI;AAEF,iBAAW,QAAQ,eAAe;AAAA,IACpC,QAAQ;AACN,kCAAS,4GAAuG;AAChH;AAAA,IACF;AAEA,UAAM,qBACJ,UAAU,iBACV,UAAU,SAAS,iBACnB;AAEF,QAAI,CAAC,sBAAsB,OAAO,uBAAuB,YAAY;AACnE,iCAAQ,2FAAsF;AAC9F;AAAA,IACF;AAGA,QAAI,KAAK,OAAO,KAAK,KAAK,MAAM,MAAM,GAAG;AACvC,iCAAQ,uDAAuD,EAAE,KAAK,KAAK,IAAI,CAAC;AAChF;AAAA,IACF;AAEA,UAAM,UAAU,KAAK,KAAK,KAAK,cAAc,KAAK,OAAO;AAEzD,QAAI;AACF,UAAI,GAAG,WAAW,OAAO,KAAK,OAAO,mBAAmB,SAAS,YAAY;AAC3E,aAAK,QAAQ,mBAAmB,KAAK,OAAO;AAC5C,oCAAS,qCAAqC,EAAE,QAAQ,CAAC;AAAA,MAC3D,OAAO;AACL,aAAK,QAAQ,IAAI,mBAAmB,KAAK,KAAK,KAAK,IAAI;AACvD,oCAAS,4BAA4B,EAAE,KAAK,KAAK,KAAK,MAAM,KAAK,KAAK,CAAC;AAAA,MACzE;AACA,WAAK,aAAa;AAAA,IACpB,SAAS,KAAK;AACZ,kCAAS,wCAAwC,EAAE,OAAO,OAAO,GAAG,EAAE,CAAC;AACvE,WAAK,aAAa;AAClB,WAAK,QAAQ;AAAA,IACf;AAAA,EACF;AAAA;AAAA,EAGA,OAAO,IAAY,KAAyB;AAC1C,QAAI,CAAC,KAAK,cAAc,CAAC,KAAK,MAAO;AACrC,QAAI;AACF,WAAK,MAAM,IAAI,IAAI,GAAG;AAAA,IACxB,SAAS,KAAK;AACZ,iCAAQ,gCAAgC,EAAE,IAAI,OAAO,OAAO,GAAG,EAAE,CAAC;AAAA,IACpE;AAAA,EACF;AAAA;AAAA,EAGA,OAAO,IAAkB;AACvB,QAAI,CAAC,KAAK,cAAc,CAAC,KAAK,MAAO;AACrC,QAAI;AACF,WAAK,MAAM,OAAO,EAAE;AAAA,IACtB,SAAS,KAAK;AACZ,iCAAQ,gCAAgC,EAAE,IAAI,OAAO,OAAO,GAAG,EAAE,CAAC;AAAA,IACpE;AAAA,EACF;AAAA;AAAA,EAGA,OAAO,UAAwB,OAAO,IAAc;AAClD,WAAO,KAAK,iBAAiB,UAAU,IAAI,EAAE,IAAI,OAAK,EAAE,EAAE;AAAA,EAC5D;AAAA;AAAA,EAGA,iBAAiB,UAAwB,OAAO,IAA0C;AACxF,QAAI,CAAC,KAAK,cAAc,CAAC,KAAK,MAAO,QAAO,CAAC;AAC7C,QAAI;AACF,YAAM,UAAgD,KAAK,MAAM,OAAO,UAAU,IAAI;AACtF,aAAO,QAAQ,MAAM,GAAG,IAAI;AAAA,IAC9B,SAAS,KAAK;AACZ,iCAAQ,gCAAgC,EAAE,OAAO,OAAO,GAAG,EAAE,CAAC;AAC9D,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,OAAsB;AAC1B,QAAI,CAAC,KAAK,cAAc,CAAC,KAAK,MAAO;AAErC,UAAM,UAAU,KAAK,KAAK,KAAK,cAAc,KAAK,OAAO;AACzD,UAAM,SAAS,UAAU;AAEzB,QAAI;AACF,WAAK,MAAM,KAAK,MAAM;AAEtB,UAAI,GAAG,WAAW,MAAM,GAAG;AACzB,WAAG,WAAW,QAAQ,OAAO;AAAA,MAC/B;AACA,YAAM,SAAS,SAAS;AACxB,UAAI,GAAG,WAAW,MAAM,GAAG;AACzB,WAAG,WAAW,QAAQ,UAAU,MAAM;AAAA,MACxC;AACA,kCAAS,wBAAwB,EAAE,QAAQ,CAAC;AAAA,IAC9C,SAAS,KAAK;AACZ,iCAAQ,8BAA8B,EAAE,OAAO,OAAO,GAAG,EAAE,CAAC;AAC5D,iBAAW,KAAK,CAAC,QAAQ,SAAS,MAAM,GAAG;AACzC,YAAI;AAAE,aAAG,WAAW,CAAC;AAAA,QAAG,QAAQ;AAAA,QAAe;AAAA,MACjD;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,cAA2G;AACzG,UAAM,IAAI,KAAK,MAAM;AACrB,UAAM,WAAW,IAAI,KAAK,MAAM;AAChC,UAAM,cAAc,KAAK,KAAK,IAAI,KAAK,MAAM,KAAK,OAAO,CAAC;AAC1D,WAAO;AAAA,MACL,WAAW,cAAc;AAAA,MACzB,eAAe,KAAK,OAAO,KAAK;AAAA,MAChC,kBAAkB,cAAc,IAAI,WAAW,cAAc;AAAA,MAC7D;AAAA,IACF;AAAA,EACF;AAAA,EAEA,QAAgB;AACd,QAAI,CAAC,KAAK,cAAc,CAAC,KAAK,MAAO,QAAO;AAC5C,QAAI;AACF,aAAO,OAAO,KAAK,MAAM,QAAQ,aAAc,KAAK,MAAM,IAAI,IAAe;AAAA,IAC/E,QAAQ;AAAE,aAAO;AAAA,IAAG;AAAA,EACtB;AAAA,EAEA,iBAA2B;AACzB,QAAI,CAAC,KAAK,cAAc,CAAC,KAAK,MAAO,QAAO,CAAC;AAC7C,QAAI;AACF,aAAO,OAAO,KAAK,MAAM,WAAW,aAAc,KAAK,MAAM,OAAO,IAAiB,CAAC;AAAA,IACxF,QAAQ;AAAE,aAAO,CAAC;AAAA,IAAG;AAAA,EACvB;AAAA,EAEA,QAAc;AACZ,QAAI;AAAE,WAAK,OAAO,MAAM;AAAA,IAAG,QAAQ;AAAA,IAAe;AAClD,SAAK,QAAQ;AACb,SAAK,aAAa;AAAA,EACpB;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kirograph",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.22.0",
|
|
4
4
|
"description": "Semantic code knowledge graph for Kiro: fewer tool calls, instant symbol lookups, 100% local.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -21,6 +21,9 @@
|
|
|
21
21
|
"test:watchmen:skip-llm": "bash scripts/watchmen/test.sh --skip-llm",
|
|
22
22
|
"test:patterns": "bash scripts/patterns/test.sh",
|
|
23
23
|
"test:sec": "bash scripts/sec/test.sh",
|
|
24
|
+
"test:turboquant": "bash scripts/turboquant/test.sh",
|
|
25
|
+
"test:turbovec": "bash scripts/turbovec/test.sh",
|
|
26
|
+
"test:data": "bash scripts/data/test.sh",
|
|
24
27
|
"clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"",
|
|
25
28
|
"release": "./scripts/release.sh",
|
|
26
29
|
"docs": "npx serve docs"
|
|
@@ -64,6 +67,7 @@
|
|
|
64
67
|
"@ast-grep/lang-swift": "^0.0.8",
|
|
65
68
|
"@ast-grep/napi": "^0.43.0",
|
|
66
69
|
"@electric-sql/pglite": "^0.2.17",
|
|
70
|
+
"@firecrawl/pdf-inspector": "^1.9.5",
|
|
67
71
|
"@lancedb/lancedb": "^0.27.2",
|
|
68
72
|
"@orama/orama": "^3.1.18",
|
|
69
73
|
"@orama/plugin-data-persistence": "^3.1.18",
|
|
@@ -71,6 +75,8 @@
|
|
|
71
75
|
"better-sqlite3": "^11.10.0",
|
|
72
76
|
"qdrant-local": "^0.0.0-alpha.10",
|
|
73
77
|
"sqlite-vec": "^0.1.9",
|
|
78
|
+
"turboquant-js": "^0.2.0",
|
|
79
|
+
"turbovec-node": "file:native/turbovec-node",
|
|
74
80
|
"typesense": "^3.0.6"
|
|
75
81
|
},
|
|
76
82
|
"devDependencies": {
|