Skip to main content
Glama
vector-store.ts2.89 kB
/** * Vector Store * * LanceDB-based local vector database for document storage and search */ import * as lancedb from '@lancedb/lancedb'; import fs from 'fs'; import path from 'path'; import { VECTOR_STORE, EMBEDDING, SEARCH } from './constants.js'; import type { IVectorStore, VectorRecord, SearchResult, VectorStoreConfig } from './types.js'; export class VectorStore implements IVectorStore { private readonly dbPath: string; private readonly tableName: string; private readonly dimensions: number; private db: lancedb.Connection | null = null; constructor(config: VectorStoreConfig = {}, dimensions?: number) { this.dbPath = config.dataDir || path.join(process.cwd(), VECTOR_STORE.DEFAULT_DATA_DIR); this.tableName = config.tableName ?? VECTOR_STORE.TABLE_NAME; this.dimensions = dimensions ?? EMBEDDING.DIMENSIONS; } async init(): Promise<void> { if (this.db) return; // Create data directory if not exists const dir = path.dirname(this.dbPath); if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } this.db = await lancedb.connect(this.dbPath); const tables = await this.db.tableNames(); if (!tables.includes(this.tableName)) { // Create initial table with schema await this.db.createTable(this.tableName, [this.createInitRecord()]); } } private createInitRecord(): VectorRecord { return { id: VECTOR_STORE.INIT_RECORD_ID, vector: Array(this.dimensions).fill(0), text: '', title: '', url: '', }; } async save(records: VectorRecord[]): Promise<number> { if (!this.db) await this.init(); if (records.length === 0) return 0; const table = await this.db!.openTable(this.tableName); // Overwrite mode for simple sync await table.add(records, { mode: 'overwrite' }); return records.length; } async search(queryVector: number[], limit: number = SEARCH.DEFAULT_LIMIT): Promise<SearchResult[]> { if (!this.db) await this.init(); const table = await this.db!.openTable(this.tableName); const results = await table.vectorSearch(queryVector).limit(limit).toArray(); return results .filter((r: Record<string, unknown>) => r.id !== VECTOR_STORE.INIT_RECORD_ID) .map((r: Record<string, unknown>) => ({ id: r.id as string, text: r.text as string, title: r.title as string, url: r.url as string, score: r._distance as number | undefined, })); } async count(): Promise<number> { if (!this.db) await this.init(); const table = await this.db!.openTable(this.tableName); return await table.countRows(); } async clear(): Promise<void> { if (!this.db) await this.init(); const table = await this.db!.openTable(this.tableName); await table.add([this.createInitRecord()], { mode: 'overwrite' }); } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/huiseo/outline-wiki-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server