minimem 0.0.3 → 0.0.4
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/dist/chunk-ARZQHOJI.js +239 -0
- package/dist/chunk-ARZQHOJI.js.map +1 -0
- package/dist/chunk-GVWPZRF7.js +260 -0
- package/dist/chunk-GVWPZRF7.js.map +1 -0
- package/dist/cli/index.js +1411 -612
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +375 -109
- package/dist/index.js +1330 -370
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +65 -0
- package/dist/internal.js +33 -0
- package/dist/internal.js.map +1 -0
- package/dist/session.d.ts +96 -0
- package/dist/session.js +15 -0
- package/dist/session.js.map +1 -0
- package/package.json +10 -2
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/minimem.ts","../src/internal.ts","../src/search/hybrid.ts","../src/search/search.ts","../src/db/schema.ts","../src/db/sqlite-vec.ts","../src/embeddings/embeddings.ts","../src/embeddings/batch-openai.ts","../src/embeddings/batch-gemini.ts","../src/server/tools.ts","../src/server/mcp.ts","../src/session.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { DatabaseSync } from \"node:sqlite\";\nimport chokidar, { type FSWatcher } from \"chokidar\";\n\nimport {\n buildFileEntry,\n chunkMarkdown,\n ensureDir,\n hashText,\n listMemoryFiles,\n type MemoryChunk,\n type MemoryFileEntry,\n parseEmbedding,\n} from \"./internal.js\";\nimport { bm25RankToScore, buildFtsQuery, mergeHybridResults } from \"./search/hybrid.js\";\nimport { searchKeyword, searchVector } from \"./search/search.js\";\nimport { ensureMemoryIndexSchema } from \"./db/schema.js\";\nimport { loadSqliteVecExtension } from \"./db/sqlite-vec.js\";\nimport {\n createEmbeddingProvider,\n type EmbeddingProvider,\n type EmbeddingProviderOptions,\n type OpenAiEmbeddingClient,\n type GeminiEmbeddingClient,\n} from \"./embeddings/embeddings.js\";\nimport { runOpenAiEmbeddingBatches, type OpenAiBatchRequest, OPENAI_BATCH_ENDPOINT } from \"./embeddings/batch-openai.js\";\nimport { runGeminiEmbeddingBatches, type GeminiBatchRequest } from \"./embeddings/batch-gemini.js\";\n\nconst META_KEY = \"memory_index_meta_v1\";\nconst SNIPPET_MAX_CHARS = 700;\nconst VECTOR_TABLE = \"chunks_vec\";\nconst FTS_TABLE = \"chunks_fts\";\nconst EMBEDDING_CACHE_TABLE = \"embedding_cache\";\nconst EMBEDDING_BATCH_MAX_TOKENS = 8000;\nconst EMBEDDING_APPROX_CHARS_PER_TOKEN = 1;\nconst EMBEDDING_INDEX_CONCURRENCY = 4;\nconst EMBEDDING_RETRY_MAX_ATTEMPTS = 3;\nconst EMBEDDING_RETRY_BASE_DELAY_MS = 500;\nconst EMBEDDING_RETRY_MAX_DELAY_MS = 8000;\nconst VECTOR_LOAD_TIMEOUT_MS = 30_000;\nconst EMBEDDING_QUERY_TIMEOUT_REMOTE_MS = 60_000;\nconst EMBEDDING_QUERY_TIMEOUT_LOCAL_MS = 5 * 60_000;\n\nconst vectorToBlob = (embedding: number[]): Buffer =>\n Buffer.from(new Float32Array(embedding).buffer);\n\nexport type MinimemConfig = {\n /** Directory containing memory files (MEMORY.md, memory/*.md) */\n memoryDir: string;\n /** Path to SQLite database. Defaults to memoryDir/.minimem/index.db */\n dbPath?: string;\n /** Embedding provider options */\n embedding: EmbeddingProviderOptions;\n /** Chunking configuration */\n chunking?: {\n /** Tokens per chunk (default: 256) */\n tokens?: number;\n /** Overlap tokens between chunks (default: 32) */\n overlap?: number;\n };\n /** Embedding cache configuration */\n cache?: {\n /** Enable embedding cache (default: true) */\n enabled?: boolean;\n /** Max cache entries before LRU pruning (default: 10000) */\n maxEntries?: number;\n };\n /** Hybrid search configuration */\n hybrid?: {\n /** Enable hybrid search (default: true) */\n enabled?: boolean;\n /** Weight for vector search (default: 0.7) */\n vectorWeight?: number;\n /** Weight for keyword search (default: 0.3) */\n textWeight?: number;\n /** Candidate multiplier for search (default: 2.0) */\n candidateMultiplier?: number;\n };\n /** Query configuration */\n query?: {\n /** Max results (default: 10) */\n maxResults?: number;\n /** Min score threshold (default: 0.3) */\n minScore?: number;\n };\n /** File watching configuration */\n watch?: {\n /** Enable file watching (default: true) */\n enabled?: boolean;\n /** Debounce delay in ms (default: 1000) */\n debounceMs?: number;\n };\n /** Batch embedding configuration */\n batch?: {\n /** Enable batch embedding API (default: false) */\n enabled?: boolean;\n /** Wait for batch completion (default: true) */\n wait?: boolean;\n /** Concurrent batch requests (default: 2) */\n concurrency?: number;\n /** Poll interval in ms (default: 2000) */\n pollIntervalMs?: number;\n /** Timeout in ms (default: 60 minutes) */\n timeoutMs?: number;\n };\n /** sqlite-vec extension path (optional) */\n vectorExtensionPath?: string;\n /** Debug logging function */\n debug?: (message: string, data?: Record<string, unknown>) => void;\n};\n\nexport type MinimemSearchResult = {\n path: string;\n startLine: number;\n endLine: number;\n score: number;\n snippet: string;\n};\n\ntype MemoryIndexMeta = {\n model: string;\n provider: string;\n providerKey?: string;\n chunkTokens: number;\n chunkOverlap: number;\n vectorDims?: number;\n};\n\nexport class Minimem {\n private readonly memoryDir: string;\n private readonly dbPath: string;\n private readonly chunking: { tokens: number; overlap: number };\n private readonly cache: { enabled: boolean; maxEntries: number };\n private readonly hybrid: {\n enabled: boolean;\n vectorWeight: number;\n textWeight: number;\n candidateMultiplier: number;\n };\n private readonly queryConfig: { maxResults: number; minScore: number };\n private readonly watchConfig: { enabled: boolean; debounceMs: number };\n private readonly batchConfig: {\n enabled: boolean;\n wait: boolean;\n concurrency: number;\n pollIntervalMs: number;\n timeoutMs: number;\n };\n private readonly vectorExtensionPath?: string;\n private readonly debug?: (message: string, data?: Record<string, unknown>) => void;\n\n private provider!: EmbeddingProvider;\n private openAi?: OpenAiEmbeddingClient;\n private gemini?: GeminiEmbeddingClient;\n private providerKey: string = \"\";\n private providerFallbackReason?: string;\n private db!: DatabaseSync;\n\n private readonly vector: {\n enabled: boolean;\n available: boolean | null;\n extensionPath?: string;\n loadError?: string;\n dims?: number;\n };\n private readonly fts: {\n enabled: boolean;\n available: boolean;\n loadError?: string;\n };\n\n private vectorReady: Promise<boolean> | null = null;\n private watcher: FSWatcher | null = null;\n private watchTimer: NodeJS.Timeout | null = null;\n private closed = false;\n private dirty = true;\n private syncing: Promise<void> | null = null;\n private embeddingOptions: EmbeddingProviderOptions;\n\n private constructor(config: MinimemConfig) {\n this.memoryDir = path.resolve(config.memoryDir);\n this.dbPath = config.dbPath ?? path.join(this.memoryDir, \".minimem\", \"index.db\");\n this.chunking = {\n tokens: config.chunking?.tokens ?? 256,\n overlap: config.chunking?.overlap ?? 32,\n };\n this.cache = {\n enabled: config.cache?.enabled ?? true,\n maxEntries: config.cache?.maxEntries ?? 10000,\n };\n this.hybrid = {\n enabled: config.hybrid?.enabled ?? true,\n vectorWeight: config.hybrid?.vectorWeight ?? 0.7,\n textWeight: config.hybrid?.textWeight ?? 0.3,\n candidateMultiplier: config.hybrid?.candidateMultiplier ?? 2.0,\n };\n this.queryConfig = {\n maxResults: config.query?.maxResults ?? 10,\n minScore: config.query?.minScore ?? 0.3,\n };\n this.watchConfig = {\n enabled: config.watch?.enabled ?? true,\n debounceMs: config.watch?.debounceMs ?? 1000,\n };\n this.batchConfig = {\n enabled: config.batch?.enabled ?? false,\n wait: config.batch?.wait ?? true,\n concurrency: config.batch?.concurrency ?? 2,\n pollIntervalMs: config.batch?.pollIntervalMs ?? 2000,\n timeoutMs: config.batch?.timeoutMs ?? 60 * 60 * 1000,\n };\n this.vectorExtensionPath = config.vectorExtensionPath;\n this.debug = config.debug;\n this.embeddingOptions = config.embedding;\n\n this.vector = {\n enabled: true,\n available: null,\n extensionPath: this.vectorExtensionPath,\n };\n this.fts = { enabled: this.hybrid.enabled, available: false };\n }\n\n static async create(config: MinimemConfig): Promise<Minimem> {\n const instance = new Minimem(config);\n await instance.initialize();\n return instance;\n }\n\n private async initialize(): Promise<void> {\n // Create embedding provider\n const providerResult = await createEmbeddingProvider(this.embeddingOptions);\n this.provider = providerResult.provider;\n this.openAi = providerResult.openAi;\n this.gemini = providerResult.gemini;\n this.providerKey = this.computeProviderKey();\n this.providerFallbackReason = providerResult.fallbackReason;\n\n // Log warning if in BM25-only fallback mode\n if (this.provider.id === \"none\") {\n this.debug?.(\"Running in BM25-only mode (no embedding API available)\");\n }\n\n // Open database\n this.db = this.openDatabase();\n this.ensureSchema();\n\n // Check for existing vector dims\n const meta = this.readMeta();\n if (meta?.vectorDims) {\n this.vector.dims = meta.vectorDims;\n }\n\n // Start file watcher\n if (this.watchConfig.enabled) {\n this.ensureWatcher();\n }\n }\n\n private openDatabase(): DatabaseSync {\n const dbDir = path.dirname(this.dbPath);\n ensureDir(dbDir);\n return new DatabaseSync(this.dbPath);\n }\n\n private ensureSchema(): void {\n const result = ensureMemoryIndexSchema({\n db: this.db,\n embeddingCacheTable: EMBEDDING_CACHE_TABLE,\n ftsTable: FTS_TABLE,\n ftsEnabled: this.fts.enabled,\n });\n this.fts.available = result.ftsAvailable;\n if (result.ftsError) {\n this.fts.loadError = result.ftsError;\n }\n }\n\n private computeProviderKey(): string {\n const parts: string[] = [this.provider.id, this.provider.model];\n if (this.openAi) {\n parts.push(this.openAi.baseUrl);\n }\n if (this.gemini) {\n parts.push(this.gemini.baseUrl);\n }\n return hashText(parts.join(\":\"));\n }\n\n private readMeta(): MemoryIndexMeta | null {\n try {\n const row = this.db.prepare(`SELECT value FROM meta WHERE key = ?`).get(META_KEY) as\n | { value: string }\n | undefined;\n if (!row?.value) return null;\n return JSON.parse(row.value) as MemoryIndexMeta;\n } catch {\n return null;\n }\n }\n\n private writeMeta(meta: MemoryIndexMeta): void {\n this.db\n .prepare(`INSERT OR REPLACE INTO meta (key, value) VALUES (?, ?)`)\n .run(META_KEY, JSON.stringify(meta));\n }\n\n private ensureWatcher(): void {\n if (this.watcher) return;\n const memorySubDir = path.join(this.memoryDir, \"memory\");\n const memoryFile = path.join(this.memoryDir, \"MEMORY.md\");\n\n this.watcher = chokidar.watch([memoryFile, memorySubDir], {\n ignoreInitial: true,\n persistent: true,\n awaitWriteFinish: { stabilityThreshold: 200, pollInterval: 50 },\n });\n\n const scheduleSync = () => {\n this.dirty = true;\n if (this.watchTimer) clearTimeout(this.watchTimer);\n this.watchTimer = setTimeout(() => {\n void this.sync({ reason: \"watch\" }).catch((err) => {\n this.debug?.(`memory sync failed (watch): ${String(err)}`);\n });\n }, this.watchConfig.debounceMs);\n };\n\n this.watcher.on(\"add\", scheduleSync);\n this.watcher.on(\"change\", scheduleSync);\n this.watcher.on(\"unlink\", scheduleSync);\n }\n\n /**\n * Check if the index is stale by comparing file mtimes against stored values.\n * This is a lightweight check (stat calls only, no file reads).\n */\n private async isStale(): Promise<boolean> {\n try {\n const files = await listMemoryFiles(this.memoryDir);\n\n // Get stored file records\n const stored = this.db\n .prepare(`SELECT path, mtime FROM files WHERE source = ?`)\n .all(\"memory\") as Array<{ path: string; mtime: number }>;\n\n // Quick check: different file count means stale\n if (files.length !== stored.length) {\n this.debug?.(`Stale: file count changed (${stored.length} -> ${files.length})`);\n return true;\n }\n\n // Build lookup map of stored mtimes\n const storedMap = new Map(stored.map((f) => [f.path, f.mtime]));\n\n // Check each file's mtime against stored value\n for (const absPath of files) {\n const relPath = path.relative(this.memoryDir, absPath).replace(/\\\\/g, \"/\");\n const storedMtime = storedMap.get(relPath);\n\n // File not in index = stale\n if (storedMtime === undefined) {\n this.debug?.(`Stale: new file ${relPath}`);\n return true;\n }\n\n // Check mtime\n const stat = await fs.stat(absPath);\n const currentMtime = Math.floor(stat.mtimeMs);\n if (currentMtime !== storedMtime) {\n this.debug?.(`Stale: mtime changed for ${relPath}`);\n return true;\n }\n }\n\n return false;\n } catch (err) {\n // On error, assume stale to be safe\n this.debug?.(`Stale check failed: ${String(err)}`);\n return true;\n }\n }\n\n async search(\n query: string,\n opts?: { maxResults?: number; minScore?: number },\n ): Promise<MinimemSearchResult[]> {\n // Check staleness: use dirty flag if watcher is on, otherwise check mtimes\n if (this.dirty || (!this.watchConfig.enabled && (await this.isStale()))) {\n await this.sync({ reason: \"search\" });\n }\n\n const cleaned = query.trim();\n if (!cleaned) return [];\n\n const minScore = opts?.minScore ?? this.queryConfig.minScore;\n const maxResults = opts?.maxResults ?? this.queryConfig.maxResults;\n const candidates = Math.min(\n 200,\n Math.max(1, Math.floor(maxResults * this.hybrid.candidateMultiplier)),\n );\n\n const sourceFilter = { sql: \"\", params: [] as string[] };\n\n const keywordResults = this.hybrid.enabled && this.fts.available\n ? await searchKeyword({\n db: this.db,\n ftsTable: FTS_TABLE,\n providerModel: this.provider.model,\n query: cleaned,\n limit: candidates,\n snippetMaxChars: SNIPPET_MAX_CHARS,\n sourceFilter,\n buildFtsQuery,\n bm25RankToScore,\n }).catch(() => [])\n : [];\n\n const queryVec = await this.embedQueryWithTimeout(cleaned);\n const hasVector = queryVec.some((v) => v !== 0);\n const vectorResults = hasVector\n ? await searchVector({\n db: this.db,\n vectorTable: VECTOR_TABLE,\n providerModel: this.provider.model,\n queryVec,\n limit: candidates,\n snippetMaxChars: SNIPPET_MAX_CHARS,\n ensureVectorReady: (dims) => this.ensureVectorReady(dims),\n sourceFilterVec: sourceFilter,\n sourceFilterChunks: sourceFilter,\n }).catch(() => [])\n : [];\n\n if (!this.hybrid.enabled) {\n return vectorResults\n .filter((entry) => entry.score >= minScore)\n .slice(0, maxResults)\n .map((r) => ({\n path: r.path,\n startLine: r.startLine,\n endLine: r.endLine,\n score: r.score,\n snippet: r.snippet,\n }));\n }\n\n const merged = mergeHybridResults({\n vector: vectorResults.map((r) => ({\n id: r.id,\n path: r.path,\n startLine: r.startLine,\n endLine: r.endLine,\n source: r.source,\n snippet: r.snippet,\n vectorScore: r.score,\n })),\n keyword: keywordResults.map((r) => ({\n id: r.id,\n path: r.path,\n startLine: r.startLine,\n endLine: r.endLine,\n source: r.source,\n snippet: r.snippet,\n textScore: r.textScore,\n })),\n vectorWeight: this.hybrid.vectorWeight,\n textWeight: this.hybrid.textWeight,\n });\n\n return merged\n .filter((entry) => entry.score >= minScore)\n .slice(0, maxResults)\n .map((r) => ({\n path: r.path,\n startLine: r.startLine,\n endLine: r.endLine,\n score: r.score,\n snippet: r.snippet,\n }));\n }\n\n async sync(opts?: { reason?: string; force?: boolean }): Promise<void> {\n if (this.syncing) {\n await this.syncing;\n return;\n }\n\n this.syncing = this.runSync(opts);\n try {\n await this.syncing;\n } finally {\n this.syncing = null;\n }\n }\n\n private async runSync(opts?: { reason?: string; force?: boolean }): Promise<void> {\n this.debug?.(`memory sync starting`, { reason: opts?.reason });\n\n await this.ensureVectorReady();\n const meta = this.readMeta();\n const needsFullReindex =\n opts?.force ||\n !meta ||\n meta.model !== this.provider.model ||\n meta.provider !== this.provider.id ||\n meta.providerKey !== this.providerKey ||\n meta.chunkTokens !== this.chunking.tokens ||\n meta.chunkOverlap !== this.chunking.overlap ||\n (this.vector.available && !meta?.vectorDims);\n\n const files = await listMemoryFiles(this.memoryDir);\n const activePaths = new Set<string>();\n\n for (const absPath of files) {\n const entry = await buildFileEntry(absPath, this.memoryDir);\n activePaths.add(entry.path);\n\n const record = this.db\n .prepare(`SELECT hash FROM files WHERE path = ? AND source = ?`)\n .get(entry.path, \"memory\") as { hash: string } | undefined;\n\n if (!needsFullReindex && record?.hash === entry.hash) {\n continue;\n }\n\n await this.indexFile(entry);\n }\n\n // Delete stale entries\n const staleRows = this.db\n .prepare(`SELECT path FROM files WHERE source = ?`)\n .all(\"memory\") as Array<{ path: string }>;\n\n for (const stale of staleRows) {\n if (activePaths.has(stale.path)) continue;\n this.db.prepare(`DELETE FROM files WHERE path = ? AND source = ?`).run(stale.path, \"memory\");\n try {\n this.db\n .prepare(\n `DELETE FROM ${VECTOR_TABLE} WHERE id IN (SELECT id FROM chunks WHERE path = ? AND source = ?)`,\n )\n .run(stale.path, \"memory\");\n } catch {}\n this.db.prepare(`DELETE FROM chunks WHERE path = ? AND source = ?`).run(stale.path, \"memory\");\n if (this.fts.enabled && this.fts.available) {\n try {\n this.db\n .prepare(`DELETE FROM ${FTS_TABLE} WHERE path = ? AND source = ? AND model = ?`)\n .run(stale.path, \"memory\", this.provider.model);\n } catch {}\n }\n }\n\n // Write meta\n this.writeMeta({\n model: this.provider.model,\n provider: this.provider.id,\n providerKey: this.providerKey,\n chunkTokens: this.chunking.tokens,\n chunkOverlap: this.chunking.overlap,\n vectorDims: this.vector.dims,\n });\n\n // Prune embedding cache\n this.pruneEmbeddingCacheIfNeeded();\n\n this.dirty = false;\n this.debug?.(`memory sync complete`, { files: files.length });\n }\n\n private async indexFile(entry: MemoryFileEntry): Promise<void> {\n const content = await fs.readFile(entry.absPath, \"utf-8\");\n const chunks = chunkMarkdown(content, this.chunking);\n\n // Get embeddings\n const embeddings = await this.embedChunks(chunks);\n\n // Update files table\n this.db\n .prepare(\n `INSERT OR REPLACE INTO files (path, source, hash, mtime, size) VALUES (?, ?, ?, ?, ?)`,\n )\n .run(entry.path, \"memory\", entry.hash, Math.floor(entry.mtimeMs), entry.size);\n\n // Delete old chunks for this file\n try {\n this.db\n .prepare(\n `DELETE FROM ${VECTOR_TABLE} WHERE id IN (SELECT id FROM chunks WHERE path = ? AND source = ?)`,\n )\n .run(entry.path, \"memory\");\n } catch {}\n this.db.prepare(`DELETE FROM chunks WHERE path = ? AND source = ?`).run(entry.path, \"memory\");\n if (this.fts.enabled && this.fts.available) {\n try {\n this.db\n .prepare(`DELETE FROM ${FTS_TABLE} WHERE path = ? AND source = ? AND model = ?`)\n .run(entry.path, \"memory\", this.provider.model);\n } catch {}\n }\n\n // Insert new chunks\n const now = Date.now();\n for (let i = 0; i < chunks.length; i++) {\n const chunk = chunks[i];\n const embedding = embeddings[i] ?? [];\n const chunkId = randomUUID();\n\n this.db\n .prepare(\n `INSERT INTO chunks (id, path, source, start_line, end_line, hash, model, text, embedding, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n chunkId,\n entry.path,\n \"memory\",\n chunk.startLine,\n chunk.endLine,\n chunk.hash,\n this.provider.model,\n chunk.text,\n JSON.stringify(embedding),\n now,\n );\n\n // Insert into vector table if available\n if (this.vector.available && embedding.length > 0) {\n if (!this.vector.dims) {\n this.vector.dims = embedding.length;\n this.ensureVectorTable(embedding.length);\n }\n try {\n this.db\n .prepare(`INSERT INTO ${VECTOR_TABLE} (id, embedding) VALUES (?, ?)`)\n .run(chunkId, vectorToBlob(embedding));\n } catch {}\n }\n\n // Insert into FTS table if available\n if (this.fts.enabled && this.fts.available) {\n try {\n this.db\n .prepare(\n `INSERT INTO ${FTS_TABLE} (text, id, path, source, model, start_line, end_line)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n chunk.text,\n chunkId,\n entry.path,\n \"memory\",\n this.provider.model,\n chunk.startLine,\n chunk.endLine,\n );\n } catch {}\n }\n }\n }\n\n private async embedChunks(chunks: MemoryChunk[]): Promise<number[][]> {\n if (chunks.length === 0) return [];\n\n const hashes = chunks.map((c) => c.hash);\n const cached = this.loadEmbeddingCache(hashes);\n const missing: Array<{ index: number; chunk: MemoryChunk }> = [];\n\n for (let i = 0; i < chunks.length; i++) {\n if (!cached.has(hashes[i])) {\n missing.push({ index: i, chunk: chunks[i] });\n }\n }\n\n if (missing.length > 0) {\n const texts = missing.map((m) => m.chunk.text);\n const newEmbeddings = await this.embedBatchWithRetry(texts);\n\n for (let i = 0; i < missing.length; i++) {\n const hash = missing[i].chunk.hash;\n const embedding = newEmbeddings[i] ?? [];\n cached.set(hash, embedding);\n this.upsertEmbeddingCache(hash, embedding);\n }\n }\n\n return hashes.map((h) => cached.get(h) ?? []);\n }\n\n private async embedBatchWithRetry(texts: string[]): Promise<number[][]> {\n if (texts.length === 0) return [];\n\n // Try batch API first if enabled\n if (this.batchConfig.enabled) {\n try {\n return await this.embedWithBatchApi(texts);\n } catch (err) {\n this.debug?.(`batch embedding failed, falling back to direct: ${String(err)}`);\n }\n }\n\n // Fall back to direct embedding\n let lastError: Error | null = null;\n for (let attempt = 0; attempt < EMBEDDING_RETRY_MAX_ATTEMPTS; attempt++) {\n try {\n return await this.provider.embedBatch(texts);\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err));\n if (attempt < EMBEDDING_RETRY_MAX_ATTEMPTS - 1) {\n const delay = Math.min(\n EMBEDDING_RETRY_MAX_DELAY_MS,\n EMBEDDING_RETRY_BASE_DELAY_MS * Math.pow(2, attempt),\n );\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n }\n throw lastError;\n }\n\n private async embedWithBatchApi(texts: string[]): Promise<number[][]> {\n if (this.openAi) {\n const requests: OpenAiBatchRequest[] = texts.map((text, i) => ({\n custom_id: `chunk-${i}`,\n method: \"POST\",\n url: OPENAI_BATCH_ENDPOINT,\n body: { model: this.openAi!.model, input: text },\n }));\n\n const results = await runOpenAiEmbeddingBatches({\n openAi: this.openAi,\n source: \"minimem\",\n requests,\n wait: this.batchConfig.wait,\n pollIntervalMs: this.batchConfig.pollIntervalMs,\n timeoutMs: this.batchConfig.timeoutMs,\n concurrency: this.batchConfig.concurrency,\n debug: this.debug,\n });\n\n return texts.map((_, i) => results.get(`chunk-${i}`) ?? []);\n }\n\n if (this.gemini) {\n const requests: GeminiBatchRequest[] = texts.map((text, i) => ({\n custom_id: `chunk-${i}`,\n content: { parts: [{ text }] },\n taskType: \"RETRIEVAL_DOCUMENT\",\n }));\n\n const results = await runGeminiEmbeddingBatches({\n gemini: this.gemini,\n source: \"minimem\",\n requests,\n wait: this.batchConfig.wait,\n pollIntervalMs: this.batchConfig.pollIntervalMs,\n timeoutMs: this.batchConfig.timeoutMs,\n concurrency: this.batchConfig.concurrency,\n debug: this.debug,\n });\n\n return texts.map((_, i) => results.get(`chunk-${i}`) ?? []);\n }\n\n throw new Error(\"Batch API not available for local embeddings\");\n }\n\n private async embedQueryWithTimeout(text: string): Promise<number[]> {\n const timeout =\n this.provider.id === \"local\" ? EMBEDDING_QUERY_TIMEOUT_LOCAL_MS : EMBEDDING_QUERY_TIMEOUT_REMOTE_MS;\n\n return Promise.race([\n this.provider.embedQuery(text),\n new Promise<number[]>((_, reject) =>\n setTimeout(() => reject(new Error(\"embedding query timeout\")), timeout),\n ),\n ]);\n }\n\n private loadEmbeddingCache(hashes: string[]): Map<string, number[]> {\n const result = new Map<string, number[]>();\n if (!this.cache.enabled || hashes.length === 0) return result;\n\n const placeholders = hashes.map(() => \"?\").join(\",\");\n const rows = this.db\n .prepare(\n `SELECT hash, embedding FROM ${EMBEDDING_CACHE_TABLE}\n WHERE provider = ? AND model = ? AND provider_key = ? AND hash IN (${placeholders})`,\n )\n .all(this.provider.id, this.provider.model, this.providerKey, ...hashes) as Array<{\n hash: string;\n embedding: string;\n }>;\n\n const now = Date.now();\n for (const row of rows) {\n result.set(row.hash, parseEmbedding(row.embedding));\n // Touch for LRU\n this.db\n .prepare(\n `UPDATE ${EMBEDDING_CACHE_TABLE} SET updated_at = ?\n WHERE provider = ? AND model = ? AND provider_key = ? AND hash = ?`,\n )\n .run(now, this.provider.id, this.provider.model, this.providerKey, row.hash);\n }\n\n return result;\n }\n\n private upsertEmbeddingCache(hash: string, embedding: number[]): void {\n if (!this.cache.enabled) return;\n const now = Date.now();\n this.db\n .prepare(\n `INSERT OR REPLACE INTO ${EMBEDDING_CACHE_TABLE}\n (provider, model, provider_key, hash, embedding, dims, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n this.provider.id,\n this.provider.model,\n this.providerKey,\n hash,\n JSON.stringify(embedding),\n embedding.length,\n now,\n );\n }\n\n private pruneEmbeddingCacheIfNeeded(): void {\n if (!this.cache.enabled) return;\n const row = this.db\n .prepare(`SELECT COUNT(*) as count FROM ${EMBEDDING_CACHE_TABLE}`)\n .get() as { count: number };\n if (row.count <= this.cache.maxEntries) return;\n\n const excess = row.count - this.cache.maxEntries;\n this.db\n .prepare(\n `DELETE FROM ${EMBEDDING_CACHE_TABLE}\n WHERE rowid IN (\n SELECT rowid FROM ${EMBEDDING_CACHE_TABLE}\n ORDER BY updated_at ASC\n LIMIT ?\n )`,\n )\n .run(excess);\n }\n\n private async ensureVectorReady(dimensions?: number): Promise<boolean> {\n if (this.vector.available === true) return true;\n if (this.vector.available === false) return false;\n\n if (!this.vectorReady) {\n this.vectorReady = this.loadVectorExtension();\n }\n\n const ready = await this.vectorReady;\n if (ready && dimensions && !this.vector.dims) {\n this.vector.dims = dimensions;\n this.ensureVectorTable(dimensions);\n }\n return ready;\n }\n\n private async loadVectorExtension(): Promise<boolean> {\n const result = await loadSqliteVecExtension({\n db: this.db,\n extensionPath: this.vectorExtensionPath,\n });\n\n this.vector.available = result.ok;\n if (result.error) {\n this.vector.loadError = result.error;\n this.debug?.(`sqlite-vec load failed: ${result.error}`);\n }\n if (result.extensionPath) {\n this.vector.extensionPath = result.extensionPath;\n }\n\n return result.ok;\n }\n\n private ensureVectorTable(dimensions: number): void {\n if (!this.vector.available) return;\n try {\n this.db.exec(\n `CREATE VIRTUAL TABLE IF NOT EXISTS ${VECTOR_TABLE} USING vec0(\n id TEXT PRIMARY KEY,\n embedding FLOAT[${dimensions}]\n )`,\n );\n } catch (err) {\n this.debug?.(`vector table creation failed: ${String(err)}`);\n }\n }\n\n async readFile(relativePath: string): Promise<string | null> {\n const absPath = path.join(this.memoryDir, relativePath);\n try {\n return await fs.readFile(absPath, \"utf-8\");\n } catch {\n return null;\n }\n }\n\n /**\n * Read specific lines from a memory file\n */\n async readLines(\n relativePath: string,\n opts?: { from?: number; lines?: number },\n ): Promise<{ content: string; startLine: number; endLine: number } | null> {\n const content = await this.readFile(relativePath);\n if (content === null) return null;\n\n const allLines = content.split(\"\\n\");\n const from = Math.max(1, opts?.from ?? 1);\n const lines = opts?.lines ?? allLines.length;\n\n const startIdx = from - 1;\n const endIdx = Math.min(startIdx + lines, allLines.length);\n const selectedLines = allLines.slice(startIdx, endIdx);\n\n return {\n content: selectedLines.join(\"\\n\"),\n startLine: from,\n endLine: startIdx + selectedLines.length,\n };\n }\n\n /**\n * Write content to a memory file (creates or overwrites)\n */\n async writeFile(relativePath: string, content: string): Promise<void> {\n this.validateMemoryPath(relativePath);\n const absPath = path.join(this.memoryDir, relativePath);\n const dir = path.dirname(absPath);\n await fs.mkdir(dir, { recursive: true });\n await fs.writeFile(absPath, content, \"utf-8\");\n this.dirty = true;\n this.debug?.(`memory write: ${relativePath}`);\n }\n\n /**\n * Append content to a memory file (creates if doesn't exist)\n */\n async appendFile(relativePath: string, content: string): Promise<void> {\n this.validateMemoryPath(relativePath);\n const absPath = path.join(this.memoryDir, relativePath);\n const dir = path.dirname(absPath);\n await fs.mkdir(dir, { recursive: true });\n\n // Ensure newline separation\n let toAppend = content;\n try {\n const existing = await fs.readFile(absPath, \"utf-8\");\n if (existing.length > 0 && !existing.endsWith(\"\\n\")) {\n toAppend = \"\\n\" + content;\n }\n } catch {\n // File doesn't exist, will be created\n }\n\n await fs.appendFile(absPath, toAppend, \"utf-8\");\n this.dirty = true;\n this.debug?.(`memory append: ${relativePath}`);\n }\n\n /**\n * Append content to today's daily log (memory/YYYY-MM-DD.md)\n */\n async appendToday(content: string): Promise<string> {\n const today = new Date().toISOString().split(\"T\")[0]; // YYYY-MM-DD\n const relativePath = `memory/${today}.md`;\n await this.appendFile(relativePath, content);\n return relativePath;\n }\n\n /**\n * List all memory files\n */\n async listFiles(): Promise<string[]> {\n const files = await listMemoryFiles(this.memoryDir);\n return files.map((f) => path.relative(this.memoryDir, f).replace(/\\\\/g, \"/\"));\n }\n\n /**\n * Validate that a path is within allowed memory locations\n */\n private validateMemoryPath(relativePath: string): void {\n const normalized = relativePath.replace(/\\\\/g, \"/\").replace(/^\\.\\//, \"\");\n\n // Allow MEMORY.md at root\n if (normalized === \"MEMORY.md\" || normalized === \"memory.md\") {\n return;\n }\n\n // Allow anything under memory/\n if (normalized.startsWith(\"memory/\") && normalized.endsWith(\".md\")) {\n // Prevent path traversal\n if (normalized.includes(\"..\")) {\n throw new Error(`Invalid memory path: ${relativePath} (path traversal not allowed)`);\n }\n return;\n }\n\n throw new Error(\n `Invalid memory path: ${relativePath}. Must be MEMORY.md or memory/*.md`,\n );\n }\n\n async status(): Promise<{\n memoryDir: string;\n dbPath: string;\n provider: string;\n model: string;\n vectorAvailable: boolean;\n ftsAvailable: boolean;\n bm25Only: boolean;\n fallbackReason?: string;\n fileCount: number;\n chunkCount: number;\n cacheCount: number;\n }> {\n const fileRow = this.db.prepare(`SELECT COUNT(*) as count FROM files`).get() as { count: number };\n const chunkRow = this.db.prepare(`SELECT COUNT(*) as count FROM chunks`).get() as { count: number };\n const cacheRow = this.db\n .prepare(`SELECT COUNT(*) as count FROM ${EMBEDDING_CACHE_TABLE}`)\n .get() as { count: number };\n\n return {\n memoryDir: this.memoryDir,\n dbPath: this.dbPath,\n provider: this.provider.id,\n model: this.provider.model,\n vectorAvailable: this.vector.available === true,\n ftsAvailable: this.fts.available,\n bm25Only: this.provider.id === \"none\",\n fallbackReason: this.providerFallbackReason,\n fileCount: fileRow.count,\n chunkCount: chunkRow.count,\n cacheCount: cacheRow.count,\n };\n }\n\n close(): void {\n if (this.closed) return;\n this.closed = true;\n\n if (this.watchTimer) {\n clearTimeout(this.watchTimer);\n this.watchTimer = null;\n }\n\n if (this.watcher) {\n void this.watcher.close();\n this.watcher = null;\n }\n\n try {\n this.db.close();\n } catch {}\n }\n}\n","import crypto from \"node:crypto\";\nimport fsSync from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\nexport type MemoryFileEntry = {\n path: string;\n absPath: string;\n mtimeMs: number;\n size: number;\n hash: string;\n};\n\nexport type MemoryChunk = {\n startLine: number;\n endLine: number;\n text: string;\n hash: string;\n};\n\nexport function ensureDir(dir: string): string {\n try {\n fsSync.mkdirSync(dir, { recursive: true });\n } catch {}\n return dir;\n}\n\nexport function normalizeRelPath(value: string): string {\n const trimmed = value.trim().replace(/^[./]+/, \"\");\n return trimmed.replace(/\\\\/g, \"/\");\n}\n\nexport function isMemoryPath(relPath: string): boolean {\n const normalized = normalizeRelPath(relPath);\n if (!normalized) return false;\n if (normalized === \"MEMORY.md\" || normalized === \"memory.md\") return true;\n return normalized.startsWith(\"memory/\");\n}\n\nasync function exists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function walkDir(dir: string, files: string[]) {\n const entries = await fs.readdir(dir, { withFileTypes: true });\n for (const entry of entries) {\n const full = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n await walkDir(full, files);\n continue;\n }\n if (!entry.isFile()) continue;\n if (!entry.name.endsWith(\".md\")) continue;\n files.push(full);\n }\n}\n\nexport async function listMemoryFiles(memoryDir: string): Promise<string[]> {\n const result: string[] = [];\n const memoryFile = path.join(memoryDir, \"MEMORY.md\");\n const altMemoryFile = path.join(memoryDir, \"memory.md\");\n if (await exists(memoryFile)) result.push(memoryFile);\n if (await exists(altMemoryFile)) result.push(altMemoryFile);\n const memorySubDir = path.join(memoryDir, \"memory\");\n if (await exists(memorySubDir)) {\n await walkDir(memorySubDir, result);\n }\n if (result.length <= 1) return result;\n const seen = new Set<string>();\n const deduped: string[] = [];\n for (const entry of result) {\n let key = entry;\n try {\n key = await fs.realpath(entry);\n } catch {}\n if (seen.has(key)) continue;\n seen.add(key);\n deduped.push(entry);\n }\n return deduped;\n}\n\nexport function hashText(value: string): string {\n return crypto.createHash(\"sha256\").update(value).digest(\"hex\");\n}\n\nexport async function buildFileEntry(\n absPath: string,\n memoryDir: string,\n): Promise<MemoryFileEntry> {\n const stat = await fs.stat(absPath);\n const content = await fs.readFile(absPath, \"utf-8\");\n const hash = hashText(content);\n return {\n path: path.relative(memoryDir, absPath).replace(/\\\\/g, \"/\"),\n absPath,\n mtimeMs: stat.mtimeMs,\n size: stat.size,\n hash,\n };\n}\n\nexport function chunkMarkdown(\n content: string,\n chunking: { tokens: number; overlap: number },\n): MemoryChunk[] {\n const lines = content.split(\"\\n\");\n if (lines.length === 0) return [];\n const maxChars = Math.max(32, chunking.tokens * 4);\n const overlapChars = Math.max(0, chunking.overlap * 4);\n const chunks: MemoryChunk[] = [];\n\n let current: Array<{ line: string; lineNo: number }> = [];\n let currentChars = 0;\n\n const flush = () => {\n if (current.length === 0) return;\n const firstEntry = current[0];\n const lastEntry = current[current.length - 1];\n if (!firstEntry || !lastEntry) return;\n const text = current.map((entry) => entry.line).join(\"\\n\");\n const startLine = firstEntry.lineNo;\n const endLine = lastEntry.lineNo;\n chunks.push({\n startLine,\n endLine,\n text,\n hash: hashText(text),\n });\n };\n\n const carryOverlap = () => {\n if (overlapChars <= 0 || current.length === 0) {\n current = [];\n currentChars = 0;\n return;\n }\n let acc = 0;\n const kept: Array<{ line: string; lineNo: number }> = [];\n for (let i = current.length - 1; i >= 0; i -= 1) {\n const entry = current[i];\n if (!entry) continue;\n acc += entry.line.length + 1;\n kept.unshift(entry);\n if (acc >= overlapChars) break;\n }\n current = kept;\n currentChars = kept.reduce((sum, entry) => sum + entry.line.length + 1, 0);\n };\n\n for (let i = 0; i < lines.length; i += 1) {\n const line = lines[i] ?? \"\";\n const lineNo = i + 1;\n const segments: string[] = [];\n if (line.length === 0) {\n segments.push(\"\");\n } else {\n for (let start = 0; start < line.length; start += maxChars) {\n segments.push(line.slice(start, start + maxChars));\n }\n }\n for (const segment of segments) {\n const lineSize = segment.length + 1;\n if (currentChars + lineSize > maxChars && current.length > 0) {\n flush();\n carryOverlap();\n }\n current.push({ line: segment, lineNo });\n currentChars += lineSize;\n }\n }\n flush();\n return chunks;\n}\n\nexport function parseEmbedding(raw: string): number[] {\n try {\n const parsed = JSON.parse(raw) as number[];\n return Array.isArray(parsed) ? parsed : [];\n } catch {\n return [];\n }\n}\n\nexport function cosineSimilarity(a: number[], b: number[]): number {\n if (a.length === 0 || b.length === 0) return 0;\n const len = Math.min(a.length, b.length);\n let dot = 0;\n let normA = 0;\n let normB = 0;\n for (let i = 0; i < len; i += 1) {\n const av = a[i] ?? 0;\n const bv = b[i] ?? 0;\n dot += av * bv;\n normA += av * av;\n normB += bv * bv;\n }\n if (normA === 0 || normB === 0) return 0;\n return dot / (Math.sqrt(normA) * Math.sqrt(normB));\n}\n\nexport function truncateUtf16Safe(text: string, maxChars: number): string {\n if (text.length <= maxChars) return text;\n return text.slice(0, maxChars);\n}\n","export type HybridSource = string;\n\nexport type HybridVectorResult = {\n id: string;\n path: string;\n startLine: number;\n endLine: number;\n source: HybridSource;\n snippet: string;\n vectorScore: number;\n};\n\nexport type HybridKeywordResult = {\n id: string;\n path: string;\n startLine: number;\n endLine: number;\n source: HybridSource;\n snippet: string;\n textScore: number;\n};\n\nexport function buildFtsQuery(raw: string): string | null {\n const tokens =\n raw\n .match(/[A-Za-z0-9_]+/g)\n ?.map((t) => t.trim())\n .filter(Boolean) ?? [];\n if (tokens.length === 0) return null;\n const quoted = tokens.map((t) => `\"${t.replaceAll('\"', \"\")}\"`);\n return quoted.join(\" AND \");\n}\n\nexport function bm25RankToScore(rank: number): number {\n const normalized = Number.isFinite(rank) ? Math.max(0, rank) : 999;\n return 1 / (1 + normalized);\n}\n\nexport function mergeHybridResults(params: {\n vector: HybridVectorResult[];\n keyword: HybridKeywordResult[];\n vectorWeight: number;\n textWeight: number;\n}): Array<{\n path: string;\n startLine: number;\n endLine: number;\n score: number;\n snippet: string;\n source: HybridSource;\n}> {\n const byId = new Map<\n string,\n {\n id: string;\n path: string;\n startLine: number;\n endLine: number;\n source: HybridSource;\n snippet: string;\n vectorScore: number;\n textScore: number;\n }\n >();\n\n for (const r of params.vector) {\n byId.set(r.id, {\n id: r.id,\n path: r.path,\n startLine: r.startLine,\n endLine: r.endLine,\n source: r.source,\n snippet: r.snippet,\n vectorScore: r.vectorScore,\n textScore: 0,\n });\n }\n\n for (const r of params.keyword) {\n const existing = byId.get(r.id);\n if (existing) {\n existing.textScore = r.textScore;\n if (r.snippet && r.snippet.length > 0) existing.snippet = r.snippet;\n } else {\n byId.set(r.id, {\n id: r.id,\n path: r.path,\n startLine: r.startLine,\n endLine: r.endLine,\n source: r.source,\n snippet: r.snippet,\n vectorScore: 0,\n textScore: r.textScore,\n });\n }\n }\n\n const merged = Array.from(byId.values()).map((entry) => {\n const score = params.vectorWeight * entry.vectorScore + params.textWeight * entry.textScore;\n return {\n path: entry.path,\n startLine: entry.startLine,\n endLine: entry.endLine,\n score,\n snippet: entry.snippet,\n source: entry.source,\n };\n });\n\n return merged.sort((a, b) => b.score - a.score);\n}\n","import type { DatabaseSync } from \"node:sqlite\";\n\nimport { cosineSimilarity, parseEmbedding, truncateUtf16Safe } from \"../internal.js\";\n\nconst vectorToBlob = (embedding: number[]): Buffer =>\n Buffer.from(new Float32Array(embedding).buffer);\n\nexport type SearchSource = string;\n\nexport type SearchRowResult = {\n id: string;\n path: string;\n startLine: number;\n endLine: number;\n score: number;\n snippet: string;\n source: SearchSource;\n};\n\nexport async function searchVector(params: {\n db: DatabaseSync;\n vectorTable: string;\n providerModel: string;\n queryVec: number[];\n limit: number;\n snippetMaxChars: number;\n ensureVectorReady: (dimensions: number) => Promise<boolean>;\n sourceFilterVec: { sql: string; params: SearchSource[] };\n sourceFilterChunks: { sql: string; params: SearchSource[] };\n}): Promise<SearchRowResult[]> {\n if (params.queryVec.length === 0 || params.limit <= 0) return [];\n if (await params.ensureVectorReady(params.queryVec.length)) {\n const rows = params.db\n .prepare(\n `SELECT c.id, c.path, c.start_line, c.end_line, c.text,\\n` +\n ` c.source,\\n` +\n ` vec_distance_cosine(v.embedding, ?) AS dist\\n` +\n ` FROM ${params.vectorTable} v\\n` +\n ` JOIN chunks c ON c.id = v.id\\n` +\n ` WHERE c.model = ?${params.sourceFilterVec.sql}\\n` +\n ` ORDER BY dist ASC\\n` +\n ` LIMIT ?`,\n )\n .all(\n vectorToBlob(params.queryVec),\n params.providerModel,\n ...params.sourceFilterVec.params,\n params.limit,\n ) as Array<{\n id: string;\n path: string;\n start_line: number;\n end_line: number;\n text: string;\n source: SearchSource;\n dist: number;\n }>;\n return rows.map((row) => ({\n id: row.id,\n path: row.path,\n startLine: row.start_line,\n endLine: row.end_line,\n score: 1 - row.dist,\n snippet: truncateUtf16Safe(row.text, params.snippetMaxChars),\n source: row.source,\n }));\n }\n\n const candidates = listChunks({\n db: params.db,\n providerModel: params.providerModel,\n sourceFilter: params.sourceFilterChunks,\n });\n const scored = candidates\n .map((chunk) => ({\n chunk,\n score: cosineSimilarity(params.queryVec, chunk.embedding),\n }))\n .filter((entry) => Number.isFinite(entry.score));\n return scored\n .sort((a, b) => b.score - a.score)\n .slice(0, params.limit)\n .map((entry) => ({\n id: entry.chunk.id,\n path: entry.chunk.path,\n startLine: entry.chunk.startLine,\n endLine: entry.chunk.endLine,\n score: entry.score,\n snippet: truncateUtf16Safe(entry.chunk.text, params.snippetMaxChars),\n source: entry.chunk.source,\n }));\n}\n\nexport function listChunks(params: {\n db: DatabaseSync;\n providerModel: string;\n sourceFilter: { sql: string; params: SearchSource[] };\n}): Array<{\n id: string;\n path: string;\n startLine: number;\n endLine: number;\n text: string;\n embedding: number[];\n source: SearchSource;\n}> {\n const rows = params.db\n .prepare(\n `SELECT id, path, start_line, end_line, text, embedding, source\\n` +\n ` FROM chunks\\n` +\n ` WHERE model = ?${params.sourceFilter.sql}`,\n )\n .all(params.providerModel, ...params.sourceFilter.params) as Array<{\n id: string;\n path: string;\n start_line: number;\n end_line: number;\n text: string;\n embedding: string;\n source: SearchSource;\n }>;\n\n return rows.map((row) => ({\n id: row.id,\n path: row.path,\n startLine: row.start_line,\n endLine: row.end_line,\n text: row.text,\n embedding: parseEmbedding(row.embedding),\n source: row.source,\n }));\n}\n\nexport async function searchKeyword(params: {\n db: DatabaseSync;\n ftsTable: string;\n providerModel: string;\n query: string;\n limit: number;\n snippetMaxChars: number;\n sourceFilter: { sql: string; params: SearchSource[] };\n buildFtsQuery: (raw: string) => string | null;\n bm25RankToScore: (rank: number) => number;\n}): Promise<Array<SearchRowResult & { textScore: number }>> {\n if (params.limit <= 0) return [];\n const ftsQuery = params.buildFtsQuery(params.query);\n if (!ftsQuery) return [];\n\n const rows = params.db\n .prepare(\n `SELECT id, path, source, start_line, end_line, text,\\n` +\n ` bm25(${params.ftsTable}) AS rank\\n` +\n ` FROM ${params.ftsTable}\\n` +\n ` WHERE ${params.ftsTable} MATCH ? AND model = ?${params.sourceFilter.sql}\\n` +\n ` ORDER BY rank ASC\\n` +\n ` LIMIT ?`,\n )\n .all(ftsQuery, params.providerModel, ...params.sourceFilter.params, params.limit) as Array<{\n id: string;\n path: string;\n source: SearchSource;\n start_line: number;\n end_line: number;\n text: string;\n rank: number;\n }>;\n\n return rows.map((row) => {\n const textScore = params.bm25RankToScore(row.rank);\n return {\n id: row.id,\n path: row.path,\n startLine: row.start_line,\n endLine: row.end_line,\n score: textScore,\n textScore,\n snippet: truncateUtf16Safe(row.text, params.snippetMaxChars),\n source: row.source,\n };\n });\n}\n","import type { DatabaseSync } from \"node:sqlite\";\n\nexport function ensureMemoryIndexSchema(params: {\n db: DatabaseSync;\n embeddingCacheTable: string;\n ftsTable: string;\n ftsEnabled: boolean;\n}): { ftsAvailable: boolean; ftsError?: string } {\n params.db.exec(`\n CREATE TABLE IF NOT EXISTS meta (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n );\n `);\n params.db.exec(`\n CREATE TABLE IF NOT EXISTS files (\n path TEXT PRIMARY KEY,\n source TEXT NOT NULL DEFAULT 'memory',\n hash TEXT NOT NULL,\n mtime INTEGER NOT NULL,\n size INTEGER NOT NULL\n );\n `);\n params.db.exec(`\n CREATE TABLE IF NOT EXISTS chunks (\n id TEXT PRIMARY KEY,\n path TEXT NOT NULL,\n source TEXT NOT NULL DEFAULT 'memory',\n start_line INTEGER NOT NULL,\n end_line INTEGER NOT NULL,\n hash TEXT NOT NULL,\n model TEXT NOT NULL,\n text TEXT NOT NULL,\n embedding TEXT NOT NULL,\n updated_at INTEGER NOT NULL\n );\n `);\n params.db.exec(`\n CREATE TABLE IF NOT EXISTS ${params.embeddingCacheTable} (\n provider TEXT NOT NULL,\n model TEXT NOT NULL,\n provider_key TEXT NOT NULL,\n hash TEXT NOT NULL,\n embedding TEXT NOT NULL,\n dims INTEGER,\n updated_at INTEGER NOT NULL,\n PRIMARY KEY (provider, model, provider_key, hash)\n );\n `);\n params.db.exec(\n `CREATE INDEX IF NOT EXISTS idx_embedding_cache_updated_at ON ${params.embeddingCacheTable}(updated_at);`,\n );\n\n let ftsAvailable = false;\n let ftsError: string | undefined;\n if (params.ftsEnabled) {\n try {\n params.db.exec(\n `CREATE VIRTUAL TABLE IF NOT EXISTS ${params.ftsTable} USING fts5(\\n` +\n ` text,\\n` +\n ` id UNINDEXED,\\n` +\n ` path UNINDEXED,\\n` +\n ` source UNINDEXED,\\n` +\n ` model UNINDEXED,\\n` +\n ` start_line UNINDEXED,\\n` +\n ` end_line UNINDEXED\\n` +\n `);`,\n );\n ftsAvailable = true;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n ftsAvailable = false;\n ftsError = message;\n }\n }\n\n ensureColumn(params.db, \"files\", \"source\", \"TEXT NOT NULL DEFAULT 'memory'\");\n ensureColumn(params.db, \"chunks\", \"source\", \"TEXT NOT NULL DEFAULT 'memory'\");\n params.db.exec(`CREATE INDEX IF NOT EXISTS idx_chunks_path ON chunks(path);`);\n params.db.exec(`CREATE INDEX IF NOT EXISTS idx_chunks_source ON chunks(source);`);\n\n return { ftsAvailable, ...(ftsError ? { ftsError } : {}) };\n}\n\nfunction ensureColumn(\n db: DatabaseSync,\n table: \"files\" | \"chunks\",\n column: string,\n definition: string,\n): void {\n const rows = db.prepare(`PRAGMA table_info(${table})`).all() as Array<{ name: string }>;\n if (rows.some((row) => row.name === column)) return;\n db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);\n}\n","import type { DatabaseSync } from \"node:sqlite\";\n\nexport async function loadSqliteVecExtension(params: {\n db: DatabaseSync;\n extensionPath?: string;\n}): Promise<{ ok: boolean; extensionPath?: string; error?: string }> {\n try {\n const sqliteVec = await import(\"sqlite-vec\");\n const resolvedPath = params.extensionPath?.trim() ? params.extensionPath.trim() : undefined;\n const extensionPath = resolvedPath ?? sqliteVec.getLoadablePath();\n\n params.db.enableLoadExtension(true);\n if (resolvedPath) {\n params.db.loadExtension(extensionPath);\n } else {\n sqliteVec.load(params.db);\n }\n\n return { ok: true, extensionPath };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { ok: false, error: message };\n }\n}\n","import fsSync from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\n\nimport type { Llama, LlamaEmbeddingContext, LlamaModel } from \"node-llama-cpp\";\n\nexport type EmbeddingProvider = {\n id: string;\n model: string;\n embedQuery: (text: string) => Promise<number[]>;\n embedBatch: (texts: string[]) => Promise<number[][]>;\n};\n\nexport type EmbeddingProviderResult = {\n provider: EmbeddingProvider;\n requestedProvider: \"openai\" | \"local\" | \"gemini\" | \"auto\";\n fallbackFrom?: \"openai\" | \"local\" | \"gemini\";\n fallbackReason?: string;\n openAi?: OpenAiEmbeddingClient;\n gemini?: GeminiEmbeddingClient;\n};\n\nexport type EmbeddingProviderOptions = {\n provider: \"openai\" | \"local\" | \"gemini\" | \"auto\" | \"none\";\n model?: string;\n fallback?: \"openai\" | \"gemini\" | \"local\" | \"none\";\n openai?: {\n apiKey?: string;\n baseUrl?: string;\n headers?: Record<string, string>;\n };\n gemini?: {\n apiKey?: string;\n baseUrl?: string;\n headers?: Record<string, string>;\n };\n local?: {\n modelPath?: string;\n modelCacheDir?: string;\n };\n};\n\nexport type OpenAiEmbeddingClient = {\n baseUrl: string;\n headers: Record<string, string>;\n model: string;\n};\n\nexport type GeminiEmbeddingClient = {\n baseUrl: string;\n headers: Record<string, string>;\n model: string;\n modelPath: string;\n};\n\nconst DEFAULT_LOCAL_MODEL = \"hf:ggml-org/embeddinggemma-300M-GGUF/embeddinggemma-300M-Q8_0.gguf\";\nconst DEFAULT_OPENAI_EMBEDDING_MODEL = \"text-embedding-3-small\";\nconst DEFAULT_OPENAI_BASE_URL = \"https://api.openai.com/v1\";\nconst DEFAULT_GEMINI_EMBEDDING_MODEL = \"gemini-embedding-001\";\nconst DEFAULT_GEMINI_BASE_URL = \"https://generativelanguage.googleapis.com/v1beta\";\n\n/**\n * Creates a no-op embedding provider that returns empty vectors.\n * Used for BM25-only mode when no embedding API is available.\n */\nfunction createNoOpEmbeddingProvider(): EmbeddingProvider {\n return {\n id: \"none\",\n model: \"bm25-only\",\n embedQuery: async () => [],\n embedBatch: async (texts) => texts.map(() => []),\n };\n}\n\nfunction resolveUserPath(filePath: string): string {\n if (filePath.startsWith(\"~/\")) {\n return path.join(os.homedir(), filePath.slice(2));\n }\n return filePath;\n}\n\nfunction canAutoSelectLocal(options: EmbeddingProviderOptions): boolean {\n const modelPath = options.local?.modelPath?.trim();\n if (!modelPath) return false;\n if (/^(hf:|https?:)/i.test(modelPath)) return false;\n const resolved = resolveUserPath(modelPath);\n try {\n return fsSync.statSync(resolved).isFile();\n } catch {\n return false;\n }\n}\n\nfunction isMissingApiKeyError(err: unknown): boolean {\n const message = formatError(err);\n return message.includes(\"API key\") || message.includes(\"apiKey\");\n}\n\nasync function importNodeLlamaCpp() {\n const llama = await import(\"node-llama-cpp\");\n return llama;\n}\n\nasync function createLocalEmbeddingProvider(\n options: EmbeddingProviderOptions,\n): Promise<EmbeddingProvider> {\n const modelPath = options.local?.modelPath?.trim() || DEFAULT_LOCAL_MODEL;\n const modelCacheDir = options.local?.modelCacheDir?.trim();\n\n const { getLlama, resolveModelFile, LlamaLogLevel } = await importNodeLlamaCpp();\n\n let llama: Llama | null = null;\n let embeddingModel: LlamaModel | null = null;\n let embeddingContext: LlamaEmbeddingContext | null = null;\n\n const ensureContext = async () => {\n if (!llama) {\n llama = await getLlama({ logLevel: LlamaLogLevel.error });\n }\n if (!embeddingModel) {\n const resolved = await resolveModelFile(modelPath, modelCacheDir || undefined);\n embeddingModel = await llama.loadModel({ modelPath: resolved });\n }\n if (!embeddingContext) {\n embeddingContext = await embeddingModel.createEmbeddingContext();\n }\n return embeddingContext;\n };\n\n return {\n id: \"local\",\n model: modelPath,\n embedQuery: async (text) => {\n const ctx = await ensureContext();\n const embedding = await ctx.getEmbeddingFor(text);\n return Array.from(embedding.vector) as number[];\n },\n embedBatch: async (texts) => {\n const ctx = await ensureContext();\n const embeddings = await Promise.all(\n texts.map(async (text) => {\n const embedding = await ctx.getEmbeddingFor(text);\n return Array.from(embedding.vector) as number[];\n }),\n );\n return embeddings;\n },\n };\n}\n\nfunction normalizeOpenAiModel(model: string): string {\n const trimmed = model.trim();\n if (!trimmed) return DEFAULT_OPENAI_EMBEDDING_MODEL;\n if (trimmed.startsWith(\"openai/\")) return trimmed.slice(\"openai/\".length);\n return trimmed;\n}\n\nfunction resolveOpenAiApiKey(options: EmbeddingProviderOptions): string {\n const apiKey = options.openai?.apiKey?.trim();\n if (apiKey) return apiKey;\n const envKey = process.env.OPENAI_API_KEY?.trim();\n if (envKey) return envKey;\n throw new Error(\"OpenAI API key not found. Set OPENAI_API_KEY env var or pass openai.apiKey option.\");\n}\n\nexport async function createOpenAiEmbeddingProvider(\n options: EmbeddingProviderOptions,\n): Promise<{ provider: EmbeddingProvider; client: OpenAiEmbeddingClient }> {\n const apiKey = resolveOpenAiApiKey(options);\n const baseUrl = options.openai?.baseUrl?.trim() || DEFAULT_OPENAI_BASE_URL;\n const headerOverrides = options.openai?.headers ?? {};\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n ...headerOverrides,\n };\n const model = normalizeOpenAiModel(options.model || \"\");\n const client: OpenAiEmbeddingClient = { baseUrl, headers, model };\n const url = `${baseUrl.replace(/\\/$/, \"\")}/embeddings`;\n\n const embed = async (input: string[]): Promise<number[][]> => {\n if (input.length === 0) return [];\n const res = await fetch(url, {\n method: \"POST\",\n headers: client.headers,\n body: JSON.stringify({ model: client.model, input }),\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`openai embeddings failed: ${res.status} ${text}`);\n }\n const payload = (await res.json()) as {\n data?: Array<{ embedding?: number[] }>;\n };\n const data = payload.data ?? [];\n return data.map((entry) => entry.embedding ?? []);\n };\n\n return {\n provider: {\n id: \"openai\",\n model: client.model,\n embedQuery: async (text) => {\n const [vec] = await embed([text]);\n return vec ?? [];\n },\n embedBatch: embed,\n },\n client,\n };\n}\n\nfunction normalizeGeminiModel(model: string): string {\n const trimmed = model.trim();\n if (!trimmed) return DEFAULT_GEMINI_EMBEDDING_MODEL;\n const withoutPrefix = trimmed.replace(/^models\\//, \"\");\n if (withoutPrefix.startsWith(\"gemini/\")) return withoutPrefix.slice(\"gemini/\".length);\n if (withoutPrefix.startsWith(\"google/\")) return withoutPrefix.slice(\"google/\".length);\n return withoutPrefix;\n}\n\nfunction normalizeGeminiBaseUrl(raw: string): string {\n const trimmed = raw.replace(/\\/+$/, \"\");\n const openAiIndex = trimmed.indexOf(\"/openai\");\n if (openAiIndex > -1) return trimmed.slice(0, openAiIndex);\n return trimmed;\n}\n\nfunction buildGeminiModelPath(model: string): string {\n return model.startsWith(\"models/\") ? model : `models/${model}`;\n}\n\nfunction resolveGeminiApiKey(options: EmbeddingProviderOptions): string {\n const apiKey = options.gemini?.apiKey?.trim();\n if (apiKey) return apiKey;\n const googleKey = process.env.GOOGLE_API_KEY?.trim();\n if (googleKey) return googleKey;\n const geminiKey = process.env.GEMINI_API_KEY?.trim();\n if (geminiKey) return geminiKey;\n throw new Error(\"Gemini API key not found. Set GOOGLE_API_KEY or GEMINI_API_KEY env var or pass gemini.apiKey option.\");\n}\n\nexport async function createGeminiEmbeddingProvider(\n options: EmbeddingProviderOptions,\n): Promise<{ provider: EmbeddingProvider; client: GeminiEmbeddingClient }> {\n const apiKey = resolveGeminiApiKey(options);\n const rawBaseUrl = options.gemini?.baseUrl?.trim() || DEFAULT_GEMINI_BASE_URL;\n const baseUrl = normalizeGeminiBaseUrl(rawBaseUrl);\n const headerOverrides = options.gemini?.headers ?? {};\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"x-goog-api-key\": apiKey,\n ...headerOverrides,\n };\n const model = normalizeGeminiModel(options.model || \"\");\n const modelPath = buildGeminiModelPath(model);\n const client: GeminiEmbeddingClient = { baseUrl, headers, model, modelPath };\n\n const embedUrl = `${baseUrl}/${modelPath}:embedContent`;\n const batchUrl = `${baseUrl}/${modelPath}:batchEmbedContents`;\n\n const embedQuery = async (text: string): Promise<number[]> => {\n if (!text.trim()) return [];\n const res = await fetch(embedUrl, {\n method: \"POST\",\n headers: client.headers,\n body: JSON.stringify({\n content: { parts: [{ text }] },\n taskType: \"RETRIEVAL_QUERY\",\n }),\n });\n if (!res.ok) {\n const payload = await res.text();\n throw new Error(`gemini embeddings failed: ${res.status} ${payload}`);\n }\n const payload = (await res.json()) as { embedding?: { values?: number[] } };\n return payload.embedding?.values ?? [];\n };\n\n const embedBatch = async (texts: string[]): Promise<number[][]> => {\n if (texts.length === 0) return [];\n const requests = texts.map((text) => ({\n model: modelPath,\n content: { parts: [{ text }] },\n taskType: \"RETRIEVAL_DOCUMENT\",\n }));\n const res = await fetch(batchUrl, {\n method: \"POST\",\n headers: client.headers,\n body: JSON.stringify({ requests }),\n });\n if (!res.ok) {\n const payload = await res.text();\n throw new Error(`gemini embeddings failed: ${res.status} ${payload}`);\n }\n const payload = (await res.json()) as { embeddings?: Array<{ values?: number[] }> };\n const embeddings = Array.isArray(payload.embeddings) ? payload.embeddings : [];\n return texts.map((_, index) => embeddings[index]?.values ?? []);\n };\n\n return {\n provider: {\n id: \"gemini\",\n model: client.model,\n embedQuery,\n embedBatch,\n },\n client,\n };\n}\n\nexport async function createEmbeddingProvider(\n options: EmbeddingProviderOptions,\n): Promise<EmbeddingProviderResult> {\n const requestedProvider = options.provider;\n const fallback = options.fallback ?? \"none\";\n\n // Handle explicit \"none\" provider (BM25-only mode)\n if (requestedProvider === \"none\") {\n return {\n provider: createNoOpEmbeddingProvider(),\n requestedProvider: \"none\" as \"auto\", // Type coercion for compatibility\n };\n }\n\n const createProvider = async (id: \"openai\" | \"local\" | \"gemini\") => {\n if (id === \"local\") {\n const provider = await createLocalEmbeddingProvider(options);\n return { provider };\n }\n if (id === \"gemini\") {\n const { provider, client } = await createGeminiEmbeddingProvider(options);\n return { provider, gemini: client };\n }\n const { provider, client } = await createOpenAiEmbeddingProvider(options);\n return { provider, openAi: client };\n };\n\n const formatPrimaryError = (err: unknown, provider: \"openai\" | \"local\" | \"gemini\") =>\n provider === \"local\" ? formatLocalSetupError(err) : formatError(err);\n\n if (requestedProvider === \"auto\") {\n const missingKeyErrors: string[] = [];\n let localError: string | null = null;\n\n if (canAutoSelectLocal(options)) {\n try {\n const local = await createProvider(\"local\");\n return { ...local, requestedProvider };\n } catch (err) {\n localError = formatLocalSetupError(err);\n }\n }\n\n for (const provider of [\"openai\", \"gemini\"] as const) {\n try {\n const result = await createProvider(provider);\n return { ...result, requestedProvider };\n } catch (err) {\n const message = formatPrimaryError(err, provider);\n if (isMissingApiKeyError(err)) {\n missingKeyErrors.push(message);\n continue;\n }\n throw new Error(message);\n }\n }\n\n // Fall back to BM25-only mode instead of throwing\n // This allows the system to work without any API keys using full-text search only\n return {\n provider: createNoOpEmbeddingProvider(),\n requestedProvider,\n fallbackFrom: \"auto\" as \"openai\", // Indicate this is a fallback\n fallbackReason: \"No embedding API available. Using BM25 full-text search only.\",\n };\n }\n\n try {\n const primary = await createProvider(requestedProvider);\n return { ...primary, requestedProvider };\n } catch (primaryErr) {\n const reason = formatPrimaryError(primaryErr, requestedProvider);\n if (fallback && fallback !== \"none\" && fallback !== requestedProvider) {\n try {\n const fallbackResult = await createProvider(fallback);\n return {\n ...fallbackResult,\n requestedProvider,\n fallbackFrom: requestedProvider,\n fallbackReason: reason,\n };\n } catch (fallbackErr) {\n throw new Error(`${reason}\\n\\nFallback to ${fallback} failed: ${formatError(fallbackErr)}`);\n }\n }\n throw new Error(reason);\n }\n}\n\nfunction formatError(err: unknown): string {\n if (err instanceof Error) return err.message;\n return String(err);\n}\n\nfunction isNodeLlamaCppMissing(err: unknown): boolean {\n if (!(err instanceof Error)) return false;\n const code = (err as Error & { code?: unknown }).code;\n if (code === \"ERR_MODULE_NOT_FOUND\") {\n return err.message.includes(\"node-llama-cpp\");\n }\n return false;\n}\n\nfunction formatLocalSetupError(err: unknown): string {\n const detail = formatError(err);\n const missing = isNodeLlamaCppMissing(err);\n return [\n \"Local embeddings unavailable.\",\n missing\n ? \"Reason: optional dependency node-llama-cpp is missing (or failed to install).\"\n : detail\n ? `Reason: ${detail}`\n : undefined,\n missing && detail ? `Detail: ${detail}` : null,\n \"To enable local embeddings:\",\n \"1) Use Node 22 LTS (recommended for installs/updates)\",\n missing ? \"2) Install node-llama-cpp: npm install node-llama-cpp\" : null,\n \"3) If you use pnpm: pnpm approve-builds (select node-llama-cpp), then pnpm rebuild node-llama-cpp\",\n 'Or set provider = \"openai\" or \"gemini\" (remote).',\n ]\n .filter(Boolean)\n .join(\"\\n\");\n}\n","import type { OpenAiEmbeddingClient } from \"./embeddings.js\";\nimport { hashText } from \"../internal.js\";\n\nexport type OpenAiBatchRequest = {\n custom_id: string;\n method: \"POST\";\n url: \"/v1/embeddings\";\n body: {\n model: string;\n input: string;\n };\n};\n\nexport type OpenAiBatchStatus = {\n id?: string;\n status?: string;\n output_file_id?: string | null;\n error_file_id?: string | null;\n};\n\nexport type OpenAiBatchOutputLine = {\n custom_id?: string;\n response?: {\n status_code?: number;\n body?: {\n data?: Array<{ embedding?: number[]; index?: number }>;\n error?: { message?: string };\n };\n };\n error?: { message?: string };\n};\n\nexport const OPENAI_BATCH_ENDPOINT = \"/v1/embeddings\";\nconst OPENAI_BATCH_COMPLETION_WINDOW = \"24h\";\nconst OPENAI_BATCH_MAX_REQUESTS = 50000;\n\nfunction getOpenAiBaseUrl(openAi: OpenAiEmbeddingClient): string {\n return openAi.baseUrl?.replace(/\\/$/, \"\") ?? \"\";\n}\n\nfunction getOpenAiHeaders(\n openAi: OpenAiEmbeddingClient,\n params: { json: boolean },\n): Record<string, string> {\n const headers = openAi.headers ? { ...openAi.headers } : {};\n if (params.json) {\n if (!headers[\"Content-Type\"] && !headers[\"content-type\"]) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n } else {\n delete headers[\"Content-Type\"];\n delete headers[\"content-type\"];\n }\n return headers;\n}\n\nfunction splitOpenAiBatchRequests(requests: OpenAiBatchRequest[]): OpenAiBatchRequest[][] {\n if (requests.length <= OPENAI_BATCH_MAX_REQUESTS) return [requests];\n const groups: OpenAiBatchRequest[][] = [];\n for (let i = 0; i < requests.length; i += OPENAI_BATCH_MAX_REQUESTS) {\n groups.push(requests.slice(i, i + OPENAI_BATCH_MAX_REQUESTS));\n }\n return groups;\n}\n\nasync function retryAsync<T>(\n fn: () => Promise<T>,\n opts: {\n attempts: number;\n minDelayMs: number;\n maxDelayMs: number;\n jitter: number;\n shouldRetry: (err: unknown) => boolean;\n },\n): Promise<T> {\n let lastError: unknown;\n for (let attempt = 0; attempt < opts.attempts; attempt++) {\n try {\n return await fn();\n } catch (err) {\n lastError = err;\n if (!opts.shouldRetry(err) || attempt === opts.attempts - 1) {\n throw err;\n }\n const delay = Math.min(\n opts.maxDelayMs,\n opts.minDelayMs * Math.pow(2, attempt) * (1 + Math.random() * opts.jitter),\n );\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n throw lastError;\n}\n\nasync function submitOpenAiBatch(params: {\n openAi: OpenAiEmbeddingClient;\n requests: OpenAiBatchRequest[];\n source: string;\n}): Promise<OpenAiBatchStatus> {\n const baseUrl = getOpenAiBaseUrl(params.openAi);\n const jsonl = params.requests.map((request) => JSON.stringify(request)).join(\"\\n\");\n const form = new FormData();\n form.append(\"purpose\", \"batch\");\n form.append(\n \"file\",\n new Blob([jsonl], { type: \"application/jsonl\" }),\n `memory-embeddings.${hashText(String(Date.now()))}.jsonl`,\n );\n\n const fileRes = await fetch(`${baseUrl}/files`, {\n method: \"POST\",\n headers: getOpenAiHeaders(params.openAi, { json: false }),\n body: form,\n });\n if (!fileRes.ok) {\n const text = await fileRes.text();\n throw new Error(`openai batch file upload failed: ${fileRes.status} ${text}`);\n }\n const filePayload = (await fileRes.json()) as { id?: string };\n if (!filePayload.id) {\n throw new Error(\"openai batch file upload failed: missing file id\");\n }\n\n const batchRes = await retryAsync(\n async () => {\n const res = await fetch(`${baseUrl}/batches`, {\n method: \"POST\",\n headers: getOpenAiHeaders(params.openAi, { json: true }),\n body: JSON.stringify({\n input_file_id: filePayload.id,\n endpoint: OPENAI_BATCH_ENDPOINT,\n completion_window: OPENAI_BATCH_COMPLETION_WINDOW,\n metadata: {\n source: params.source,\n },\n }),\n });\n if (!res.ok) {\n const text = await res.text();\n const err = new Error(`openai batch create failed: ${res.status} ${text}`) as Error & {\n status?: number;\n };\n err.status = res.status;\n throw err;\n }\n return res;\n },\n {\n attempts: 3,\n minDelayMs: 300,\n maxDelayMs: 2000,\n jitter: 0.2,\n shouldRetry: (err) => {\n const status = (err as { status?: number }).status;\n return status === 429 || (typeof status === \"number\" && status >= 500);\n },\n },\n );\n return (await batchRes.json()) as OpenAiBatchStatus;\n}\n\nasync function fetchOpenAiBatchStatus(params: {\n openAi: OpenAiEmbeddingClient;\n batchId: string;\n}): Promise<OpenAiBatchStatus> {\n const baseUrl = getOpenAiBaseUrl(params.openAi);\n const res = await fetch(`${baseUrl}/batches/${params.batchId}`, {\n headers: getOpenAiHeaders(params.openAi, { json: true }),\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`openai batch status failed: ${res.status} ${text}`);\n }\n return (await res.json()) as OpenAiBatchStatus;\n}\n\nasync function fetchOpenAiFileContent(params: {\n openAi: OpenAiEmbeddingClient;\n fileId: string;\n}): Promise<string> {\n const baseUrl = getOpenAiBaseUrl(params.openAi);\n const res = await fetch(`${baseUrl}/files/${params.fileId}/content`, {\n headers: getOpenAiHeaders(params.openAi, { json: true }),\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`openai batch file content failed: ${res.status} ${text}`);\n }\n return await res.text();\n}\n\nfunction parseOpenAiBatchOutput(text: string): OpenAiBatchOutputLine[] {\n if (!text.trim()) return [];\n return text\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter(Boolean)\n .map((line) => JSON.parse(line) as OpenAiBatchOutputLine);\n}\n\nasync function readOpenAiBatchError(params: {\n openAi: OpenAiEmbeddingClient;\n errorFileId: string;\n}): Promise<string | undefined> {\n try {\n const content = await fetchOpenAiFileContent({\n openAi: params.openAi,\n fileId: params.errorFileId,\n });\n const lines = parseOpenAiBatchOutput(content);\n const first = lines.find((line) => line.error?.message || line.response?.body?.error);\n const message =\n first?.error?.message ??\n (typeof first?.response?.body?.error?.message === \"string\"\n ? first?.response?.body?.error?.message\n : undefined);\n return message;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return message ? `error file unavailable: ${message}` : undefined;\n }\n}\n\nasync function waitForOpenAiBatch(params: {\n openAi: OpenAiEmbeddingClient;\n batchId: string;\n wait: boolean;\n pollIntervalMs: number;\n timeoutMs: number;\n debug?: (message: string, data?: Record<string, unknown>) => void;\n initial?: OpenAiBatchStatus;\n}): Promise<{ outputFileId: string; errorFileId?: string }> {\n const start = Date.now();\n let current: OpenAiBatchStatus | undefined = params.initial;\n while (true) {\n const status =\n current ??\n (await fetchOpenAiBatchStatus({\n openAi: params.openAi,\n batchId: params.batchId,\n }));\n const state = status.status ?? \"unknown\";\n if (state === \"completed\") {\n if (!status.output_file_id) {\n throw new Error(`openai batch ${params.batchId} completed without output file`);\n }\n return {\n outputFileId: status.output_file_id,\n errorFileId: status.error_file_id ?? undefined,\n };\n }\n if ([\"failed\", \"expired\", \"cancelled\", \"canceled\"].includes(state)) {\n const detail = status.error_file_id\n ? await readOpenAiBatchError({ openAi: params.openAi, errorFileId: status.error_file_id })\n : undefined;\n const suffix = detail ? `: ${detail}` : \"\";\n throw new Error(`openai batch ${params.batchId} ${state}${suffix}`);\n }\n if (!params.wait) {\n throw new Error(`openai batch ${params.batchId} still ${state}; wait disabled`);\n }\n if (Date.now() - start > params.timeoutMs) {\n throw new Error(`openai batch ${params.batchId} timed out after ${params.timeoutMs}ms`);\n }\n params.debug?.(`openai batch ${params.batchId} ${state}; waiting ${params.pollIntervalMs}ms`);\n await new Promise((resolve) => setTimeout(resolve, params.pollIntervalMs));\n current = undefined;\n }\n}\n\nasync function runWithConcurrency<T>(tasks: Array<() => Promise<T>>, limit: number): Promise<T[]> {\n if (tasks.length === 0) return [];\n const resolvedLimit = Math.max(1, Math.min(limit, tasks.length));\n const results: T[] = Array.from({ length: tasks.length });\n let next = 0;\n let firstError: unknown = null;\n\n const workers = Array.from({ length: resolvedLimit }, async () => {\n while (true) {\n if (firstError) return;\n const index = next;\n next += 1;\n if (index >= tasks.length) return;\n try {\n results[index] = await tasks[index]();\n } catch (err) {\n firstError = err;\n return;\n }\n }\n });\n\n await Promise.allSettled(workers);\n if (firstError) throw firstError;\n return results;\n}\n\nexport async function runOpenAiEmbeddingBatches(params: {\n openAi: OpenAiEmbeddingClient;\n source: string;\n requests: OpenAiBatchRequest[];\n wait: boolean;\n pollIntervalMs: number;\n timeoutMs: number;\n concurrency: number;\n debug?: (message: string, data?: Record<string, unknown>) => void;\n}): Promise<Map<string, number[]>> {\n if (params.requests.length === 0) return new Map();\n const groups = splitOpenAiBatchRequests(params.requests);\n const byCustomId = new Map<string, number[]>();\n\n const tasks = groups.map((group, groupIndex) => async () => {\n const batchInfo = await submitOpenAiBatch({\n openAi: params.openAi,\n requests: group,\n source: params.source,\n });\n if (!batchInfo.id) {\n throw new Error(\"openai batch create failed: missing batch id\");\n }\n\n params.debug?.(\"memory embeddings: openai batch created\", {\n batchId: batchInfo.id,\n status: batchInfo.status,\n group: groupIndex + 1,\n groups: groups.length,\n requests: group.length,\n });\n\n if (!params.wait && batchInfo.status !== \"completed\") {\n throw new Error(\n `openai batch ${batchInfo.id} submitted; enable batch.wait to await completion`,\n );\n }\n\n const completed =\n batchInfo.status === \"completed\"\n ? {\n outputFileId: batchInfo.output_file_id ?? \"\",\n errorFileId: batchInfo.error_file_id ?? undefined,\n }\n : await waitForOpenAiBatch({\n openAi: params.openAi,\n batchId: batchInfo.id,\n wait: params.wait,\n pollIntervalMs: params.pollIntervalMs,\n timeoutMs: params.timeoutMs,\n debug: params.debug,\n initial: batchInfo,\n });\n if (!completed.outputFileId) {\n throw new Error(`openai batch ${batchInfo.id} completed without output file`);\n }\n\n const content = await fetchOpenAiFileContent({\n openAi: params.openAi,\n fileId: completed.outputFileId,\n });\n const outputLines = parseOpenAiBatchOutput(content);\n const errors: string[] = [];\n const remaining = new Set(group.map((request) => request.custom_id));\n\n for (const line of outputLines) {\n const customId = line.custom_id;\n if (!customId) continue;\n remaining.delete(customId);\n if (line.error?.message) {\n errors.push(`${customId}: ${line.error.message}`);\n continue;\n }\n const response = line.response;\n const statusCode = response?.status_code ?? 0;\n if (statusCode >= 400) {\n const message =\n response?.body?.error?.message ??\n (typeof response?.body === \"string\" ? response.body : undefined) ??\n \"unknown error\";\n errors.push(`${customId}: ${message}`);\n continue;\n }\n const data = response?.body?.data ?? [];\n const embedding = data[0]?.embedding ?? [];\n if (embedding.length === 0) {\n errors.push(`${customId}: empty embedding`);\n continue;\n }\n byCustomId.set(customId, embedding);\n }\n\n if (errors.length > 0) {\n throw new Error(`openai batch ${batchInfo.id} failed: ${errors.join(\"; \")}`);\n }\n if (remaining.size > 0) {\n throw new Error(`openai batch ${batchInfo.id} missing ${remaining.size} embedding responses`);\n }\n });\n\n params.debug?.(\"memory embeddings: openai batch submit\", {\n requests: params.requests.length,\n groups: groups.length,\n wait: params.wait,\n concurrency: params.concurrency,\n pollIntervalMs: params.pollIntervalMs,\n timeoutMs: params.timeoutMs,\n });\n\n await runWithConcurrency(tasks, params.concurrency);\n return byCustomId;\n}\n","import type { GeminiEmbeddingClient } from \"./embeddings.js\";\nimport { hashText } from \"../internal.js\";\n\nexport type GeminiBatchRequest = {\n custom_id: string;\n content: { parts: Array<{ text: string }> };\n taskType: \"RETRIEVAL_DOCUMENT\" | \"RETRIEVAL_QUERY\";\n};\n\nexport type GeminiBatchStatus = {\n name?: string;\n state?: string;\n outputConfig?: { file?: string; fileId?: string };\n metadata?: {\n output?: {\n responsesFile?: string;\n };\n };\n error?: { message?: string };\n};\n\nexport type GeminiBatchOutputLine = {\n key?: string;\n custom_id?: string;\n request_id?: string;\n embedding?: { values?: number[] };\n response?: {\n embedding?: { values?: number[] };\n error?: { message?: string };\n };\n error?: { message?: string };\n};\n\nconst GEMINI_BATCH_MAX_REQUESTS = 50000;\n\nfunction getGeminiBaseUrl(gemini: GeminiEmbeddingClient): string {\n return gemini.baseUrl?.replace(/\\/$/, \"\") ?? \"\";\n}\n\nfunction getGeminiHeaders(\n gemini: GeminiEmbeddingClient,\n params: { json: boolean },\n): Record<string, string> {\n const headers = gemini.headers ? { ...gemini.headers } : {};\n if (params.json) {\n if (!headers[\"Content-Type\"] && !headers[\"content-type\"]) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n } else {\n delete headers[\"Content-Type\"];\n delete headers[\"content-type\"];\n }\n return headers;\n}\n\nfunction getGeminiUploadUrl(baseUrl: string): string {\n if (baseUrl.includes(\"/v1beta\")) {\n return baseUrl.replace(/\\/v1beta\\/?$/, \"/upload/v1beta\");\n }\n return `${baseUrl.replace(/\\/$/, \"\")}/upload`;\n}\n\nfunction splitGeminiBatchRequests(requests: GeminiBatchRequest[]): GeminiBatchRequest[][] {\n if (requests.length <= GEMINI_BATCH_MAX_REQUESTS) return [requests];\n const groups: GeminiBatchRequest[][] = [];\n for (let i = 0; i < requests.length; i += GEMINI_BATCH_MAX_REQUESTS) {\n groups.push(requests.slice(i, i + GEMINI_BATCH_MAX_REQUESTS));\n }\n return groups;\n}\n\nfunction buildGeminiUploadBody(params: { jsonl: string; displayName: string }): {\n body: Blob;\n contentType: string;\n} {\n const boundary = `minimem-${hashText(params.displayName)}`;\n const jsonPart = JSON.stringify({\n file: {\n displayName: params.displayName,\n mimeType: \"application/jsonl\",\n },\n });\n const delimiter = `--${boundary}\\r\\n`;\n const closeDelimiter = `--${boundary}--\\r\\n`;\n const parts = [\n `${delimiter}Content-Type: application/json; charset=UTF-8\\r\\n\\r\\n${jsonPart}\\r\\n`,\n `${delimiter}Content-Type: application/jsonl; charset=UTF-8\\r\\n\\r\\n${params.jsonl}\\r\\n`,\n closeDelimiter,\n ];\n const body = new Blob([parts.join(\"\")], { type: \"multipart/related\" });\n return {\n body,\n contentType: `multipart/related; boundary=${boundary}`,\n };\n}\n\nasync function submitGeminiBatch(params: {\n gemini: GeminiEmbeddingClient;\n requests: GeminiBatchRequest[];\n source: string;\n}): Promise<GeminiBatchStatus> {\n const baseUrl = getGeminiBaseUrl(params.gemini);\n const jsonl = params.requests\n .map((request) =>\n JSON.stringify({\n key: request.custom_id,\n request: {\n content: request.content,\n task_type: request.taskType,\n },\n }),\n )\n .join(\"\\n\");\n const displayName = `memory-embeddings-${hashText(String(Date.now()))}`;\n const uploadPayload = buildGeminiUploadBody({ jsonl, displayName });\n\n const uploadUrl = `${getGeminiUploadUrl(baseUrl)}/files?uploadType=multipart`;\n const fileRes = await fetch(uploadUrl, {\n method: \"POST\",\n headers: {\n ...getGeminiHeaders(params.gemini, { json: false }),\n \"Content-Type\": uploadPayload.contentType,\n },\n body: uploadPayload.body,\n });\n if (!fileRes.ok) {\n const text = await fileRes.text();\n throw new Error(`gemini batch file upload failed: ${fileRes.status} ${text}`);\n }\n const filePayload = (await fileRes.json()) as { name?: string; file?: { name?: string } };\n const fileId = filePayload.name ?? filePayload.file?.name;\n if (!fileId) {\n throw new Error(\"gemini batch file upload failed: missing file id\");\n }\n\n const batchBody = {\n batch: {\n displayName: `memory-embeddings-${params.source}`,\n inputConfig: {\n file_name: fileId,\n },\n },\n };\n\n const batchEndpoint = `${baseUrl}/${params.gemini.modelPath}:asyncBatchEmbedContent`;\n const batchRes = await fetch(batchEndpoint, {\n method: \"POST\",\n headers: getGeminiHeaders(params.gemini, { json: true }),\n body: JSON.stringify(batchBody),\n });\n if (batchRes.ok) {\n return (await batchRes.json()) as GeminiBatchStatus;\n }\n const text = await batchRes.text();\n if (batchRes.status === 404) {\n throw new Error(\n \"gemini batch create failed: 404 (asyncBatchEmbedContent not available for this model/baseUrl). Disable batch.enabled or switch providers.\",\n );\n }\n throw new Error(`gemini batch create failed: ${batchRes.status} ${text}`);\n}\n\nasync function fetchGeminiBatchStatus(params: {\n gemini: GeminiEmbeddingClient;\n batchName: string;\n}): Promise<GeminiBatchStatus> {\n const baseUrl = getGeminiBaseUrl(params.gemini);\n const name = params.batchName.startsWith(\"batches/\")\n ? params.batchName\n : `batches/${params.batchName}`;\n const statusUrl = `${baseUrl}/${name}`;\n const res = await fetch(statusUrl, {\n headers: getGeminiHeaders(params.gemini, { json: true }),\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`gemini batch status failed: ${res.status} ${text}`);\n }\n return (await res.json()) as GeminiBatchStatus;\n}\n\nasync function fetchGeminiFileContent(params: {\n gemini: GeminiEmbeddingClient;\n fileId: string;\n}): Promise<string> {\n const baseUrl = getGeminiBaseUrl(params.gemini);\n const file = params.fileId.startsWith(\"files/\") ? params.fileId : `files/${params.fileId}`;\n const downloadUrl = `${baseUrl}/${file}:download`;\n const res = await fetch(downloadUrl, {\n headers: getGeminiHeaders(params.gemini, { json: true }),\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`gemini batch file content failed: ${res.status} ${text}`);\n }\n return await res.text();\n}\n\nfunction parseGeminiBatchOutput(text: string): GeminiBatchOutputLine[] {\n if (!text.trim()) return [];\n return text\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter(Boolean)\n .map((line) => JSON.parse(line) as GeminiBatchOutputLine);\n}\n\nasync function waitForGeminiBatch(params: {\n gemini: GeminiEmbeddingClient;\n batchName: string;\n wait: boolean;\n pollIntervalMs: number;\n timeoutMs: number;\n debug?: (message: string, data?: Record<string, unknown>) => void;\n initial?: GeminiBatchStatus;\n}): Promise<{ outputFileId: string }> {\n const start = Date.now();\n let current: GeminiBatchStatus | undefined = params.initial;\n while (true) {\n const status =\n current ??\n (await fetchGeminiBatchStatus({\n gemini: params.gemini,\n batchName: params.batchName,\n }));\n const state = status.state ?? \"UNKNOWN\";\n if ([\"SUCCEEDED\", \"COMPLETED\", \"DONE\"].includes(state)) {\n const outputFileId =\n status.outputConfig?.file ??\n status.outputConfig?.fileId ??\n status.metadata?.output?.responsesFile;\n if (!outputFileId) {\n throw new Error(`gemini batch ${params.batchName} completed without output file`);\n }\n return { outputFileId };\n }\n if ([\"FAILED\", \"CANCELLED\", \"CANCELED\", \"EXPIRED\"].includes(state)) {\n const message = status.error?.message ?? \"unknown error\";\n throw new Error(`gemini batch ${params.batchName} ${state}: ${message}`);\n }\n if (!params.wait) {\n throw new Error(`gemini batch ${params.batchName} still ${state}; wait disabled`);\n }\n if (Date.now() - start > params.timeoutMs) {\n throw new Error(`gemini batch ${params.batchName} timed out after ${params.timeoutMs}ms`);\n }\n params.debug?.(`gemini batch ${params.batchName} ${state}; waiting ${params.pollIntervalMs}ms`);\n await new Promise((resolve) => setTimeout(resolve, params.pollIntervalMs));\n current = undefined;\n }\n}\n\nasync function runWithConcurrency<T>(tasks: Array<() => Promise<T>>, limit: number): Promise<T[]> {\n if (tasks.length === 0) return [];\n const resolvedLimit = Math.max(1, Math.min(limit, tasks.length));\n const results: T[] = Array.from({ length: tasks.length });\n let next = 0;\n let firstError: unknown = null;\n\n const workers = Array.from({ length: resolvedLimit }, async () => {\n while (true) {\n if (firstError) return;\n const index = next;\n next += 1;\n if (index >= tasks.length) return;\n try {\n results[index] = await tasks[index]();\n } catch (err) {\n firstError = err;\n return;\n }\n }\n });\n\n await Promise.allSettled(workers);\n if (firstError) throw firstError;\n return results;\n}\n\nexport async function runGeminiEmbeddingBatches(params: {\n gemini: GeminiEmbeddingClient;\n source: string;\n requests: GeminiBatchRequest[];\n wait: boolean;\n pollIntervalMs: number;\n timeoutMs: number;\n concurrency: number;\n debug?: (message: string, data?: Record<string, unknown>) => void;\n}): Promise<Map<string, number[]>> {\n if (params.requests.length === 0) return new Map();\n const groups = splitGeminiBatchRequests(params.requests);\n const byCustomId = new Map<string, number[]>();\n\n const tasks = groups.map((group, groupIndex) => async () => {\n const batchInfo = await submitGeminiBatch({\n gemini: params.gemini,\n requests: group,\n source: params.source,\n });\n const batchName = batchInfo.name ?? \"\";\n if (!batchName) {\n throw new Error(\"gemini batch create failed: missing batch name\");\n }\n\n params.debug?.(\"memory embeddings: gemini batch created\", {\n batchName,\n state: batchInfo.state,\n group: groupIndex + 1,\n groups: groups.length,\n requests: group.length,\n });\n\n if (\n !params.wait &&\n batchInfo.state &&\n ![\"SUCCEEDED\", \"COMPLETED\", \"DONE\"].includes(batchInfo.state)\n ) {\n throw new Error(\n `gemini batch ${batchName} submitted; enable batch.wait to await completion`,\n );\n }\n\n const completed =\n batchInfo.state && [\"SUCCEEDED\", \"COMPLETED\", \"DONE\"].includes(batchInfo.state)\n ? {\n outputFileId:\n batchInfo.outputConfig?.file ??\n batchInfo.outputConfig?.fileId ??\n batchInfo.metadata?.output?.responsesFile ??\n \"\",\n }\n : await waitForGeminiBatch({\n gemini: params.gemini,\n batchName,\n wait: params.wait,\n pollIntervalMs: params.pollIntervalMs,\n timeoutMs: params.timeoutMs,\n debug: params.debug,\n initial: batchInfo,\n });\n if (!completed.outputFileId) {\n throw new Error(`gemini batch ${batchName} completed without output file`);\n }\n\n const content = await fetchGeminiFileContent({\n gemini: params.gemini,\n fileId: completed.outputFileId,\n });\n const outputLines = parseGeminiBatchOutput(content);\n const errors: string[] = [];\n const remaining = new Set(group.map((request) => request.custom_id));\n\n for (const line of outputLines) {\n const customId = line.key ?? line.custom_id ?? line.request_id;\n if (!customId) continue;\n remaining.delete(customId);\n if (line.error?.message) {\n errors.push(`${customId}: ${line.error.message}`);\n continue;\n }\n if (line.response?.error?.message) {\n errors.push(`${customId}: ${line.response.error.message}`);\n continue;\n }\n const embedding = line.embedding?.values ?? line.response?.embedding?.values ?? [];\n if (embedding.length === 0) {\n errors.push(`${customId}: empty embedding`);\n continue;\n }\n byCustomId.set(customId, embedding);\n }\n\n if (errors.length > 0) {\n throw new Error(`gemini batch ${batchName} failed: ${errors.join(\"; \")}`);\n }\n if (remaining.size > 0) {\n throw new Error(`gemini batch ${batchName} missing ${remaining.size} embedding responses`);\n }\n });\n\n params.debug?.(\"memory embeddings: gemini batch submit\", {\n requests: params.requests.length,\n groups: groups.length,\n wait: params.wait,\n concurrency: params.concurrency,\n pollIntervalMs: params.pollIntervalMs,\n timeoutMs: params.timeoutMs,\n });\n\n await runWithConcurrency(tasks, params.concurrency);\n return byCustomId;\n}\n","/**\n * Tool definitions for memory operations\n *\n * These tools are compatible with:\n * - MCP (Model Context Protocol)\n * - Anthropic Claude tool use\n * - OpenAI function calling\n *\n * Note: Only memory_search is provided since the memory system is file-based.\n * Agents can use filesystem tools directly for read/write operations.\n */\n\nimport type { Minimem, MinimemSearchResult } from \"../minimem.js\";\n\n/**\n * JSON Schema for tool parameters (MCP/OpenAI/Anthropic compatible)\n */\nexport type ToolInputSchema = {\n type: \"object\";\n properties: Record<\n string,\n {\n type: string;\n description?: string;\n enum?: string[];\n items?: { type: string };\n default?: unknown;\n }\n >;\n required?: string[];\n};\n\n/**\n * Tool definition compatible with MCP, Anthropic, and OpenAI\n */\nexport type ToolDefinition = {\n name: string;\n description: string;\n inputSchema: ToolInputSchema;\n};\n\n/**\n * Tool execution result\n */\nexport type ToolResult = {\n content: Array<{ type: \"text\"; text: string }>;\n isError?: boolean;\n};\n\n/**\n * Memory search tool parameters\n */\nexport type MemorySearchParams = {\n query: string;\n maxResults?: number;\n minScore?: number;\n directories?: string[];\n};\n\n/**\n * Search result with source directory\n */\ntype SearchResultWithSource = MinimemSearchResult & {\n memoryDir: string;\n};\n\nexport const MEMORY_SEARCH_TOOL: ToolDefinition = {\n name: \"memory_search\",\n description:\n \"Semantically search through memory files (MEMORY.md and memory/*.md). \" +\n \"Use this to recall prior decisions, facts, preferences, people, dates, or context. \" +\n \"Returns ranked snippets with file paths and line numbers. \" +\n \"When multiple memory directories are configured, searches all by default.\",\n inputSchema: {\n type: \"object\",\n properties: {\n query: {\n type: \"string\",\n description: \"Natural language search query\",\n },\n maxResults: {\n type: \"number\",\n description: \"Maximum number of results to return (default: 10)\",\n },\n minScore: {\n type: \"number\",\n description: \"Minimum relevance score threshold 0-1 (default: 0.3)\",\n },\n directories: {\n type: \"array\",\n items: { type: \"string\" },\n description:\n \"Optional: filter to specific memory directories by name/path. \" +\n \"If omitted, searches all configured directories.\",\n },\n },\n required: [\"query\"],\n },\n};\n\n/**\n * All available memory tools\n */\nexport const MEMORY_TOOLS: ToolDefinition[] = [MEMORY_SEARCH_TOOL];\n\n/**\n * Get tool definitions for use with LLM APIs\n */\nexport function getToolDefinitions(): ToolDefinition[] {\n return MEMORY_TOOLS;\n}\n\n/**\n * Memory instance with its directory path\n */\nexport type MemoryInstance = {\n minimem: Minimem;\n memoryDir: string;\n name?: string;\n};\n\n/**\n * Tool executor that handles memory search across multiple directories\n */\nexport class MemoryToolExecutor {\n private instances: MemoryInstance[];\n\n constructor(instances: Minimem | MemoryInstance | MemoryInstance[]) {\n // Normalize to array of MemoryInstance\n if (Array.isArray(instances)) {\n this.instances = instances;\n } else if (\"minimem\" in instances) {\n this.instances = [instances];\n } else {\n // Legacy: single Minimem instance without directory info\n this.instances = [{ minimem: instances, memoryDir: \"default\" }];\n }\n }\n\n /**\n * Get list of configured directory names/paths\n */\n getDirectories(): string[] {\n return this.instances.map((i) => i.name ?? i.memoryDir);\n }\n\n /**\n * Execute a tool by name with given parameters\n */\n async execute(\n toolName: string,\n params: Record<string, unknown>,\n ): Promise<ToolResult> {\n try {\n switch (toolName) {\n case \"memory_search\":\n return await this.memorySearch(params as MemorySearchParams);\n default:\n return {\n content: [{ type: \"text\", text: `Unknown tool: ${toolName}` }],\n isError: true,\n };\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n content: [{ type: \"text\", text: `Error: ${message}` }],\n isError: true,\n };\n }\n }\n\n private async memorySearch(params: MemorySearchParams): Promise<ToolResult> {\n const maxResults = params.maxResults ?? 10;\n const minScore = params.minScore;\n\n // Filter instances by directories param if provided\n let instancesToSearch = this.instances;\n if (params.directories && params.directories.length > 0) {\n const dirFilter = new Set(params.directories.map((d) => d.toLowerCase()));\n instancesToSearch = this.instances.filter((i) => {\n const name = (i.name ?? i.memoryDir).toLowerCase();\n const dir = i.memoryDir.toLowerCase();\n return (\n dirFilter.has(name) ||\n dirFilter.has(dir) ||\n // Also match partial paths\n [...dirFilter].some((f) => dir.includes(f) || name.includes(f))\n );\n });\n\n if (instancesToSearch.length === 0) {\n const available = this.getDirectories().join(\", \");\n return {\n content: [\n {\n type: \"text\",\n text: `No matching directories found. Available: ${available}`,\n },\n ],\n isError: true,\n };\n }\n }\n\n // Search all matching instances\n const allResults: SearchResultWithSource[] = [];\n\n for (const instance of instancesToSearch) {\n // Get more results per directory, then merge and trim\n const perDirMax = Math.ceil(maxResults * 1.5);\n const results = await instance.minimem.search(params.query, {\n maxResults: perDirMax,\n minScore,\n });\n\n for (const result of results) {\n allResults.push({\n ...result,\n memoryDir: instance.name ?? instance.memoryDir,\n });\n }\n }\n\n // Sort by score and limit\n allResults.sort((a, b) => b.score - a.score);\n const topResults = allResults.slice(0, maxResults);\n\n if (topResults.length === 0) {\n return {\n content: [{ type: \"text\", text: \"No results found.\" }],\n };\n }\n\n // Format results\n const showSource = instancesToSearch.length > 1;\n const formatted = topResults\n .map((r, i) => {\n const location = `${r.path}:${r.startLine}-${r.endLine}`;\n const score = (r.score * 100).toFixed(1);\n const source = showSource ? ` [${r.memoryDir}]` : \"\";\n return `[${i + 1}] ${location}${source} (${score}% match)\\n${r.snippet}`;\n })\n .join(\"\\n\\n\");\n\n const dirSummary =\n instancesToSearch.length > 1\n ? `\\n\\n(Searched ${instancesToSearch.length} directories)`\n : \"\";\n\n return {\n content: [{ type: \"text\", text: formatted + dirSummary }],\n };\n }\n}\n\n/**\n * Create a tool executor for the given Minimem instance(s)\n */\nexport function createToolExecutor(\n instances: Minimem | MemoryInstance | MemoryInstance[],\n): MemoryToolExecutor {\n return new MemoryToolExecutor(instances);\n}\n","/**\n * MCP (Model Context Protocol) Server for Minimem\n *\n * Provides memory tools via JSON-RPC 2.0 over stdio.\n * Compatible with Claude Desktop, Cursor, and other MCP clients.\n *\n * Usage:\n * import { Minimem } from \"minimem\";\n * import { createMcpServer, runMcpServer } from \"minimem/mcp\";\n *\n * const minimem = await Minimem.create({ ... });\n * const server = createMcpServer(minimem);\n * await runMcpServer(server); // Runs over stdio\n */\n\nimport * as readline from \"node:readline\";\nimport type { Minimem } from \"../minimem.js\";\nimport {\n MEMORY_TOOLS,\n type ToolDefinition,\n type ToolResult,\n type MemoryInstance,\n MemoryToolExecutor,\n} from \"./tools.js\";\n\nconst PROTOCOL_VERSION = \"2024-11-05\";\nconst SERVER_NAME = \"minimem\";\nconst SERVER_VERSION = \"0.1.0\";\n\n/**\n * JSON-RPC 2.0 request\n */\ntype JsonRpcRequest = {\n jsonrpc: \"2.0\";\n id: string | number;\n method: string;\n params?: Record<string, unknown>;\n};\n\n/**\n * JSON-RPC 2.0 response\n */\ntype JsonRpcResponse = {\n jsonrpc: \"2.0\";\n id: string | number | null;\n result?: unknown;\n error?: {\n code: number;\n message: string;\n data?: unknown;\n };\n};\n\n/**\n * JSON-RPC 2.0 notification (no id)\n */\ntype JsonRpcNotification = {\n jsonrpc: \"2.0\";\n method: string;\n params?: Record<string, unknown>;\n};\n\n/**\n * MCP Server capabilities\n */\ntype ServerCapabilities = {\n tools?: {\n listChanged?: boolean;\n };\n};\n\n/**\n * MCP Server info\n */\ntype ServerInfo = {\n name: string;\n version: string;\n};\n\n/**\n * MCP Initialize result\n */\ntype InitializeResult = {\n protocolVersion: string;\n capabilities: ServerCapabilities;\n serverInfo: ServerInfo;\n};\n\n/**\n * MCP Tool in list format\n */\ntype McpTool = {\n name: string;\n description: string;\n inputSchema: {\n type: \"object\";\n properties: Record<string, unknown>;\n required?: string[];\n };\n};\n\n/**\n * MCP Server implementation\n */\nexport class McpServer {\n private executor: MemoryToolExecutor;\n private initialized = false;\n\n constructor(instances: Minimem | MemoryInstance | MemoryInstance[]) {\n this.executor = new MemoryToolExecutor(instances);\n }\n\n /**\n * Handle a JSON-RPC request and return a response\n */\n async handleRequest(request: JsonRpcRequest): Promise<JsonRpcResponse> {\n try {\n const result = await this.dispatch(request.method, request.params);\n return {\n jsonrpc: \"2.0\",\n id: request.id,\n result,\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n const code = err instanceof McpError ? err.code : -32603;\n return {\n jsonrpc: \"2.0\",\n id: request.id,\n error: { code, message },\n };\n }\n }\n\n /**\n * Dispatch a method call\n */\n private async dispatch(\n method: string,\n params?: Record<string, unknown>,\n ): Promise<unknown> {\n switch (method) {\n case \"initialize\":\n return this.initialize(params);\n case \"initialized\":\n // Notification, no response needed\n return {};\n case \"tools/list\":\n return this.listTools();\n case \"tools/call\":\n return this.callTool(params);\n case \"ping\":\n return {};\n default:\n throw new McpError(-32601, `Method not found: ${method}`);\n }\n }\n\n /**\n * Handle initialize request\n */\n private initialize(\n params?: Record<string, unknown>,\n ): InitializeResult {\n this.initialized = true;\n return {\n protocolVersion: PROTOCOL_VERSION,\n capabilities: {\n tools: {\n listChanged: false,\n },\n },\n serverInfo: {\n name: SERVER_NAME,\n version: SERVER_VERSION,\n },\n };\n }\n\n /**\n * List available tools\n */\n private listTools(): { tools: McpTool[] } {\n const tools: McpTool[] = MEMORY_TOOLS.map((tool) => ({\n name: tool.name,\n description: tool.description,\n inputSchema: tool.inputSchema,\n }));\n return { tools };\n }\n\n /**\n * Call a tool\n */\n private async callTool(\n params?: Record<string, unknown>,\n ): Promise<{ content: Array<{ type: string; text: string }>; isError?: boolean }> {\n if (!params?.name || typeof params.name !== \"string\") {\n throw new McpError(-32602, \"Missing tool name\");\n }\n\n const toolName = params.name;\n const toolParams = (params.arguments ?? {}) as Record<string, unknown>;\n\n const result = await this.executor.execute(toolName, toolParams);\n return result;\n }\n}\n\n/**\n * Custom error class for MCP errors\n */\nclass McpError extends Error {\n constructor(\n public code: number,\n message: string,\n ) {\n super(message);\n this.name = \"McpError\";\n }\n}\n\n/**\n * Create an MCP server for the given Minimem instance(s)\n */\nexport function createMcpServer(\n instances: Minimem | MemoryInstance | MemoryInstance[],\n): McpServer {\n return new McpServer(instances);\n}\n\n/**\n * Run the MCP server over stdio\n */\nexport async function runMcpServer(server: McpServer): Promise<void> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n terminal: false,\n });\n\n const send = (message: JsonRpcResponse | JsonRpcNotification) => {\n const json = JSON.stringify(message);\n process.stdout.write(json + \"\\n\");\n };\n\n rl.on(\"line\", async (line) => {\n if (!line.trim()) return;\n\n try {\n const request = JSON.parse(line) as JsonRpcRequest;\n\n if (request.jsonrpc !== \"2.0\") {\n send({\n jsonrpc: \"2.0\",\n id: request.id ?? null,\n error: { code: -32600, message: \"Invalid JSON-RPC version\" },\n });\n return;\n }\n\n // Handle notification (no id)\n if (request.id === undefined) {\n await server.handleRequest({ ...request, id: 0 });\n return;\n }\n\n const response = await server.handleRequest(request);\n send(response);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n send({\n jsonrpc: \"2.0\",\n id: null,\n error: { code: -32700, message: `Parse error: ${message}` },\n });\n }\n });\n\n rl.on(\"close\", () => {\n process.exit(0);\n });\n\n // Keep the process alive\n await new Promise(() => {});\n}\n\n/**\n * MCP server configuration for claude_desktop_config.json\n *\n * Example:\n * {\n * \"mcpServers\": {\n * \"minimem\": {\n * \"command\": \"node\",\n * \"args\": [\"path/to/your/mcp-server.js\"],\n * \"env\": {\n * \"MEMORY_DIR\": \"/path/to/memory\"\n * }\n * }\n * }\n * }\n */\nexport type McpServerConfig = {\n command: string;\n args: string[];\n env?: Record<string, string>;\n};\n\n/**\n * Generate MCP server config for Claude Desktop\n */\nexport function generateMcpConfig(opts: {\n serverPath: string;\n memoryDir: string;\n embeddingProvider?: \"openai\" | \"gemini\" | \"local\" | \"auto\";\n}): McpServerConfig {\n return {\n command: \"node\",\n args: [opts.serverPath],\n env: {\n MEMORY_DIR: opts.memoryDir,\n ...(opts.embeddingProvider ? { EMBEDDING_PROVIDER: opts.embeddingProvider } : {}),\n },\n };\n}\n","/**\n * Session tracking for memory entries\n *\n * Captures context about the originating session (Claude Code, VS Code, etc.)\n * and stores it as YAML frontmatter in memory files.\n */\n\nimport * as os from \"node:os\";\n\n/**\n * Session metadata for memory entries\n */\nexport type SessionContext = {\n /** Session identifier (e.g., Claude Code session ID) */\n id?: string;\n /** Source application (claude-code, vscode, cursor, etc.) */\n source?: string;\n /** Project directory path */\n project?: string;\n /** Path to session transcript/log file */\n transcript?: string;\n};\n\n/**\n * Frontmatter structure for memory files\n */\nexport type MemoryFrontmatter = {\n session?: SessionContext;\n created?: string;\n updated?: string;\n tags?: string[];\n};\n\n/**\n * Parse YAML frontmatter from content\n *\n * Frontmatter is delimited by --- at the start and end:\n * ```\n * ---\n * session:\n * id: abc123\n * source: claude-code\n * created: 2024-01-27T14:30:00Z\n * ---\n * Actual content here...\n * ```\n */\nexport function parseFrontmatter(content: string): {\n frontmatter: MemoryFrontmatter | undefined;\n body: string;\n} {\n const frontmatterRegex = /^---\\n([\\s\\S]*?)\\n---\\n/;\n const match = content.match(frontmatterRegex);\n\n if (!match) {\n return { frontmatter: undefined, body: content };\n }\n\n const yamlContent = match[1];\n const body = content.slice(match[0].length);\n\n try {\n const frontmatter = parseSimpleYaml(yamlContent);\n return { frontmatter, body };\n } catch {\n // If parsing fails, treat as no frontmatter\n return { frontmatter: undefined, body: content };\n }\n}\n\n/**\n * Simple YAML parser for frontmatter\n * Handles basic key-value pairs and nested objects\n */\nfunction parseSimpleYaml(yaml: string): MemoryFrontmatter {\n const result: MemoryFrontmatter = {};\n const lines = yaml.split(\"\\n\");\n let currentKey: string | null = null;\n let currentObject: Record<string, unknown> | null = null;\n\n for (const line of lines) {\n // Skip empty lines\n if (!line.trim()) continue;\n\n // Check indentation level\n const indentMatch = line.match(/^(\\s*)/);\n const indent = indentMatch ? indentMatch[1].length : 0;\n\n // Top-level key\n if (indent === 0) {\n const keyMatch = line.match(/^(\\w+):\\s*(.*)?$/);\n if (keyMatch) {\n const [, key, value] = keyMatch;\n if (value && value.trim()) {\n // Simple key: value\n (result as Record<string, unknown>)[key] = parseYamlValue(value.trim());\n currentKey = null;\n currentObject = null;\n } else {\n // Object start\n currentKey = key;\n currentObject = {};\n (result as Record<string, unknown>)[key] = currentObject;\n }\n }\n } else if (currentObject && indent >= 2) {\n // Nested key\n const nestedMatch = line.match(/^\\s+(\\w+):\\s*(.*)$/);\n if (nestedMatch) {\n const [, key, value] = nestedMatch;\n currentObject[key] = parseYamlValue(value.trim());\n }\n }\n }\n\n return result;\n}\n\n/**\n * Parse a YAML value (handles strings, numbers, booleans, arrays)\n */\nfunction parseYamlValue(value: string): unknown {\n // Remove quotes if present\n if ((value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))) {\n return value.slice(1, -1);\n }\n\n // Boolean\n if (value === \"true\") return true;\n if (value === \"false\") return false;\n\n // Number\n const num = Number(value);\n if (!isNaN(num) && value !== \"\") return num;\n\n // Array (simple inline format)\n if (value.startsWith(\"[\") && value.endsWith(\"]\")) {\n const inner = value.slice(1, -1);\n return inner.split(\",\").map((s) => parseYamlValue(s.trim()));\n }\n\n // String\n return value;\n}\n\n/**\n * Serialize frontmatter to YAML string\n */\nexport function serializeFrontmatter(frontmatter: MemoryFrontmatter): string {\n const lines: string[] = [\"---\"];\n\n if (frontmatter.session) {\n lines.push(\"session:\");\n const session = frontmatter.session;\n if (session.id) lines.push(` id: ${session.id}`);\n if (session.source) lines.push(` source: ${session.source}`);\n if (session.project) lines.push(` project: ${formatPath(session.project)}`);\n if (session.transcript) lines.push(` transcript: ${formatPath(session.transcript)}`);\n }\n\n if (frontmatter.created) {\n lines.push(`created: ${frontmatter.created}`);\n }\n\n if (frontmatter.updated) {\n lines.push(`updated: ${frontmatter.updated}`);\n }\n\n if (frontmatter.tags && frontmatter.tags.length > 0) {\n lines.push(`tags: [${frontmatter.tags.join(\", \")}]`);\n }\n\n lines.push(\"---\");\n return lines.join(\"\\n\") + \"\\n\";\n}\n\n/**\n * Add or update frontmatter in content\n */\nexport function addFrontmatter(\n content: string,\n frontmatter: MemoryFrontmatter,\n): string {\n const { frontmatter: existing, body } = parseFrontmatter(content);\n\n // Merge with existing frontmatter\n const merged: MemoryFrontmatter = {\n ...existing,\n ...frontmatter,\n session: {\n ...existing?.session,\n ...frontmatter.session,\n },\n };\n\n // Update timestamp\n if (!merged.created) {\n merged.created = new Date().toISOString();\n }\n merged.updated = new Date().toISOString();\n\n return serializeFrontmatter(merged) + body;\n}\n\n/**\n * Add session context as frontmatter to content\n */\nexport function addSessionToContent(\n content: string,\n session: SessionContext,\n): string {\n return addFrontmatter(content, { session });\n}\n\n/**\n * Format path for display (use ~ for home directory)\n */\nfunction formatPath(filePath: string): string {\n const home = os.homedir();\n if (filePath.startsWith(home)) {\n return \"~\" + filePath.slice(home.length);\n }\n return filePath;\n}\n\n/**\n * Extract session context from file content\n */\nexport function extractSession(content: string): SessionContext | undefined {\n const { frontmatter } = parseFrontmatter(content);\n return frontmatter?.session;\n}\n"],"mappings":"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","names":["fs","path","fsSync","path","payload","provider","client","text","runWithConcurrency","vectorToBlob","path","fs","os"]}
|
|
1
|
+
{"version":3,"sources":["../src/minimem.ts","../src/search/hybrid.ts","../src/search/search.ts","../src/db/schema.ts","../src/search/graph.ts","../src/db/sqlite-vec.ts","../src/embeddings/embeddings.ts","../src/embeddings/batch-openai.ts","../src/embeddings/batch-gemini.ts","../src/server/tools.ts","../src/server/mcp.ts","../src/core/indexer.ts","../src/core/searcher.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { DatabaseSync } from \"node:sqlite\";\nimport chokidar, { type FSWatcher } from \"chokidar\";\n\nimport {\n buildFileEntry,\n chunkMarkdown,\n ensureDir,\n extractChunkMetadata,\n hashText,\n listMemoryFiles,\n logError,\n type MemoryChunk,\n type MemoryFileEntry,\n parseEmbedding,\n vectorToBlob,\n} from \"./internal.js\";\nimport { bm25RankToScore, buildFtsQuery, mergeHybridResults } from \"./search/hybrid.js\";\nimport { searchKeyword, searchVector, buildKnowledgeFilterSql } from \"./search/search.js\";\nimport { ensureMemoryIndexSchema } from \"./db/schema.js\";\nimport { parseFrontmatter, type MemoryFrontmatter, type KnowledgeLink } from \"./session.js\";\nimport {\n getLinksFrom,\n getLinksTo,\n getNeighbors,\n getPathBetween,\n type GraphLink,\n type GraphNeighbor,\n} from \"./search/graph.js\";\nimport { loadSqliteVecExtension } from \"./db/sqlite-vec.js\";\nimport {\n createEmbeddingProvider,\n type EmbeddingProvider,\n type EmbeddingProviderOptions,\n type OpenAiEmbeddingClient,\n type GeminiEmbeddingClient,\n} from \"./embeddings/embeddings.js\";\nimport { runOpenAiEmbeddingBatches, type OpenAiBatchRequest, OPENAI_BATCH_ENDPOINT } from \"./embeddings/batch-openai.js\";\nimport { runGeminiEmbeddingBatches, type GeminiBatchRequest } from \"./embeddings/batch-gemini.js\";\n\nconst META_KEY = \"memory_index_meta_v1\";\nconst SNIPPET_MAX_CHARS = 700;\nconst VECTOR_TABLE = \"chunks_vec\";\nconst FTS_TABLE = \"chunks_fts\";\nconst EMBEDDING_CACHE_TABLE = \"embedding_cache\";\nconst EMBEDDING_BATCH_MAX_TOKENS = 8000;\nconst EMBEDDING_APPROX_CHARS_PER_TOKEN = 1;\nconst EMBEDDING_INDEX_CONCURRENCY = 4;\nconst EMBEDDING_RETRY_MAX_ATTEMPTS = 3;\nconst EMBEDDING_RETRY_BASE_DELAY_MS = 500;\nconst EMBEDDING_RETRY_MAX_DELAY_MS = 8000;\nconst VECTOR_LOAD_TIMEOUT_MS = 30_000;\nconst EMBEDDING_QUERY_TIMEOUT_REMOTE_MS = 60_000;\nconst EMBEDDING_QUERY_TIMEOUT_LOCAL_MS = 5 * 60_000;\n\nexport type MinimemConfig = {\n /** Directory containing memory files (MEMORY.md, memory/*.md) */\n memoryDir: string;\n /** Path to SQLite database. Defaults to memoryDir/.minimem/index.db */\n dbPath?: string;\n /** Embedding provider options */\n embedding: EmbeddingProviderOptions;\n /** Chunking configuration */\n chunking?: {\n /** Tokens per chunk (default: 256) */\n tokens?: number;\n /** Overlap tokens between chunks (default: 32) */\n overlap?: number;\n };\n /** Embedding cache configuration */\n cache?: {\n /** Enable embedding cache (default: true) */\n enabled?: boolean;\n /** Max cache entries before LRU pruning (default: 10000) */\n maxEntries?: number;\n };\n /** Hybrid search configuration */\n hybrid?: {\n /** Enable hybrid search (default: true) */\n enabled?: boolean;\n /** Weight for vector search (default: 0.7) */\n vectorWeight?: number;\n /** Weight for keyword search (default: 0.3) */\n textWeight?: number;\n /** Candidate multiplier for search (default: 2.0) */\n candidateMultiplier?: number;\n };\n /** Query configuration */\n query?: {\n /** Max results (default: 10) */\n maxResults?: number;\n /** Min score threshold (default: 0.3) */\n minScore?: number;\n };\n /** File watching configuration */\n watch?: {\n /** Enable file watching (default: true) */\n enabled?: boolean;\n /** Debounce delay in ms (default: 1000) */\n debounceMs?: number;\n };\n /** Batch embedding configuration */\n batch?: {\n /** Enable batch embedding API (default: false) */\n enabled?: boolean;\n /** Wait for batch completion (default: true) */\n wait?: boolean;\n /** Concurrent batch requests (default: 2) */\n concurrency?: number;\n /** Poll interval in ms (default: 2000) */\n pollIntervalMs?: number;\n /** Timeout in ms (default: 60 minutes) */\n timeoutMs?: number;\n };\n /** sqlite-vec extension path (optional) */\n vectorExtensionPath?: string;\n /** Debug logging function */\n debug?: (message: string, data?: Record<string, unknown>) => void;\n};\n\nexport type MinimemSearchResult = {\n path: string;\n startLine: number;\n endLine: number;\n score: number;\n snippet: string;\n};\n\ntype MemoryIndexMeta = {\n model: string;\n provider: string;\n providerKey?: string;\n chunkTokens: number;\n chunkOverlap: number;\n vectorDims?: number;\n};\n\nexport class Minimem {\n private readonly memoryDir: string;\n private readonly dbPath: string;\n private readonly chunking: { tokens: number; overlap: number };\n private readonly cache: { enabled: boolean; maxEntries: number };\n private readonly hybrid: {\n enabled: boolean;\n vectorWeight: number;\n textWeight: number;\n candidateMultiplier: number;\n };\n private readonly queryConfig: { maxResults: number; minScore: number };\n private readonly watchConfig: { enabled: boolean; debounceMs: number };\n private readonly batchConfig: {\n enabled: boolean;\n wait: boolean;\n concurrency: number;\n pollIntervalMs: number;\n timeoutMs: number;\n };\n private readonly vectorExtensionPath?: string;\n private readonly debug?: (message: string, data?: Record<string, unknown>) => void;\n\n private provider!: EmbeddingProvider;\n private openAi?: OpenAiEmbeddingClient;\n private gemini?: GeminiEmbeddingClient;\n private providerKey: string = \"\";\n private providerFallbackReason?: string;\n private db!: DatabaseSync;\n\n private readonly vector: {\n enabled: boolean;\n available: boolean | null;\n extensionPath?: string;\n loadError?: string;\n dims?: number;\n };\n private readonly fts: {\n enabled: boolean;\n available: boolean;\n loadError?: string;\n };\n\n private vectorReady: Promise<boolean> | null = null;\n private watcher: FSWatcher | null = null;\n private watchTimer: NodeJS.Timeout | null = null;\n private closed = false;\n private dirty = true;\n private syncing: Promise<void> | null = null;\n private syncLock = false;\n private embeddingOptions: EmbeddingProviderOptions;\n\n private constructor(config: MinimemConfig) {\n this.memoryDir = path.resolve(config.memoryDir);\n this.dbPath = config.dbPath ?? path.join(this.memoryDir, \".minimem\", \"index.db\");\n this.chunking = {\n tokens: config.chunking?.tokens ?? 256,\n overlap: config.chunking?.overlap ?? 32,\n };\n this.cache = {\n enabled: config.cache?.enabled ?? true,\n maxEntries: config.cache?.maxEntries ?? 10000,\n };\n this.hybrid = {\n enabled: config.hybrid?.enabled ?? true,\n vectorWeight: config.hybrid?.vectorWeight ?? 0.7,\n textWeight: config.hybrid?.textWeight ?? 0.3,\n candidateMultiplier: config.hybrid?.candidateMultiplier ?? 2.0,\n };\n this.queryConfig = {\n maxResults: config.query?.maxResults ?? 10,\n minScore: config.query?.minScore ?? 0.3,\n };\n this.watchConfig = {\n enabled: config.watch?.enabled ?? true,\n debounceMs: config.watch?.debounceMs ?? 1000,\n };\n this.batchConfig = {\n enabled: config.batch?.enabled ?? false,\n wait: config.batch?.wait ?? true,\n concurrency: config.batch?.concurrency ?? 2,\n pollIntervalMs: config.batch?.pollIntervalMs ?? 2000,\n timeoutMs: config.batch?.timeoutMs ?? 60 * 60 * 1000,\n };\n this.vectorExtensionPath = config.vectorExtensionPath;\n this.debug = config.debug;\n this.embeddingOptions = config.embedding;\n\n this.vector = {\n enabled: true,\n available: null,\n extensionPath: this.vectorExtensionPath,\n };\n this.fts = { enabled: this.hybrid.enabled, available: false };\n }\n\n static async create(config: MinimemConfig): Promise<Minimem> {\n const instance = new Minimem(config);\n await instance.initialize();\n return instance;\n }\n\n private async initialize(): Promise<void> {\n // Create embedding provider\n const providerResult = await createEmbeddingProvider(this.embeddingOptions);\n this.provider = providerResult.provider;\n this.openAi = providerResult.openAi;\n this.gemini = providerResult.gemini;\n this.providerKey = this.computeProviderKey();\n this.providerFallbackReason = providerResult.fallbackReason;\n\n // Log warning if in BM25-only fallback mode\n if (this.provider.id === \"none\") {\n this.debug?.(\"Running in BM25-only mode (no embedding API available)\");\n }\n\n // Open database\n this.db = this.openDatabase();\n this.ensureSchema();\n\n // Check for existing vector dims\n const meta = this.readMeta();\n if (meta?.vectorDims) {\n this.vector.dims = meta.vectorDims;\n }\n\n // Start file watcher\n if (this.watchConfig.enabled) {\n this.ensureWatcher();\n }\n }\n\n private openDatabase(): DatabaseSync {\n const dbDir = path.dirname(this.dbPath);\n ensureDir(dbDir);\n return new DatabaseSync(this.dbPath);\n }\n\n private ensureSchema(): void {\n const result = ensureMemoryIndexSchema({\n db: this.db,\n embeddingCacheTable: EMBEDDING_CACHE_TABLE,\n ftsTable: FTS_TABLE,\n ftsEnabled: this.fts.enabled,\n });\n this.fts.available = result.ftsAvailable;\n if (result.ftsError) {\n this.fts.loadError = result.ftsError;\n }\n }\n\n private computeProviderKey(): string {\n const parts: string[] = [this.provider.id, this.provider.model];\n if (this.openAi) {\n parts.push(this.openAi.baseUrl);\n }\n if (this.gemini) {\n parts.push(this.gemini.baseUrl);\n }\n return hashText(parts.join(\":\"));\n }\n\n private readMeta(): MemoryIndexMeta | null {\n try {\n const row = this.db.prepare(`SELECT value FROM meta WHERE key = ?`).get(META_KEY) as\n | { value: string }\n | undefined;\n if (!row?.value) return null;\n return JSON.parse(row.value) as MemoryIndexMeta;\n } catch {\n return null;\n }\n }\n\n private writeMeta(meta: MemoryIndexMeta): void {\n this.db\n .prepare(`INSERT OR REPLACE INTO meta (key, value) VALUES (?, ?)`)\n .run(META_KEY, JSON.stringify(meta));\n }\n\n private ensureWatcher(): void {\n if (this.watcher) return;\n const memorySubDir = path.join(this.memoryDir, \"memory\");\n const memoryFile = path.join(this.memoryDir, \"MEMORY.md\");\n\n this.watcher = chokidar.watch([memoryFile, memorySubDir], {\n ignoreInitial: true,\n persistent: true,\n awaitWriteFinish: { stabilityThreshold: 200, pollInterval: 50 },\n });\n\n const scheduleSync = () => {\n this.dirty = true;\n if (this.watchTimer) clearTimeout(this.watchTimer);\n this.watchTimer = setTimeout(() => {\n void this.sync({ reason: \"watch\" }).catch((err) => {\n this.debug?.(`memory sync failed (watch): ${String(err)}`);\n });\n }, this.watchConfig.debounceMs);\n };\n\n this.watcher.on(\"add\", scheduleSync);\n this.watcher.on(\"change\", scheduleSync);\n this.watcher.on(\"unlink\", scheduleSync);\n }\n\n /**\n * Check if the index is stale by comparing file mtimes against stored values.\n * This is a lightweight check (stat calls only, no file reads).\n */\n private async isStale(): Promise<boolean> {\n try {\n const files = await listMemoryFiles(this.memoryDir);\n\n // Get stored file records\n const stored = this.db\n .prepare(`SELECT path, mtime FROM files WHERE source = ?`)\n .all(\"memory\") as Array<{ path: string; mtime: number }>;\n\n // Quick check: different file count means stale\n if (files.length !== stored.length) {\n this.debug?.(`Stale: file count changed (${stored.length} -> ${files.length})`);\n return true;\n }\n\n // Build lookup map of stored mtimes\n const storedMap = new Map(stored.map((f) => [f.path, f.mtime]));\n\n // Check each file's mtime against stored value\n for (const absPath of files) {\n const relPath = path.relative(this.memoryDir, absPath).replace(/\\\\/g, \"/\");\n const storedMtime = storedMap.get(relPath);\n\n // File not in index = stale\n if (storedMtime === undefined) {\n this.debug?.(`Stale: new file ${relPath}`);\n return true;\n }\n\n // Check mtime\n const stat = await fs.stat(absPath);\n const currentMtime = Math.floor(stat.mtimeMs);\n if (currentMtime !== storedMtime) {\n this.debug?.(`Stale: mtime changed for ${relPath}`);\n return true;\n }\n }\n\n return false;\n } catch (err) {\n // On error, assume stale to be safe\n this.debug?.(`Stale check failed: ${String(err)}`);\n return true;\n }\n }\n\n async search(\n query: string,\n opts?: { maxResults?: number; minScore?: number; type?: string },\n ): Promise<MinimemSearchResult[]> {\n // Check staleness: use dirty flag if watcher is on, otherwise check mtimes\n if (this.dirty || (!this.watchConfig.enabled && (await this.isStale()))) {\n await this.sync({ reason: \"search\" });\n }\n\n const cleaned = query.trim();\n if (!cleaned) return [];\n\n const minScore = opts?.minScore ?? this.queryConfig.minScore;\n const maxResults = opts?.maxResults ?? this.queryConfig.maxResults;\n const candidates = Math.min(\n 200,\n Math.max(1, Math.floor(maxResults * this.hybrid.candidateMultiplier)),\n );\n\n const sourceFilter = { sql: \"\", params: [] as string[] };\n\n const keywordResults = this.hybrid.enabled && this.fts.available\n ? await searchKeyword({\n db: this.db,\n ftsTable: FTS_TABLE,\n providerModel: this.provider.model,\n query: cleaned,\n limit: candidates,\n snippetMaxChars: SNIPPET_MAX_CHARS,\n sourceFilter,\n buildFtsQuery,\n bm25RankToScore,\n }).catch(() => [])\n : [];\n\n const queryVec = await this.embedQueryWithTimeout(cleaned);\n const hasVector = queryVec.some((v) => v !== 0);\n const vectorResults = hasVector\n ? await searchVector({\n db: this.db,\n vectorTable: VECTOR_TABLE,\n providerModel: this.provider.model,\n queryVec,\n limit: candidates,\n snippetMaxChars: SNIPPET_MAX_CHARS,\n ensureVectorReady: (dims) => this.ensureVectorReady(dims),\n sourceFilterVec: sourceFilter,\n sourceFilterChunks: sourceFilter,\n }).catch(() => [])\n : [];\n\n // Apply type filter if specified\n const typeFilterFn = opts?.type\n ? (id: string) => {\n const row = this.db\n .prepare(`SELECT type FROM chunks WHERE id = ?`)\n .get(id) as { type: string | null } | undefined;\n return row?.type === opts.type;\n }\n : undefined;\n\n if (!this.hybrid.enabled) {\n let results = vectorResults;\n if (typeFilterFn) results = results.filter((r) => typeFilterFn(r.id));\n return results\n .filter((entry) => entry.score >= minScore)\n .slice(0, maxResults)\n .map((r) => ({\n path: r.path,\n startLine: r.startLine,\n endLine: r.endLine,\n score: r.score,\n snippet: r.snippet,\n }));\n }\n\n let filteredVector = vectorResults;\n let filteredKeyword = keywordResults;\n if (typeFilterFn) {\n filteredVector = vectorResults.filter((r) => typeFilterFn(r.id));\n filteredKeyword = keywordResults.filter((r) => typeFilterFn(r.id));\n }\n\n const merged = mergeHybridResults({\n vector: filteredVector.map((r) => ({\n id: r.id,\n path: r.path,\n startLine: r.startLine,\n endLine: r.endLine,\n source: r.source,\n snippet: r.snippet,\n vectorScore: r.score,\n })),\n keyword: filteredKeyword.map((r) => ({\n id: r.id,\n path: r.path,\n startLine: r.startLine,\n endLine: r.endLine,\n source: r.source,\n snippet: r.snippet,\n textScore: r.textScore,\n })),\n vectorWeight: this.hybrid.vectorWeight,\n textWeight: this.hybrid.textWeight,\n });\n\n return merged\n .filter((entry) => entry.score >= minScore)\n .slice(0, maxResults)\n .map((r) => ({\n path: r.path,\n startLine: r.startLine,\n endLine: r.endLine,\n score: r.score,\n snippet: r.snippet,\n }));\n }\n\n async sync(opts?: { reason?: string; force?: boolean }): Promise<void> {\n // If a sync is already running, wait for it instead of starting another\n if (this.syncing) {\n await this.syncing;\n return;\n }\n\n // Use a synchronous flag to prevent the race window between\n // checking this.syncing and assigning to it\n if (this.syncLock) {\n return;\n }\n this.syncLock = true;\n\n this.syncing = this.runSync(opts);\n try {\n await this.syncing;\n } finally {\n this.syncing = null;\n this.syncLock = false;\n }\n }\n\n private async runSync(opts?: { reason?: string; force?: boolean }): Promise<void> {\n this.debug?.(`memory sync starting`, { reason: opts?.reason });\n\n await this.ensureVectorReady();\n const meta = this.readMeta();\n const needsFullReindex =\n opts?.force ||\n !meta ||\n meta.model !== this.provider.model ||\n meta.provider !== this.provider.id ||\n meta.providerKey !== this.providerKey ||\n meta.chunkTokens !== this.chunking.tokens ||\n meta.chunkOverlap !== this.chunking.overlap ||\n (this.vector.available && !meta?.vectorDims);\n\n const files = await listMemoryFiles(this.memoryDir);\n const activePaths = new Set<string>();\n\n for (const absPath of files) {\n const entry = await buildFileEntry(absPath, this.memoryDir);\n activePaths.add(entry.path);\n\n const record = this.db\n .prepare(`SELECT hash FROM files WHERE path = ? AND source = ?`)\n .get(entry.path, \"memory\") as { hash: string } | undefined;\n\n if (!needsFullReindex && record?.hash === entry.hash) {\n continue;\n }\n\n await this.indexFile(entry);\n }\n\n // Delete stale entries\n const staleRows = this.db\n .prepare(`SELECT path FROM files WHERE source = ?`)\n .all(\"memory\") as Array<{ path: string }>;\n\n for (const stale of staleRows) {\n if (activePaths.has(stale.path)) continue;\n this.db.prepare(`DELETE FROM files WHERE path = ? AND source = ?`).run(stale.path, \"memory\");\n try {\n this.db\n .prepare(\n `DELETE FROM ${VECTOR_TABLE} WHERE id IN (SELECT id FROM chunks WHERE path = ? AND source = ?)`,\n )\n .run(stale.path, \"memory\");\n } catch (err) {\n logError(\"deleteStaleVectorEntries\", err, this.debug);\n }\n this.db.prepare(`DELETE FROM chunks WHERE path = ? AND source = ?`).run(stale.path, \"memory\");\n this.db.prepare(`DELETE FROM knowledge_links WHERE source_path = ?`).run(stale.path);\n if (this.fts.enabled && this.fts.available) {\n try {\n this.db\n .prepare(`DELETE FROM ${FTS_TABLE} WHERE path = ? AND source = ? AND model = ?`)\n .run(stale.path, \"memory\", this.provider.model);\n } catch (err) {\n logError(\"deleteStaleFtsEntries\", err, this.debug);\n }\n }\n }\n\n // Write meta\n this.writeMeta({\n model: this.provider.model,\n provider: this.provider.id,\n providerKey: this.providerKey,\n chunkTokens: this.chunking.tokens,\n chunkOverlap: this.chunking.overlap,\n vectorDims: this.vector.dims,\n });\n\n // Prune embedding cache\n this.pruneEmbeddingCacheIfNeeded();\n\n this.dirty = false;\n this.debug?.(`memory sync complete`, { files: files.length });\n }\n\n private async indexFile(entry: MemoryFileEntry): Promise<void> {\n const content = await fs.readFile(entry.absPath, \"utf-8\");\n const chunks = chunkMarkdown(content, this.chunking);\n\n // Extract knowledge frontmatter\n const { frontmatter } = parseFrontmatter(content);\n const knowledgeType = frontmatter?.type ?? null;\n const knowledgeId = frontmatter?.id ?? null;\n const domains = frontmatter?.domain ?? null;\n const entities = frontmatter?.entities ?? null;\n const confidence = frontmatter?.confidence ?? null;\n const links = frontmatter?.links ?? null;\n\n // Get embeddings\n const embeddings = await this.embedChunks(chunks);\n\n // Update files table\n this.db\n .prepare(\n `INSERT OR REPLACE INTO files (path, source, hash, mtime, size) VALUES (?, ?, ?, ?, ?)`,\n )\n .run(entry.path, \"memory\", entry.hash, Math.floor(entry.mtimeMs), entry.size);\n\n // Delete old chunks for this file\n try {\n this.db\n .prepare(\n `DELETE FROM ${VECTOR_TABLE} WHERE id IN (SELECT id FROM chunks WHERE path = ? AND source = ?)`,\n )\n .run(entry.path, \"memory\");\n } catch (err) {\n logError(\"deleteOldVectorChunks\", err, this.debug);\n }\n this.db.prepare(`DELETE FROM chunks WHERE path = ? AND source = ?`).run(entry.path, \"memory\");\n if (this.fts.enabled && this.fts.available) {\n try {\n this.db\n .prepare(`DELETE FROM ${FTS_TABLE} WHERE path = ? AND source = ? AND model = ?`)\n .run(entry.path, \"memory\", this.provider.model);\n } catch (err) {\n logError(\"deleteOldFtsChunks\", err, this.debug);\n }\n }\n\n // Delete old knowledge links for this file path on re-index\n this.db.prepare(`DELETE FROM knowledge_links WHERE source_path = ?`).run(entry.path);\n\n // Insert new chunks\n const now = Date.now();\n for (let i = 0; i < chunks.length; i++) {\n const chunk = chunks[i];\n const embedding = embeddings[i] ?? [];\n const chunkId = randomUUID();\n const meta = extractChunkMetadata(chunk.text);\n\n this.db\n .prepare(\n `INSERT INTO chunks (id, path, source, start_line, end_line, hash, model, text, embedding, updated_at, type, knowledge_type, knowledge_id, domains, entities, confidence)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n chunkId,\n entry.path,\n \"memory\",\n chunk.startLine,\n chunk.endLine,\n chunk.hash,\n this.provider.model,\n chunk.text,\n JSON.stringify(embedding),\n now,\n meta.type ?? null,\n knowledgeType,\n knowledgeId,\n domains ? JSON.stringify(domains) : null,\n entities ? JSON.stringify(entities) : null,\n confidence,\n );\n\n // Insert into vector table if available\n if (this.vector.available && embedding.length > 0) {\n if (!this.vector.dims) {\n this.vector.dims = embedding.length;\n this.ensureVectorTable(embedding.length);\n }\n try {\n this.db\n .prepare(`INSERT INTO ${VECTOR_TABLE} (id, embedding) VALUES (?, ?)`)\n .run(chunkId, vectorToBlob(embedding));\n } catch (err) {\n logError(\"insertVectorChunk\", err, this.debug);\n }\n }\n\n // Insert into FTS table if available\n if (this.fts.enabled && this.fts.available) {\n try {\n this.db\n .prepare(\n `INSERT INTO ${FTS_TABLE} (text, id, path, source, model, start_line, end_line)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n chunk.text,\n chunkId,\n entry.path,\n \"memory\",\n this.provider.model,\n chunk.startLine,\n chunk.endLine,\n );\n } catch (err) {\n logError(\"insertFtsChunk\", err, this.debug);\n }\n }\n }\n\n // Upsert knowledge links if present\n if (links && knowledgeId) {\n const upsertLink = this.db.prepare(\n `INSERT OR REPLACE INTO knowledge_links (from_id, to_id, relation, layer, weight, source_path, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n );\n for (const link of links) {\n upsertLink.run(\n knowledgeId,\n link.target,\n link.relation,\n link.layer ?? null,\n 0.5,\n entry.path,\n now,\n );\n }\n }\n }\n\n private async embedChunks(chunks: MemoryChunk[]): Promise<number[][]> {\n if (chunks.length === 0) return [];\n\n const hashes = chunks.map((c) => c.hash);\n const cached = this.loadEmbeddingCache(hashes);\n const missing: Array<{ index: number; chunk: MemoryChunk }> = [];\n\n for (let i = 0; i < chunks.length; i++) {\n if (!cached.has(hashes[i])) {\n missing.push({ index: i, chunk: chunks[i] });\n }\n }\n\n if (missing.length > 0) {\n const texts = missing.map((m) => m.chunk.text);\n const newEmbeddings = await this.embedBatchWithRetry(texts);\n\n for (let i = 0; i < missing.length; i++) {\n const hash = missing[i].chunk.hash;\n const embedding = newEmbeddings[i] ?? [];\n cached.set(hash, embedding);\n this.upsertEmbeddingCache(hash, embedding);\n }\n }\n\n return hashes.map((h) => cached.get(h) ?? []);\n }\n\n private async embedBatchWithRetry(texts: string[]): Promise<number[][]> {\n if (texts.length === 0) return [];\n\n // Try batch API first if enabled\n if (this.batchConfig.enabled) {\n try {\n return await this.embedWithBatchApi(texts);\n } catch (err) {\n this.debug?.(`batch embedding failed, falling back to direct: ${String(err)}`);\n }\n }\n\n // Fall back to direct embedding\n let lastError: Error | null = null;\n for (let attempt = 0; attempt < EMBEDDING_RETRY_MAX_ATTEMPTS; attempt++) {\n try {\n return await this.provider.embedBatch(texts);\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err));\n if (attempt < EMBEDDING_RETRY_MAX_ATTEMPTS - 1) {\n const delay = Math.min(\n EMBEDDING_RETRY_MAX_DELAY_MS,\n EMBEDDING_RETRY_BASE_DELAY_MS * Math.pow(2, attempt),\n );\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n }\n throw lastError;\n }\n\n private async embedWithBatchApi(texts: string[]): Promise<number[][]> {\n if (this.openAi) {\n const requests: OpenAiBatchRequest[] = texts.map((text, i) => ({\n custom_id: `chunk-${i}`,\n method: \"POST\",\n url: OPENAI_BATCH_ENDPOINT,\n body: { model: this.openAi!.model, input: text },\n }));\n\n const results = await runOpenAiEmbeddingBatches({\n openAi: this.openAi,\n source: \"minimem\",\n requests,\n wait: this.batchConfig.wait,\n pollIntervalMs: this.batchConfig.pollIntervalMs,\n timeoutMs: this.batchConfig.timeoutMs,\n concurrency: this.batchConfig.concurrency,\n debug: this.debug,\n });\n\n return texts.map((_, i) => results.get(`chunk-${i}`) ?? []);\n }\n\n if (this.gemini) {\n const requests: GeminiBatchRequest[] = texts.map((text, i) => ({\n custom_id: `chunk-${i}`,\n content: { parts: [{ text }] },\n taskType: \"RETRIEVAL_DOCUMENT\",\n }));\n\n const results = await runGeminiEmbeddingBatches({\n gemini: this.gemini,\n source: \"minimem\",\n requests,\n wait: this.batchConfig.wait,\n pollIntervalMs: this.batchConfig.pollIntervalMs,\n timeoutMs: this.batchConfig.timeoutMs,\n concurrency: this.batchConfig.concurrency,\n debug: this.debug,\n });\n\n return texts.map((_, i) => results.get(`chunk-${i}`) ?? []);\n }\n\n throw new Error(\"Batch API not available for local embeddings\");\n }\n\n private async embedQueryWithTimeout(text: string): Promise<number[]> {\n const timeout =\n this.provider.id === \"local\" ? EMBEDDING_QUERY_TIMEOUT_LOCAL_MS : EMBEDDING_QUERY_TIMEOUT_REMOTE_MS;\n\n const ac = new AbortController();\n const timer = setTimeout(() => ac.abort(), timeout);\n\n try {\n const result = await Promise.race([\n this.provider.embedQuery(text),\n new Promise<number[]>((_, reject) => {\n ac.signal.addEventListener(\"abort\", () =>\n reject(new Error(\"embedding query timeout\")),\n );\n }),\n ]);\n return result;\n } finally {\n clearTimeout(timer);\n }\n }\n\n private loadEmbeddingCache(hashes: string[]): Map<string, number[]> {\n const result = new Map<string, number[]>();\n if (!this.cache.enabled || hashes.length === 0) return result;\n\n const placeholders = hashes.map(() => \"?\").join(\",\");\n const rows = this.db\n .prepare(\n `SELECT hash, embedding FROM ${EMBEDDING_CACHE_TABLE}\n WHERE provider = ? AND model = ? AND provider_key = ? AND hash IN (${placeholders})`,\n )\n .all(this.provider.id, this.provider.model, this.providerKey, ...hashes) as Array<{\n hash: string;\n embedding: string;\n }>;\n\n const now = Date.now();\n for (const row of rows) {\n result.set(row.hash, parseEmbedding(row.embedding));\n // Touch for LRU\n this.db\n .prepare(\n `UPDATE ${EMBEDDING_CACHE_TABLE} SET updated_at = ?\n WHERE provider = ? AND model = ? AND provider_key = ? AND hash = ?`,\n )\n .run(now, this.provider.id, this.provider.model, this.providerKey, row.hash);\n }\n\n return result;\n }\n\n private upsertEmbeddingCache(hash: string, embedding: number[]): void {\n if (!this.cache.enabled) return;\n const now = Date.now();\n this.db\n .prepare(\n `INSERT OR REPLACE INTO ${EMBEDDING_CACHE_TABLE}\n (provider, model, provider_key, hash, embedding, dims, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n this.provider.id,\n this.provider.model,\n this.providerKey,\n hash,\n JSON.stringify(embedding),\n embedding.length,\n now,\n );\n }\n\n private pruneEmbeddingCacheIfNeeded(): void {\n if (!this.cache.enabled) return;\n const row = this.db\n .prepare(`SELECT COUNT(*) as count FROM ${EMBEDDING_CACHE_TABLE}`)\n .get() as { count: number };\n if (row.count <= this.cache.maxEntries) return;\n\n const excess = row.count - this.cache.maxEntries;\n this.db\n .prepare(\n `DELETE FROM ${EMBEDDING_CACHE_TABLE}\n WHERE rowid IN (\n SELECT rowid FROM ${EMBEDDING_CACHE_TABLE}\n ORDER BY updated_at ASC\n LIMIT ?\n )`,\n )\n .run(excess);\n }\n\n private async ensureVectorReady(dimensions?: number): Promise<boolean> {\n if (this.vector.available === true) return true;\n if (this.vector.available === false) return false;\n\n if (!this.vectorReady) {\n this.vectorReady = this.loadVectorExtension();\n }\n\n const ready = await this.vectorReady;\n if (ready && dimensions && !this.vector.dims) {\n this.vector.dims = dimensions;\n this.ensureVectorTable(dimensions);\n }\n return ready;\n }\n\n private async loadVectorExtension(): Promise<boolean> {\n const result = await loadSqliteVecExtension({\n db: this.db,\n extensionPath: this.vectorExtensionPath,\n });\n\n this.vector.available = result.ok;\n if (result.error) {\n this.vector.loadError = result.error;\n this.debug?.(`sqlite-vec load failed: ${result.error}`);\n }\n if (result.extensionPath) {\n this.vector.extensionPath = result.extensionPath;\n }\n\n return result.ok;\n }\n\n private ensureVectorTable(dimensions: number): void {\n if (!this.vector.available) return;\n try {\n this.db.exec(\n `CREATE VIRTUAL TABLE IF NOT EXISTS ${VECTOR_TABLE} USING vec0(\n id TEXT PRIMARY KEY,\n embedding FLOAT[${dimensions}]\n )`,\n );\n } catch (err) {\n this.debug?.(`vector table creation failed: ${String(err)}`);\n }\n }\n\n async readFile(relativePath: string): Promise<string | null> {\n const absPath = path.join(this.memoryDir, relativePath);\n try {\n return await fs.readFile(absPath, \"utf-8\");\n } catch {\n return null;\n }\n }\n\n /**\n * Read specific lines from a memory file\n */\n async readLines(\n relativePath: string,\n opts?: { from?: number; lines?: number },\n ): Promise<{ content: string; startLine: number; endLine: number } | null> {\n const content = await this.readFile(relativePath);\n if (content === null) return null;\n\n const allLines = content.split(\"\\n\");\n const from = Math.max(1, opts?.from ?? 1);\n const lines = opts?.lines ?? allLines.length;\n\n const startIdx = from - 1;\n const endIdx = Math.min(startIdx + lines, allLines.length);\n const selectedLines = allLines.slice(startIdx, endIdx);\n\n return {\n content: selectedLines.join(\"\\n\"),\n startLine: from,\n endLine: startIdx + selectedLines.length,\n };\n }\n\n /**\n * Write content to a memory file (creates or overwrites)\n */\n async writeFile(relativePath: string, content: string): Promise<void> {\n this.validateMemoryPath(relativePath);\n const absPath = path.join(this.memoryDir, relativePath);\n const dir = path.dirname(absPath);\n await fs.mkdir(dir, { recursive: true });\n await fs.writeFile(absPath, content, \"utf-8\");\n this.dirty = true;\n this.debug?.(`memory write: ${relativePath}`);\n }\n\n /**\n * Append content to a memory file (creates if doesn't exist)\n */\n async appendFile(relativePath: string, content: string): Promise<void> {\n this.validateMemoryPath(relativePath);\n const absPath = path.join(this.memoryDir, relativePath);\n const dir = path.dirname(absPath);\n await fs.mkdir(dir, { recursive: true });\n\n // Ensure newline separation\n let toAppend = content;\n try {\n const existing = await fs.readFile(absPath, \"utf-8\");\n if (existing.length > 0 && !existing.endsWith(\"\\n\")) {\n toAppend = \"\\n\" + content;\n }\n } catch {\n // File doesn't exist, will be created\n }\n\n await fs.appendFile(absPath, toAppend, \"utf-8\");\n this.dirty = true;\n this.debug?.(`memory append: ${relativePath}`);\n }\n\n /**\n * Append content to today's daily log (memory/YYYY-MM-DD.md)\n */\n async appendToday(content: string): Promise<string> {\n const today = new Date().toISOString().split(\"T\")[0]; // YYYY-MM-DD\n const relativePath = `memory/${today}.md`;\n await this.appendFile(relativePath, content);\n return relativePath;\n }\n\n /**\n * List all memory files\n */\n async listFiles(): Promise<string[]> {\n const files = await listMemoryFiles(this.memoryDir);\n return files.map((f) => path.relative(this.memoryDir, f).replace(/\\\\/g, \"/\"));\n }\n\n /**\n * Validate that a path is within allowed memory locations\n */\n private validateMemoryPath(relativePath: string): void {\n const normalized = relativePath.replace(/\\\\/g, \"/\").replace(/^\\.\\//, \"\");\n\n // Allow MEMORY.md at root\n if (normalized === \"MEMORY.md\" || normalized === \"memory.md\") {\n return;\n }\n\n // Allow anything under memory/\n if (normalized.startsWith(\"memory/\") && normalized.endsWith(\".md\")) {\n // Prevent path traversal\n if (normalized.includes(\"..\")) {\n throw new Error(`Invalid memory path: ${relativePath} (path traversal not allowed)`);\n }\n return;\n }\n\n throw new Error(\n `Invalid memory path: ${relativePath}. Must be MEMORY.md or memory/*.md`,\n );\n }\n\n async status(): Promise<{\n memoryDir: string;\n dbPath: string;\n provider: string;\n model: string;\n vectorAvailable: boolean;\n ftsAvailable: boolean;\n bm25Only: boolean;\n fallbackReason?: string;\n fileCount: number;\n chunkCount: number;\n cacheCount: number;\n }> {\n const fileRow = this.db.prepare(`SELECT COUNT(*) as count FROM files`).get() as { count: number };\n const chunkRow = this.db.prepare(`SELECT COUNT(*) as count FROM chunks`).get() as { count: number };\n const cacheRow = this.db\n .prepare(`SELECT COUNT(*) as count FROM ${EMBEDDING_CACHE_TABLE}`)\n .get() as { count: number };\n\n return {\n memoryDir: this.memoryDir,\n dbPath: this.dbPath,\n provider: this.provider.id,\n model: this.provider.model,\n vectorAvailable: this.vector.available === true,\n ftsAvailable: this.fts.available,\n bm25Only: this.provider.id === \"none\",\n fallbackReason: this.providerFallbackReason,\n fileCount: fileRow.count,\n chunkCount: chunkRow.count,\n cacheCount: cacheRow.count,\n };\n }\n\n /**\n * Search with knowledge metadata filters (domain, entities, confidence, type).\n * Runs a standard search then post-filters by knowledge columns.\n */\n async knowledgeSearch(\n query: string,\n opts?: {\n maxResults?: number;\n minScore?: number;\n domain?: string[];\n entities?: string[];\n minConfidence?: number;\n knowledgeType?: string;\n },\n ): Promise<MinimemSearchResult[]> {\n // Ensure index is up to date\n if (this.dirty || (!this.watchConfig.enabled && (await this.isStale()))) {\n await this.sync({ reason: \"knowledgeSearch\" });\n }\n\n const cleaned = query.trim();\n if (!cleaned) return [];\n\n const minScore = opts?.minScore ?? this.queryConfig.minScore;\n const maxResults = opts?.maxResults ?? this.queryConfig.maxResults;\n\n // Build knowledge filter SQL\n const { sql: knowledgeWhere, params: knowledgeParams } =\n buildKnowledgeFilterSql({\n domain: opts?.domain,\n entities: opts?.entities,\n minConfidence: opts?.minConfidence,\n knowledgeType: opts?.knowledgeType,\n });\n\n // If no knowledge filters, delegate to regular search\n if (!knowledgeWhere) {\n return this.search(query, { maxResults, minScore });\n }\n\n // Get all chunk IDs matching knowledge filters\n const matchingRows = this.db\n .prepare(\n `SELECT id FROM chunks c WHERE c.model = ? AND c.source = 'memory'${knowledgeWhere}`,\n )\n .all(this.provider.model, ...knowledgeParams) as Array<{ id: string }>;\n\n const matchingIds = new Set(matchingRows.map((r) => r.id));\n\n if (matchingIds.size === 0) return [];\n\n // Run standard search with extra candidates to compensate for filtering\n const overFetch = Math.max(maxResults * 3, 30);\n const results = await this.search(query, {\n maxResults: overFetch,\n minScore,\n });\n\n // Post-filter: look up chunk IDs for each result and keep only matching ones\n const filtered: MinimemSearchResult[] = [];\n for (const r of results) {\n const row = this.db\n .prepare(\n `SELECT id FROM chunks WHERE path = ? AND start_line = ? AND end_line = ? AND model = ?`,\n )\n .get(r.path, r.startLine, r.endLine, this.provider.model) as { id: string } | undefined;\n if (row && matchingIds.has(row.id)) {\n filtered.push(r);\n if (filtered.length >= maxResults) break;\n }\n }\n\n return filtered;\n }\n\n /**\n * Get knowledge graph links from or to a node.\n */\n getLinks(\n nodeId: string,\n direction: \"from\" | \"to\" = \"from\",\n opts?: { relation?: string; layer?: string },\n ): GraphLink[] {\n if (direction === \"from\") {\n return getLinksFrom(this.db, nodeId, opts);\n }\n return getLinksTo(this.db, nodeId, opts);\n }\n\n /**\n * Get neighbor nodes via BFS traversal.\n */\n getGraphNeighbors(\n nodeId: string,\n depth: number = 1,\n opts?: { relation?: string; layer?: string },\n ): GraphNeighbor[] {\n return getNeighbors(this.db, nodeId, depth, opts);\n }\n\n /**\n * Find shortest path between two knowledge nodes.\n */\n getGraphPath(fromId: string, toId: string, maxDepth: number = 3): GraphLink[] {\n return getPathBetween(this.db, fromId, toId, maxDepth);\n }\n\n close(): void {\n if (this.closed) return;\n this.closed = true;\n\n if (this.watchTimer) {\n clearTimeout(this.watchTimer);\n this.watchTimer = null;\n }\n\n if (this.watcher) {\n void this.watcher.close();\n this.watcher = null;\n }\n\n try {\n this.db.close();\n } catch (err) {\n logError(\"dbClose\", err, this.debug);\n }\n }\n}\n","export type HybridSource = string;\n\nexport type HybridVectorResult = {\n id: string;\n path: string;\n startLine: number;\n endLine: number;\n source: HybridSource;\n snippet: string;\n vectorScore: number;\n};\n\nexport type HybridKeywordResult = {\n id: string;\n path: string;\n startLine: number;\n endLine: number;\n source: HybridSource;\n snippet: string;\n textScore: number;\n};\n\nexport function buildFtsQuery(raw: string): string | null {\n const tokens =\n raw\n .match(/[A-Za-z0-9_]+/g)\n ?.map((t) => t.trim())\n .filter(Boolean) ?? [];\n if (tokens.length === 0) return null;\n const quoted = tokens.map((t) => `\"${t.replaceAll('\"', \"\")}\"`);\n return quoted.join(\" AND \");\n}\n\n/**\n * Convert BM25 rank from SQLite FTS5 to a 0-1 score.\n *\n * FTS5 BM25 ranks are NEGATIVE numbers where more negative = better match.\n * A rank of 0 means no match, -10 is better than -1.\n *\n * We use absolute value to convert to positive, then normalize to 0-1\n * using the formula: score = 1 / (1 + absRank)\n *\n * Examples:\n * - rank 0 (no match) -> score 1.0\n * - rank -1 (weak match) -> score 0.5\n * - rank -10 (strong match) -> score ~0.09\n *\n * Note: Higher absolute rank magnitude = better match = higher score after conversion.\n */\nexport function bm25RankToScore(rank: number): number {\n // Handle non-finite values (NaN, Infinity)\n if (!Number.isFinite(rank)) {\n return 0;\n }\n\n // BM25 ranks from FTS5 are negative (more negative = better match)\n // Use absolute value to get the magnitude\n const absRank = Math.abs(rank);\n\n // Convert to 0-1 score where higher magnitude = higher score\n // Using 1/(1+x) gives us a nice 0-1 range that decreases smoothly\n return 1 / (1 + absRank);\n}\n\nexport function mergeHybridResults(params: {\n vector: HybridVectorResult[];\n keyword: HybridKeywordResult[];\n vectorWeight: number;\n textWeight: number;\n}): Array<{\n path: string;\n startLine: number;\n endLine: number;\n score: number;\n snippet: string;\n source: HybridSource;\n}> {\n const byId = new Map<\n string,\n {\n id: string;\n path: string;\n startLine: number;\n endLine: number;\n source: HybridSource;\n snippet: string;\n vectorScore: number;\n textScore: number;\n }\n >();\n\n for (const r of params.vector) {\n byId.set(r.id, {\n id: r.id,\n path: r.path,\n startLine: r.startLine,\n endLine: r.endLine,\n source: r.source,\n snippet: r.snippet,\n vectorScore: r.vectorScore,\n textScore: 0,\n });\n }\n\n for (const r of params.keyword) {\n const existing = byId.get(r.id);\n if (existing) {\n existing.textScore = r.textScore;\n if (r.snippet && r.snippet.length > 0) existing.snippet = r.snippet;\n } else {\n byId.set(r.id, {\n id: r.id,\n path: r.path,\n startLine: r.startLine,\n endLine: r.endLine,\n source: r.source,\n snippet: r.snippet,\n vectorScore: 0,\n textScore: r.textScore,\n });\n }\n }\n\n // When one side of the hybrid search has no results, normalize weights\n // so the available side scores at full strength. Without this, BM25-only\n // results would be scaled to 0.3 * textScore which is too low to pass\n // the default minScore threshold.\n let vw = params.vectorWeight;\n let tw = params.textWeight;\n if (params.vector.length === 0 && params.keyword.length > 0) {\n vw = 0;\n tw = 1;\n } else if (params.keyword.length === 0 && params.vector.length > 0) {\n vw = 1;\n tw = 0;\n }\n\n const merged = Array.from(byId.values()).map((entry) => {\n const score = vw * entry.vectorScore + tw * entry.textScore;\n return {\n path: entry.path,\n startLine: entry.startLine,\n endLine: entry.endLine,\n score,\n snippet: entry.snippet,\n source: entry.source,\n };\n });\n\n return merged.sort((a, b) => b.score - a.score);\n}\n","import type { DatabaseSync } from \"node:sqlite\";\n\nimport { cosineSimilarity, parseEmbedding, truncateUtf16Safe, vectorToBlob } from \"../internal.js\";\n\nexport type SearchSource = string;\n\nexport type SearchRowResult = {\n id: string;\n path: string;\n startLine: number;\n endLine: number;\n score: number;\n snippet: string;\n source: SearchSource;\n};\n\n/**\n * Options for filtering search results by knowledge metadata\n */\nexport type KnowledgeSearchOptions = {\n /** Filter to chunks matching any of these domains */\n domain?: string[];\n /** Filter to chunks referencing any of these entities */\n entities?: string[];\n /** Minimum confidence threshold */\n minConfidence?: number;\n /** Filter to a specific knowledge type */\n knowledgeType?: string;\n};\n\n/**\n * Build SQL WHERE clause fragments for knowledge filters.\n * Uses json_each() for array column filtering.\n */\nexport function buildKnowledgeFilterSql(opts: KnowledgeSearchOptions): {\n sql: string;\n params: (string | number)[];\n} {\n const clauses: string[] = [];\n const params: (string | number)[] = [];\n\n if (opts.knowledgeType) {\n clauses.push(` AND c.knowledge_type = ?`);\n params.push(opts.knowledgeType);\n }\n\n if (opts.minConfidence !== undefined) {\n clauses.push(` AND c.confidence >= ?`);\n params.push(opts.minConfidence);\n }\n\n if (opts.domain && opts.domain.length > 0) {\n // At least one of the provided domains must appear in the JSON array\n const domainPlaceholders = opts.domain.map(() => \"?\").join(\", \");\n clauses.push(\n ` AND EXISTS (SELECT 1 FROM json_each(c.domains) AS d WHERE d.value IN (${domainPlaceholders}))`,\n );\n params.push(...opts.domain);\n }\n\n if (opts.entities && opts.entities.length > 0) {\n const entityPlaceholders = opts.entities.map(() => \"?\").join(\", \");\n clauses.push(\n ` AND EXISTS (SELECT 1 FROM json_each(c.entities) AS e WHERE e.value IN (${entityPlaceholders}))`,\n );\n params.push(...opts.entities);\n }\n\n return { sql: clauses.join(\"\"), params };\n}\n\n/**\n * Perform a vector similarity search against indexed memory chunks.\n *\n * First attempts to use sqlite-vec for fast approximate nearest neighbor search.\n * Falls back to brute-force cosine similarity over all chunks if the vector\n * extension is unavailable.\n *\n * @returns Matching chunks sorted by descending similarity score (0-1 range).\n */\nexport async function searchVector(params: {\n db: DatabaseSync;\n vectorTable: string;\n providerModel: string;\n queryVec: number[];\n limit: number;\n snippetMaxChars: number;\n ensureVectorReady: (dimensions: number) => Promise<boolean>;\n sourceFilterVec: { sql: string; params: SearchSource[] };\n sourceFilterChunks: { sql: string; params: SearchSource[] };\n}): Promise<SearchRowResult[]> {\n if (params.queryVec.length === 0 || params.limit <= 0) return [];\n if (await params.ensureVectorReady(params.queryVec.length)) {\n const rows = params.db\n .prepare(\n `SELECT c.id, c.path, c.start_line, c.end_line, c.text,\\n` +\n ` c.source,\\n` +\n ` vec_distance_cosine(v.embedding, ?) AS dist\\n` +\n ` FROM ${params.vectorTable} v\\n` +\n ` JOIN chunks c ON c.id = v.id\\n` +\n ` WHERE c.model = ?${params.sourceFilterVec.sql}\\n` +\n ` ORDER BY dist ASC\\n` +\n ` LIMIT ?`,\n )\n .all(\n vectorToBlob(params.queryVec),\n params.providerModel,\n ...params.sourceFilterVec.params,\n params.limit,\n ) as Array<{\n id: string;\n path: string;\n start_line: number;\n end_line: number;\n text: string;\n source: SearchSource;\n dist: number;\n }>;\n return rows.map((row) => ({\n id: row.id,\n path: row.path,\n startLine: row.start_line,\n endLine: row.end_line,\n score: 1 - row.dist,\n snippet: truncateUtf16Safe(row.text, params.snippetMaxChars),\n source: row.source,\n }));\n }\n\n const candidates = listChunks({\n db: params.db,\n providerModel: params.providerModel,\n sourceFilter: params.sourceFilterChunks,\n });\n const scored = candidates\n .map((chunk) => ({\n chunk,\n score: cosineSimilarity(params.queryVec, chunk.embedding),\n }))\n .filter((entry) => Number.isFinite(entry.score));\n return scored\n .sort((a, b) => b.score - a.score)\n .slice(0, params.limit)\n .map((entry) => ({\n id: entry.chunk.id,\n path: entry.chunk.path,\n startLine: entry.chunk.startLine,\n endLine: entry.chunk.endLine,\n score: entry.score,\n snippet: truncateUtf16Safe(entry.chunk.text, params.snippetMaxChars),\n source: entry.chunk.source,\n }));\n}\n\n/**\n * List all indexed chunks for a given embedding model and source filter.\n * Used as a fallback when sqlite-vec is not available for vector search.\n *\n * @returns All matching chunks with their parsed embedding vectors.\n */\nexport function listChunks(params: {\n db: DatabaseSync;\n providerModel: string;\n sourceFilter: { sql: string; params: SearchSource[] };\n}): Array<{\n id: string;\n path: string;\n startLine: number;\n endLine: number;\n text: string;\n embedding: number[];\n source: SearchSource;\n}> {\n const rows = params.db\n .prepare(\n `SELECT id, path, start_line, end_line, text, embedding, source\\n` +\n ` FROM chunks\\n` +\n ` WHERE model = ?${params.sourceFilter.sql}`,\n )\n .all(params.providerModel, ...params.sourceFilter.params) as Array<{\n id: string;\n path: string;\n start_line: number;\n end_line: number;\n text: string;\n embedding: string;\n source: SearchSource;\n }>;\n\n return rows.map((row) => ({\n id: row.id,\n path: row.path,\n startLine: row.start_line,\n endLine: row.end_line,\n text: row.text,\n embedding: parseEmbedding(row.embedding),\n source: row.source,\n }));\n}\n\n/**\n * Perform a full-text keyword search using SQLite FTS5 with BM25 ranking.\n *\n * Tokenizes the query into quoted AND terms and runs them against the FTS index.\n * Results are scored using BM25 rank converted to a 0-1 range.\n *\n * @returns Matching chunks sorted by BM25 relevance, with both score and textScore fields.\n */\nexport async function searchKeyword(params: {\n db: DatabaseSync;\n ftsTable: string;\n providerModel: string;\n query: string;\n limit: number;\n snippetMaxChars: number;\n sourceFilter: { sql: string; params: SearchSource[] };\n buildFtsQuery: (raw: string) => string | null;\n bm25RankToScore: (rank: number) => number;\n}): Promise<Array<SearchRowResult & { textScore: number }>> {\n if (params.limit <= 0) return [];\n const ftsQuery = params.buildFtsQuery(params.query);\n if (!ftsQuery) return [];\n\n const rows = params.db\n .prepare(\n `SELECT id, path, source, start_line, end_line, text,\\n` +\n ` bm25(${params.ftsTable}) AS rank\\n` +\n ` FROM ${params.ftsTable}\\n` +\n ` WHERE ${params.ftsTable} MATCH ? AND model = ?${params.sourceFilter.sql}\\n` +\n ` ORDER BY rank ASC\\n` +\n ` LIMIT ?`,\n )\n .all(ftsQuery, params.providerModel, ...params.sourceFilter.params, params.limit) as Array<{\n id: string;\n path: string;\n source: SearchSource;\n start_line: number;\n end_line: number;\n text: string;\n rank: number;\n }>;\n\n return rows.map((row) => {\n const textScore = params.bm25RankToScore(row.rank);\n return {\n id: row.id,\n path: row.path,\n startLine: row.start_line,\n endLine: row.end_line,\n score: textScore,\n textScore,\n snippet: truncateUtf16Safe(row.text, params.snippetMaxChars),\n source: row.source,\n };\n });\n}\n","import type { DatabaseSync } from \"node:sqlite\";\n\n/**\n * Current schema version. Increment this when making breaking schema changes.\n *\n * Version history:\n * - 1: Initial schema (meta, files, chunks, embedding_cache, FTS5)\n * - 2: Added source column to files and chunks tables\n * - 3: Added type column to chunks table for observation type metadata\n * - 4: Added knowledge columns to chunks + knowledge_links table\n */\nexport const SCHEMA_VERSION = 4;\n\nexport function ensureMemoryIndexSchema(params: {\n db: DatabaseSync;\n embeddingCacheTable: string;\n ftsTable: string;\n ftsEnabled: boolean;\n}): { ftsAvailable: boolean; ftsError?: string; migrated?: boolean } {\n // Create meta table first (needed for version tracking)\n params.db.exec(`\n CREATE TABLE IF NOT EXISTS meta (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n );\n `);\n\n // Check schema version and handle migration\n const migrated = migrateIfNeeded(params.db, params.ftsTable);\n\n params.db.exec(`\n CREATE TABLE IF NOT EXISTS files (\n path TEXT PRIMARY KEY,\n source TEXT NOT NULL DEFAULT 'memory',\n hash TEXT NOT NULL,\n mtime INTEGER NOT NULL,\n size INTEGER NOT NULL\n );\n `);\n params.db.exec(`\n CREATE TABLE IF NOT EXISTS chunks (\n id TEXT PRIMARY KEY,\n path TEXT NOT NULL,\n source TEXT NOT NULL DEFAULT 'memory',\n start_line INTEGER NOT NULL,\n end_line INTEGER NOT NULL,\n hash TEXT NOT NULL,\n model TEXT NOT NULL,\n text TEXT NOT NULL,\n embedding TEXT NOT NULL,\n updated_at INTEGER NOT NULL\n );\n `);\n params.db.exec(`\n CREATE TABLE IF NOT EXISTS ${params.embeddingCacheTable} (\n provider TEXT NOT NULL,\n model TEXT NOT NULL,\n provider_key TEXT NOT NULL,\n hash TEXT NOT NULL,\n embedding TEXT NOT NULL,\n dims INTEGER,\n updated_at INTEGER NOT NULL,\n PRIMARY KEY (provider, model, provider_key, hash)\n );\n `);\n params.db.exec(\n `CREATE INDEX IF NOT EXISTS idx_embedding_cache_updated_at ON ${params.embeddingCacheTable}(updated_at);`,\n );\n\n let ftsAvailable = false;\n let ftsError: string | undefined;\n if (params.ftsEnabled) {\n try {\n params.db.exec(\n `CREATE VIRTUAL TABLE IF NOT EXISTS ${params.ftsTable} USING fts5(\\n` +\n ` text,\\n` +\n ` id UNINDEXED,\\n` +\n ` path UNINDEXED,\\n` +\n ` source UNINDEXED,\\n` +\n ` model UNINDEXED,\\n` +\n ` start_line UNINDEXED,\\n` +\n ` end_line UNINDEXED\\n` +\n `);`,\n );\n ftsAvailable = true;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n ftsAvailable = false;\n ftsError = message;\n }\n }\n\n ensureColumn(params.db, \"files\", \"source\", \"TEXT NOT NULL DEFAULT 'memory'\");\n ensureColumn(params.db, \"chunks\", \"source\", \"TEXT NOT NULL DEFAULT 'memory'\");\n ensureColumn(params.db, \"chunks\", \"type\", \"TEXT\");\n ensureColumn(params.db, \"chunks\", \"knowledge_type\", \"TEXT\");\n ensureColumn(params.db, \"chunks\", \"knowledge_id\", \"TEXT\");\n ensureColumn(params.db, \"chunks\", \"domains\", \"TEXT\");\n ensureColumn(params.db, \"chunks\", \"entities\", \"TEXT\");\n ensureColumn(params.db, \"chunks\", \"confidence\", \"REAL\");\n params.db.exec(`CREATE INDEX IF NOT EXISTS idx_chunks_path ON chunks(path);`);\n params.db.exec(`CREATE INDEX IF NOT EXISTS idx_chunks_source ON chunks(source);`);\n params.db.exec(`CREATE INDEX IF NOT EXISTS idx_chunks_type ON chunks(type);`);\n params.db.exec(`CREATE INDEX IF NOT EXISTS idx_chunks_knowledge_type ON chunks(knowledge_type);`);\n params.db.exec(`CREATE INDEX IF NOT EXISTS idx_chunks_knowledge_id ON chunks(knowledge_id);`);\n\n // Knowledge links table for graph traversal\n params.db.exec(`\n CREATE TABLE IF NOT EXISTS knowledge_links (\n from_id TEXT NOT NULL,\n to_id TEXT NOT NULL,\n relation TEXT NOT NULL,\n layer TEXT,\n weight REAL DEFAULT 0.5,\n source_path TEXT,\n created_at INTEGER,\n PRIMARY KEY (from_id, to_id, relation)\n );\n `);\n params.db.exec(`CREATE INDEX IF NOT EXISTS idx_kl_from ON knowledge_links(from_id);`);\n params.db.exec(`CREATE INDEX IF NOT EXISTS idx_kl_to ON knowledge_links(to_id);`);\n params.db.exec(`CREATE INDEX IF NOT EXISTS idx_kl_layer ON knowledge_links(layer);`);\n\n // Store current schema version\n params.db.prepare(\n `INSERT OR REPLACE INTO meta (key, value) VALUES ('schema_version', ?)`,\n ).run(String(SCHEMA_VERSION));\n\n return { ftsAvailable, ...(ftsError ? { ftsError } : {}), ...(migrated ? { migrated } : {}) };\n}\n\n/**\n * Check the stored schema version and migrate if needed.\n * For breaking changes, drops data tables so they get recreated fresh.\n * The embedding cache is preserved across migrations when possible.\n *\n * @returns true if a migration was performed, false otherwise.\n */\nfunction migrateIfNeeded(db: DatabaseSync, ftsTable: string): boolean {\n let storedVersion = 0;\n try {\n const row = db.prepare(\n `SELECT value FROM meta WHERE key = 'schema_version'`,\n ).get() as { value: string } | undefined;\n if (row) {\n storedVersion = parseInt(row.value, 10) || 0;\n }\n } catch {\n // meta table may not have the key yet (pre-versioning databases)\n storedVersion = 0;\n }\n\n if (storedVersion >= SCHEMA_VERSION) return false;\n\n if (storedVersion > 0 && storedVersion < SCHEMA_VERSION) {\n // Breaking schema change: drop and recreate data tables.\n // Embedding cache is preserved since embeddings are content-addressed\n // and will be reused on re-index.\n db.exec(`DROP TABLE IF EXISTS files`);\n db.exec(`DROP TABLE IF EXISTS chunks`);\n db.exec(`DROP TABLE IF EXISTS knowledge_links`);\n db.exec(`DROP TABLE IF EXISTS ${ftsTable}`);\n // Also drop the vector table if it exists\n try {\n db.exec(`DROP TABLE IF EXISTS chunks_vec`);\n } catch {\n // sqlite-vec table may not exist\n }\n }\n\n return storedVersion > 0;\n}\n\nfunction ensureColumn(\n db: DatabaseSync,\n table: \"files\" | \"chunks\",\n column: string,\n definition: string,\n): void {\n const rows = db.prepare(`PRAGMA table_info(${table})`).all() as Array<{ name: string }>;\n if (rows.some((row) => row.name === column)) return;\n db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);\n}\n","import type { DatabaseSync } from \"node:sqlite\";\n\n/**\n * A knowledge graph link between two nodes\n */\nexport type GraphLink = {\n fromId: string;\n toId: string;\n relation: string;\n layer: string | null;\n weight: number;\n sourcePath: string | null;\n};\n\n/**\n * A neighbor node discovered during graph traversal\n */\nexport type GraphNeighbor = {\n id: string;\n depth: number;\n link: GraphLink;\n};\n\n/**\n * Get all outgoing links from a node.\n */\nexport function getLinksFrom(\n db: DatabaseSync,\n fromId: string,\n opts?: { relation?: string; layer?: string },\n): GraphLink[] {\n let sql = `SELECT from_id, to_id, relation, layer, weight, source_path FROM knowledge_links WHERE from_id = ?`;\n const params: (string | number)[] = [fromId];\n\n if (opts?.relation) {\n sql += ` AND relation = ?`;\n params.push(opts.relation);\n }\n if (opts?.layer) {\n sql += ` AND layer = ?`;\n params.push(opts.layer);\n }\n\n const rows = db.prepare(sql).all(...params) as Array<{\n from_id: string;\n to_id: string;\n relation: string;\n layer: string | null;\n weight: number;\n source_path: string | null;\n }>;\n\n return rows.map(toGraphLink);\n}\n\n/**\n * Get all incoming links to a node.\n */\nexport function getLinksTo(\n db: DatabaseSync,\n toId: string,\n opts?: { relation?: string; layer?: string },\n): GraphLink[] {\n let sql = `SELECT from_id, to_id, relation, layer, weight, source_path FROM knowledge_links WHERE to_id = ?`;\n const params: (string | number)[] = [toId];\n\n if (opts?.relation) {\n sql += ` AND relation = ?`;\n params.push(opts.relation);\n }\n if (opts?.layer) {\n sql += ` AND layer = ?`;\n params.push(opts.layer);\n }\n\n const rows = db.prepare(sql).all(...params) as Array<{\n from_id: string;\n to_id: string;\n relation: string;\n layer: string | null;\n weight: number;\n source_path: string | null;\n }>;\n\n return rows.map(toGraphLink);\n}\n\n/**\n * BFS traversal to find neighbors up to a given depth.\n *\n * @param db - Database handle\n * @param startId - The starting node ID\n * @param depth - Maximum traversal depth (default: 1)\n * @param opts - Optional filters for relation and layer\n * @returns Array of neighbor nodes with their depth and connecting link\n */\nexport function getNeighbors(\n db: DatabaseSync,\n startId: string,\n depth: number = 1,\n opts?: { relation?: string; layer?: string },\n): GraphNeighbor[] {\n const visited = new Set<string>([startId]);\n const result: GraphNeighbor[] = [];\n let frontier = [startId];\n\n for (let d = 1; d <= depth; d++) {\n const nextFrontier: string[] = [];\n\n for (const nodeId of frontier) {\n // Follow outgoing links\n const outgoing = getLinksFrom(db, nodeId, opts);\n for (const link of outgoing) {\n if (!visited.has(link.toId)) {\n visited.add(link.toId);\n nextFrontier.push(link.toId);\n result.push({ id: link.toId, depth: d, link });\n }\n }\n\n // Follow incoming links\n const incoming = getLinksTo(db, nodeId, opts);\n for (const link of incoming) {\n if (!visited.has(link.fromId)) {\n visited.add(link.fromId);\n nextFrontier.push(link.fromId);\n result.push({ id: link.fromId, depth: d, link });\n }\n }\n }\n\n frontier = nextFrontier;\n if (frontier.length === 0) break;\n }\n\n return result;\n}\n\n/**\n * BFS shortest path between two nodes, max depth 3.\n *\n * @returns Array of links forming the path, or empty if no path found.\n */\nexport function getPathBetween(\n db: DatabaseSync,\n fromId: string,\n toId: string,\n maxDepth: number = 3,\n): GraphLink[] {\n if (fromId === toId) return [];\n\n // BFS with parent tracking\n const visited = new Set<string>([fromId]);\n // Maps each visited node to the link that discovered it\n const parentLink = new Map<string, GraphLink>();\n let frontier = [fromId];\n\n for (let d = 0; d < maxDepth; d++) {\n const nextFrontier: string[] = [];\n\n for (const nodeId of frontier) {\n // Follow outgoing links\n const outgoing = getLinksFrom(db, nodeId);\n for (const link of outgoing) {\n if (!visited.has(link.toId)) {\n visited.add(link.toId);\n parentLink.set(link.toId, link);\n if (link.toId === toId) {\n return reconstructPath(parentLink, fromId, toId);\n }\n nextFrontier.push(link.toId);\n }\n }\n\n // Follow incoming links\n const incoming = getLinksTo(db, nodeId);\n for (const link of incoming) {\n if (!visited.has(link.fromId)) {\n visited.add(link.fromId);\n parentLink.set(link.fromId, link);\n if (link.fromId === toId) {\n return reconstructPath(parentLink, fromId, toId);\n }\n nextFrontier.push(link.fromId);\n }\n }\n }\n\n frontier = nextFrontier;\n if (frontier.length === 0) break;\n }\n\n return []; // No path found\n}\n\n/**\n * Reconstruct the path from BFS parent map.\n */\nfunction reconstructPath(\n parentLink: Map<string, GraphLink>,\n fromId: string,\n toId: string,\n): GraphLink[] {\n const path: GraphLink[] = [];\n let current = toId;\n\n while (current !== fromId) {\n const link = parentLink.get(current);\n if (!link) break;\n path.unshift(link);\n // Determine which side led to `current`\n current = link.toId === current ? link.fromId : link.toId;\n }\n\n return path;\n}\n\nfunction toGraphLink(row: {\n from_id: string;\n to_id: string;\n relation: string;\n layer: string | null;\n weight: number;\n source_path: string | null;\n}): GraphLink {\n return {\n fromId: row.from_id,\n toId: row.to_id,\n relation: row.relation,\n layer: row.layer,\n weight: row.weight,\n sourcePath: row.source_path,\n };\n}\n","import type { DatabaseSync } from \"node:sqlite\";\n\nexport async function loadSqliteVecExtension(params: {\n db: DatabaseSync;\n extensionPath?: string;\n}): Promise<{ ok: boolean; extensionPath?: string; error?: string }> {\n try {\n const sqliteVec = await import(\"sqlite-vec\");\n const resolvedPath = params.extensionPath?.trim() ? params.extensionPath.trim() : undefined;\n const extensionPath = resolvedPath ?? sqliteVec.getLoadablePath();\n\n params.db.enableLoadExtension(true);\n if (resolvedPath) {\n params.db.loadExtension(extensionPath);\n } else {\n sqliteVec.load(params.db);\n }\n\n return { ok: true, extensionPath };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { ok: false, error: message };\n }\n}\n","import fsSync from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\n\nimport type { Llama, LlamaEmbeddingContext, LlamaModel } from \"node-llama-cpp\";\n\nexport type EmbeddingProvider = {\n id: string;\n model: string;\n embedQuery: (text: string) => Promise<number[]>;\n embedBatch: (texts: string[]) => Promise<number[][]>;\n};\n\nexport type EmbeddingProviderResult = {\n provider: EmbeddingProvider;\n requestedProvider: \"openai\" | \"local\" | \"gemini\" | \"auto\" | \"none\";\n fallbackFrom?: \"openai\" | \"local\" | \"gemini\" | \"auto\";\n fallbackReason?: string;\n openAi?: OpenAiEmbeddingClient;\n gemini?: GeminiEmbeddingClient;\n};\n\nexport type EmbeddingProviderOptions = {\n provider: \"openai\" | \"local\" | \"gemini\" | \"auto\" | \"none\";\n model?: string;\n fallback?: \"openai\" | \"gemini\" | \"local\" | \"none\";\n openai?: {\n apiKey?: string;\n baseUrl?: string;\n headers?: Record<string, string>;\n };\n gemini?: {\n apiKey?: string;\n baseUrl?: string;\n headers?: Record<string, string>;\n };\n local?: {\n modelPath?: string;\n modelCacheDir?: string;\n };\n};\n\nexport type OpenAiEmbeddingClient = {\n baseUrl: string;\n headers: Record<string, string>;\n model: string;\n};\n\nexport type GeminiEmbeddingClient = {\n baseUrl: string;\n headers: Record<string, string>;\n model: string;\n modelPath: string;\n};\n\nconst DEFAULT_LOCAL_MODEL = \"hf:ggml-org/embeddinggemma-300M-GGUF/embeddinggemma-300M-Q8_0.gguf\";\nconst DEFAULT_OPENAI_EMBEDDING_MODEL = \"text-embedding-3-small\";\nconst DEFAULT_OPENAI_BASE_URL = \"https://api.openai.com/v1\";\nconst DEFAULT_GEMINI_EMBEDDING_MODEL = \"gemini-embedding-001\";\nconst DEFAULT_GEMINI_BASE_URL = \"https://generativelanguage.googleapis.com/v1beta\";\n\n/**\n * Creates a no-op embedding provider that returns empty vectors.\n * Used for BM25-only mode when no embedding API is available.\n */\nfunction createNoOpEmbeddingProvider(): EmbeddingProvider {\n return {\n id: \"none\",\n model: \"bm25-only\",\n embedQuery: async () => [],\n embedBatch: async (texts) => texts.map(() => []),\n };\n}\n\nfunction resolveUserPath(filePath: string): string {\n if (filePath.startsWith(\"~/\")) {\n return path.join(os.homedir(), filePath.slice(2));\n }\n return filePath;\n}\n\nfunction canAutoSelectLocal(options: EmbeddingProviderOptions): boolean {\n const modelPath = options.local?.modelPath?.trim();\n if (!modelPath) return false;\n if (/^(hf:|https?:)/i.test(modelPath)) return false;\n const resolved = resolveUserPath(modelPath);\n try {\n return fsSync.statSync(resolved).isFile();\n } catch {\n return false;\n }\n}\n\nfunction isMissingApiKeyError(err: unknown): boolean {\n const message = formatError(err);\n return message.includes(\"API key\") || message.includes(\"apiKey\");\n}\n\nasync function importNodeLlamaCpp() {\n const llama = await import(\"node-llama-cpp\");\n return llama;\n}\n\nasync function createLocalEmbeddingProvider(\n options: EmbeddingProviderOptions,\n): Promise<EmbeddingProvider> {\n const modelPath = options.local?.modelPath?.trim() || DEFAULT_LOCAL_MODEL;\n const modelCacheDir = options.local?.modelCacheDir?.trim();\n\n const { getLlama, resolveModelFile, LlamaLogLevel } = await importNodeLlamaCpp();\n\n let llama: Llama | null = null;\n let embeddingModel: LlamaModel | null = null;\n let embeddingContext: LlamaEmbeddingContext | null = null;\n\n const ensureContext = async () => {\n if (!llama) {\n llama = await getLlama({ logLevel: LlamaLogLevel.error });\n }\n if (!embeddingModel) {\n const resolved = await resolveModelFile(modelPath, modelCacheDir || undefined);\n embeddingModel = await llama.loadModel({ modelPath: resolved });\n }\n if (!embeddingContext) {\n embeddingContext = await embeddingModel.createEmbeddingContext();\n }\n return embeddingContext;\n };\n\n return {\n id: \"local\",\n model: modelPath,\n embedQuery: async (text) => {\n const ctx = await ensureContext();\n const embedding = await ctx.getEmbeddingFor(text);\n return Array.from(embedding.vector) as number[];\n },\n embedBatch: async (texts) => {\n const ctx = await ensureContext();\n const embeddings = await Promise.all(\n texts.map(async (text) => {\n const embedding = await ctx.getEmbeddingFor(text);\n return Array.from(embedding.vector) as number[];\n }),\n );\n return embeddings;\n },\n };\n}\n\nfunction normalizeOpenAiModel(model: string): string {\n const trimmed = model.trim();\n if (!trimmed) return DEFAULT_OPENAI_EMBEDDING_MODEL;\n if (trimmed.startsWith(\"openai/\")) return trimmed.slice(\"openai/\".length);\n return trimmed;\n}\n\nfunction resolveOpenAiApiKey(options: EmbeddingProviderOptions): string {\n const apiKey = options.openai?.apiKey?.trim();\n if (apiKey) return apiKey;\n const envKey = process.env.OPENAI_API_KEY?.trim();\n if (envKey) return envKey;\n throw new Error(\"OpenAI API key not found. Set OPENAI_API_KEY env var or pass openai.apiKey option.\");\n}\n\nexport async function createOpenAiEmbeddingProvider(\n options: EmbeddingProviderOptions,\n): Promise<{ provider: EmbeddingProvider; client: OpenAiEmbeddingClient }> {\n const apiKey = resolveOpenAiApiKey(options);\n const baseUrl = options.openai?.baseUrl?.trim() || DEFAULT_OPENAI_BASE_URL;\n const headerOverrides = options.openai?.headers ?? {};\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n ...headerOverrides,\n };\n const model = normalizeOpenAiModel(options.model || \"\");\n const client: OpenAiEmbeddingClient = { baseUrl, headers, model };\n const url = `${baseUrl.replace(/\\/$/, \"\")}/embeddings`;\n\n const embed = async (input: string[]): Promise<number[][]> => {\n if (input.length === 0) return [];\n const res = await fetch(url, {\n method: \"POST\",\n headers: client.headers,\n body: JSON.stringify({ model: client.model, input }),\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`openai embeddings failed: ${res.status} ${text}`);\n }\n const payload = (await res.json()) as {\n data?: Array<{ embedding?: number[] }>;\n };\n const data = payload.data ?? [];\n return data.map((entry) => entry.embedding ?? []);\n };\n\n return {\n provider: {\n id: \"openai\",\n model: client.model,\n embedQuery: async (text) => {\n const [vec] = await embed([text]);\n return vec ?? [];\n },\n embedBatch: embed,\n },\n client,\n };\n}\n\nfunction normalizeGeminiModel(model: string): string {\n const trimmed = model.trim();\n if (!trimmed) return DEFAULT_GEMINI_EMBEDDING_MODEL;\n const withoutPrefix = trimmed.replace(/^models\\//, \"\");\n if (withoutPrefix.startsWith(\"gemini/\")) return withoutPrefix.slice(\"gemini/\".length);\n if (withoutPrefix.startsWith(\"google/\")) return withoutPrefix.slice(\"google/\".length);\n return withoutPrefix;\n}\n\nfunction normalizeGeminiBaseUrl(raw: string): string {\n const trimmed = raw.replace(/\\/+$/, \"\");\n const openAiIndex = trimmed.indexOf(\"/openai\");\n if (openAiIndex > -1) return trimmed.slice(0, openAiIndex);\n return trimmed;\n}\n\nfunction buildGeminiModelPath(model: string): string {\n return model.startsWith(\"models/\") ? model : `models/${model}`;\n}\n\nfunction resolveGeminiApiKey(options: EmbeddingProviderOptions): string {\n const apiKey = options.gemini?.apiKey?.trim();\n if (apiKey) return apiKey;\n const googleKey = process.env.GOOGLE_API_KEY?.trim();\n if (googleKey) return googleKey;\n const geminiKey = process.env.GEMINI_API_KEY?.trim();\n if (geminiKey) return geminiKey;\n throw new Error(\"Gemini API key not found. Set GOOGLE_API_KEY or GEMINI_API_KEY env var or pass gemini.apiKey option.\");\n}\n\nexport async function createGeminiEmbeddingProvider(\n options: EmbeddingProviderOptions,\n): Promise<{ provider: EmbeddingProvider; client: GeminiEmbeddingClient }> {\n const apiKey = resolveGeminiApiKey(options);\n const rawBaseUrl = options.gemini?.baseUrl?.trim() || DEFAULT_GEMINI_BASE_URL;\n const baseUrl = normalizeGeminiBaseUrl(rawBaseUrl);\n const headerOverrides = options.gemini?.headers ?? {};\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"x-goog-api-key\": apiKey,\n ...headerOverrides,\n };\n const model = normalizeGeminiModel(options.model || \"\");\n const modelPath = buildGeminiModelPath(model);\n const client: GeminiEmbeddingClient = { baseUrl, headers, model, modelPath };\n\n const embedUrl = `${baseUrl}/${modelPath}:embedContent`;\n const batchUrl = `${baseUrl}/${modelPath}:batchEmbedContents`;\n\n const embedQuery = async (text: string): Promise<number[]> => {\n if (!text.trim()) return [];\n const res = await fetch(embedUrl, {\n method: \"POST\",\n headers: client.headers,\n body: JSON.stringify({\n content: { parts: [{ text }] },\n taskType: \"RETRIEVAL_QUERY\",\n }),\n });\n if (!res.ok) {\n const payload = await res.text();\n throw new Error(`gemini embeddings failed: ${res.status} ${payload}`);\n }\n const payload = (await res.json()) as { embedding?: { values?: number[] } };\n return payload.embedding?.values ?? [];\n };\n\n const embedBatch = async (texts: string[]): Promise<number[][]> => {\n if (texts.length === 0) return [];\n const requests = texts.map((text) => ({\n model: modelPath,\n content: { parts: [{ text }] },\n taskType: \"RETRIEVAL_DOCUMENT\",\n }));\n const res = await fetch(batchUrl, {\n method: \"POST\",\n headers: client.headers,\n body: JSON.stringify({ requests }),\n });\n if (!res.ok) {\n const payload = await res.text();\n throw new Error(`gemini embeddings failed: ${res.status} ${payload}`);\n }\n const payload = (await res.json()) as { embeddings?: Array<{ values?: number[] }> };\n const embeddings = Array.isArray(payload.embeddings) ? payload.embeddings : [];\n return texts.map((_, index) => embeddings[index]?.values ?? []);\n };\n\n return {\n provider: {\n id: \"gemini\",\n model: client.model,\n embedQuery,\n embedBatch,\n },\n client,\n };\n}\n\nexport async function createEmbeddingProvider(\n options: EmbeddingProviderOptions,\n): Promise<EmbeddingProviderResult> {\n const requestedProvider = options.provider;\n const fallback = options.fallback ?? \"none\";\n\n // Handle explicit \"none\" provider (BM25-only mode)\n if (requestedProvider === \"none\") {\n return {\n provider: createNoOpEmbeddingProvider(),\n requestedProvider: \"none\",\n };\n }\n\n const createProvider = async (id: \"openai\" | \"local\" | \"gemini\") => {\n if (id === \"local\") {\n const provider = await createLocalEmbeddingProvider(options);\n return { provider };\n }\n if (id === \"gemini\") {\n const { provider, client } = await createGeminiEmbeddingProvider(options);\n return { provider, gemini: client };\n }\n const { provider, client } = await createOpenAiEmbeddingProvider(options);\n return { provider, openAi: client };\n };\n\n const formatPrimaryError = (err: unknown, provider: \"openai\" | \"local\" | \"gemini\") =>\n provider === \"local\" ? formatLocalSetupError(err) : formatError(err);\n\n if (requestedProvider === \"auto\") {\n const missingKeyErrors: string[] = [];\n let localError: string | null = null;\n\n if (canAutoSelectLocal(options)) {\n try {\n const local = await createProvider(\"local\");\n return { ...local, requestedProvider };\n } catch (err) {\n localError = formatLocalSetupError(err);\n }\n }\n\n for (const provider of [\"openai\", \"gemini\"] as const) {\n try {\n const result = await createProvider(provider);\n return { ...result, requestedProvider };\n } catch (err) {\n const message = formatPrimaryError(err, provider);\n if (isMissingApiKeyError(err)) {\n missingKeyErrors.push(message);\n continue;\n }\n throw new Error(message);\n }\n }\n\n // Fall back to BM25-only mode instead of throwing\n // This allows the system to work without any API keys using full-text search only\n return {\n provider: createNoOpEmbeddingProvider(),\n requestedProvider,\n fallbackFrom: \"auto\",\n fallbackReason: \"No embedding API available. Using BM25 full-text search only.\",\n };\n }\n\n try {\n const primary = await createProvider(requestedProvider);\n return { ...primary, requestedProvider };\n } catch (primaryErr) {\n const reason = formatPrimaryError(primaryErr, requestedProvider);\n if (fallback && fallback !== \"none\" && fallback !== requestedProvider) {\n try {\n const fallbackResult = await createProvider(fallback);\n return {\n ...fallbackResult,\n requestedProvider,\n fallbackFrom: requestedProvider,\n fallbackReason: reason,\n };\n } catch (fallbackErr) {\n throw new Error(`${reason}\\n\\nFallback to ${fallback} failed: ${formatError(fallbackErr)}`);\n }\n }\n throw new Error(reason);\n }\n}\n\nfunction formatError(err: unknown): string {\n if (err instanceof Error) return err.message;\n return String(err);\n}\n\nfunction isNodeLlamaCppMissing(err: unknown): boolean {\n if (!(err instanceof Error)) return false;\n const code = (err as Error & { code?: unknown }).code;\n if (code === \"ERR_MODULE_NOT_FOUND\") {\n return err.message.includes(\"node-llama-cpp\");\n }\n return false;\n}\n\nfunction formatLocalSetupError(err: unknown): string {\n const detail = formatError(err);\n const missing = isNodeLlamaCppMissing(err);\n return [\n \"Local embeddings unavailable.\",\n missing\n ? \"Reason: optional dependency node-llama-cpp is missing (or failed to install).\"\n : detail\n ? `Reason: ${detail}`\n : undefined,\n missing && detail ? `Detail: ${detail}` : null,\n \"To enable local embeddings:\",\n \"1) Use Node 22 LTS (recommended for installs/updates)\",\n missing ? \"2) Install node-llama-cpp: npm install node-llama-cpp\" : null,\n \"3) If you use pnpm: pnpm approve-builds (select node-llama-cpp), then pnpm rebuild node-llama-cpp\",\n 'Or set provider = \"openai\" or \"gemini\" (remote).',\n ]\n .filter(Boolean)\n .join(\"\\n\");\n}\n","import type { OpenAiEmbeddingClient } from \"./embeddings.js\";\nimport { hashText } from \"../internal.js\";\n\nexport type OpenAiBatchRequest = {\n custom_id: string;\n method: \"POST\";\n url: \"/v1/embeddings\";\n body: {\n model: string;\n input: string;\n };\n};\n\nexport type OpenAiBatchStatus = {\n id?: string;\n status?: string;\n output_file_id?: string | null;\n error_file_id?: string | null;\n};\n\nexport type OpenAiBatchOutputLine = {\n custom_id?: string;\n response?: {\n status_code?: number;\n body?: {\n data?: Array<{ embedding?: number[]; index?: number }>;\n error?: { message?: string };\n };\n };\n error?: { message?: string };\n};\n\nexport const OPENAI_BATCH_ENDPOINT = \"/v1/embeddings\";\nconst OPENAI_BATCH_COMPLETION_WINDOW = \"24h\";\nconst OPENAI_BATCH_MAX_REQUESTS = 50000;\n\nfunction getOpenAiBaseUrl(openAi: OpenAiEmbeddingClient): string {\n return openAi.baseUrl?.replace(/\\/$/, \"\") ?? \"\";\n}\n\nfunction getOpenAiHeaders(\n openAi: OpenAiEmbeddingClient,\n params: { json: boolean },\n): Record<string, string> {\n const headers = openAi.headers ? { ...openAi.headers } : {};\n if (params.json) {\n if (!headers[\"Content-Type\"] && !headers[\"content-type\"]) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n } else {\n delete headers[\"Content-Type\"];\n delete headers[\"content-type\"];\n }\n return headers;\n}\n\nfunction splitOpenAiBatchRequests(requests: OpenAiBatchRequest[]): OpenAiBatchRequest[][] {\n if (requests.length <= OPENAI_BATCH_MAX_REQUESTS) return [requests];\n const groups: OpenAiBatchRequest[][] = [];\n for (let i = 0; i < requests.length; i += OPENAI_BATCH_MAX_REQUESTS) {\n groups.push(requests.slice(i, i + OPENAI_BATCH_MAX_REQUESTS));\n }\n return groups;\n}\n\nasync function retryAsync<T>(\n fn: () => Promise<T>,\n opts: {\n attempts: number;\n minDelayMs: number;\n maxDelayMs: number;\n jitter: number;\n shouldRetry: (err: unknown) => boolean;\n },\n): Promise<T> {\n let lastError: unknown;\n for (let attempt = 0; attempt < opts.attempts; attempt++) {\n try {\n return await fn();\n } catch (err) {\n lastError = err;\n if (!opts.shouldRetry(err) || attempt === opts.attempts - 1) {\n throw err;\n }\n const delay = Math.min(\n opts.maxDelayMs,\n opts.minDelayMs * Math.pow(2, attempt) * (1 + Math.random() * opts.jitter),\n );\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n throw lastError;\n}\n\nasync function submitOpenAiBatch(params: {\n openAi: OpenAiEmbeddingClient;\n requests: OpenAiBatchRequest[];\n source: string;\n}): Promise<OpenAiBatchStatus> {\n const baseUrl = getOpenAiBaseUrl(params.openAi);\n const jsonl = params.requests.map((request) => JSON.stringify(request)).join(\"\\n\");\n const form = new FormData();\n form.append(\"purpose\", \"batch\");\n form.append(\n \"file\",\n new Blob([jsonl], { type: \"application/jsonl\" }),\n `memory-embeddings.${hashText(String(Date.now()))}.jsonl`,\n );\n\n const fileRes = await fetch(`${baseUrl}/files`, {\n method: \"POST\",\n headers: getOpenAiHeaders(params.openAi, { json: false }),\n body: form,\n });\n if (!fileRes.ok) {\n const text = await fileRes.text();\n throw new Error(`openai batch file upload failed: ${fileRes.status} ${text}`);\n }\n const filePayload = (await fileRes.json()) as { id?: string };\n if (!filePayload.id) {\n throw new Error(\"openai batch file upload failed: missing file id\");\n }\n\n const batchRes = await retryAsync(\n async () => {\n const res = await fetch(`${baseUrl}/batches`, {\n method: \"POST\",\n headers: getOpenAiHeaders(params.openAi, { json: true }),\n body: JSON.stringify({\n input_file_id: filePayload.id,\n endpoint: OPENAI_BATCH_ENDPOINT,\n completion_window: OPENAI_BATCH_COMPLETION_WINDOW,\n metadata: {\n source: params.source,\n },\n }),\n });\n if (!res.ok) {\n const text = await res.text();\n const err = new Error(`openai batch create failed: ${res.status} ${text}`) as Error & {\n status?: number;\n };\n err.status = res.status;\n throw err;\n }\n return res;\n },\n {\n attempts: 3,\n minDelayMs: 300,\n maxDelayMs: 2000,\n jitter: 0.2,\n shouldRetry: (err) => {\n const status = (err as { status?: number }).status;\n return status === 429 || (typeof status === \"number\" && status >= 500);\n },\n },\n );\n return (await batchRes.json()) as OpenAiBatchStatus;\n}\n\nasync function fetchOpenAiBatchStatus(params: {\n openAi: OpenAiEmbeddingClient;\n batchId: string;\n}): Promise<OpenAiBatchStatus> {\n const baseUrl = getOpenAiBaseUrl(params.openAi);\n const res = await fetch(`${baseUrl}/batches/${params.batchId}`, {\n headers: getOpenAiHeaders(params.openAi, { json: true }),\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`openai batch status failed: ${res.status} ${text}`);\n }\n return (await res.json()) as OpenAiBatchStatus;\n}\n\nasync function fetchOpenAiFileContent(params: {\n openAi: OpenAiEmbeddingClient;\n fileId: string;\n}): Promise<string> {\n const baseUrl = getOpenAiBaseUrl(params.openAi);\n const res = await fetch(`${baseUrl}/files/${params.fileId}/content`, {\n headers: getOpenAiHeaders(params.openAi, { json: true }),\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`openai batch file content failed: ${res.status} ${text}`);\n }\n return await res.text();\n}\n\nfunction parseOpenAiBatchOutput(text: string): OpenAiBatchOutputLine[] {\n if (!text.trim()) return [];\n return text\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter(Boolean)\n .map((line) => JSON.parse(line) as OpenAiBatchOutputLine);\n}\n\nasync function readOpenAiBatchError(params: {\n openAi: OpenAiEmbeddingClient;\n errorFileId: string;\n}): Promise<string | undefined> {\n try {\n const content = await fetchOpenAiFileContent({\n openAi: params.openAi,\n fileId: params.errorFileId,\n });\n const lines = parseOpenAiBatchOutput(content);\n const first = lines.find((line) => line.error?.message || line.response?.body?.error);\n const message =\n first?.error?.message ??\n (typeof first?.response?.body?.error?.message === \"string\"\n ? first?.response?.body?.error?.message\n : undefined);\n return message;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return message ? `error file unavailable: ${message}` : undefined;\n }\n}\n\nasync function waitForOpenAiBatch(params: {\n openAi: OpenAiEmbeddingClient;\n batchId: string;\n wait: boolean;\n pollIntervalMs: number;\n timeoutMs: number;\n debug?: (message: string, data?: Record<string, unknown>) => void;\n initial?: OpenAiBatchStatus;\n}): Promise<{ outputFileId: string; errorFileId?: string }> {\n const start = Date.now();\n let current: OpenAiBatchStatus | undefined = params.initial;\n while (true) {\n const status =\n current ??\n (await fetchOpenAiBatchStatus({\n openAi: params.openAi,\n batchId: params.batchId,\n }));\n const state = status.status ?? \"unknown\";\n if (state === \"completed\") {\n if (!status.output_file_id) {\n throw new Error(`openai batch ${params.batchId} completed without output file`);\n }\n return {\n outputFileId: status.output_file_id,\n errorFileId: status.error_file_id ?? undefined,\n };\n }\n if ([\"failed\", \"expired\", \"cancelled\", \"canceled\"].includes(state)) {\n const detail = status.error_file_id\n ? await readOpenAiBatchError({ openAi: params.openAi, errorFileId: status.error_file_id })\n : undefined;\n const suffix = detail ? `: ${detail}` : \"\";\n throw new Error(`openai batch ${params.batchId} ${state}${suffix}`);\n }\n if (!params.wait) {\n throw new Error(`openai batch ${params.batchId} still ${state}; wait disabled`);\n }\n if (Date.now() - start > params.timeoutMs) {\n throw new Error(`openai batch ${params.batchId} timed out after ${params.timeoutMs}ms`);\n }\n params.debug?.(`openai batch ${params.batchId} ${state}; waiting ${params.pollIntervalMs}ms`);\n await new Promise((resolve) => setTimeout(resolve, params.pollIntervalMs));\n current = undefined;\n }\n}\n\nasync function runWithConcurrency<T>(tasks: Array<() => Promise<T>>, limit: number): Promise<T[]> {\n if (tasks.length === 0) return [];\n const resolvedLimit = Math.max(1, Math.min(limit, tasks.length));\n const results: T[] = Array.from({ length: tasks.length });\n let next = 0;\n let firstError: unknown = null;\n\n const workers = Array.from({ length: resolvedLimit }, async () => {\n while (true) {\n if (firstError) return;\n const index = next;\n next += 1;\n if (index >= tasks.length) return;\n try {\n results[index] = await tasks[index]();\n } catch (err) {\n firstError = err;\n return;\n }\n }\n });\n\n await Promise.allSettled(workers);\n if (firstError) throw firstError;\n return results;\n}\n\nexport async function runOpenAiEmbeddingBatches(params: {\n openAi: OpenAiEmbeddingClient;\n source: string;\n requests: OpenAiBatchRequest[];\n wait: boolean;\n pollIntervalMs: number;\n timeoutMs: number;\n concurrency: number;\n debug?: (message: string, data?: Record<string, unknown>) => void;\n}): Promise<Map<string, number[]>> {\n if (params.requests.length === 0) return new Map();\n const groups = splitOpenAiBatchRequests(params.requests);\n const byCustomId = new Map<string, number[]>();\n\n const tasks = groups.map((group, groupIndex) => async () => {\n const batchInfo = await submitOpenAiBatch({\n openAi: params.openAi,\n requests: group,\n source: params.source,\n });\n if (!batchInfo.id) {\n throw new Error(\"openai batch create failed: missing batch id\");\n }\n\n params.debug?.(\"memory embeddings: openai batch created\", {\n batchId: batchInfo.id,\n status: batchInfo.status,\n group: groupIndex + 1,\n groups: groups.length,\n requests: group.length,\n });\n\n if (!params.wait && batchInfo.status !== \"completed\") {\n throw new Error(\n `openai batch ${batchInfo.id} submitted; enable batch.wait to await completion`,\n );\n }\n\n const completed =\n batchInfo.status === \"completed\"\n ? {\n outputFileId: batchInfo.output_file_id ?? \"\",\n errorFileId: batchInfo.error_file_id ?? undefined,\n }\n : await waitForOpenAiBatch({\n openAi: params.openAi,\n batchId: batchInfo.id,\n wait: params.wait,\n pollIntervalMs: params.pollIntervalMs,\n timeoutMs: params.timeoutMs,\n debug: params.debug,\n initial: batchInfo,\n });\n if (!completed.outputFileId) {\n throw new Error(`openai batch ${batchInfo.id} completed without output file`);\n }\n\n const content = await fetchOpenAiFileContent({\n openAi: params.openAi,\n fileId: completed.outputFileId,\n });\n const outputLines = parseOpenAiBatchOutput(content);\n const errors: string[] = [];\n const remaining = new Set(group.map((request) => request.custom_id));\n\n for (const line of outputLines) {\n const customId = line.custom_id;\n if (!customId) continue;\n remaining.delete(customId);\n if (line.error?.message) {\n errors.push(`${customId}: ${line.error.message}`);\n continue;\n }\n const response = line.response;\n const statusCode = response?.status_code ?? 0;\n if (statusCode >= 400) {\n const message =\n response?.body?.error?.message ??\n (typeof response?.body === \"string\" ? response.body : undefined) ??\n \"unknown error\";\n errors.push(`${customId}: ${message}`);\n continue;\n }\n const data = response?.body?.data ?? [];\n const embedding = data[0]?.embedding ?? [];\n if (embedding.length === 0) {\n errors.push(`${customId}: empty embedding`);\n continue;\n }\n byCustomId.set(customId, embedding);\n }\n\n if (errors.length > 0) {\n throw new Error(`openai batch ${batchInfo.id} failed: ${errors.join(\"; \")}`);\n }\n if (remaining.size > 0) {\n throw new Error(`openai batch ${batchInfo.id} missing ${remaining.size} embedding responses`);\n }\n });\n\n params.debug?.(\"memory embeddings: openai batch submit\", {\n requests: params.requests.length,\n groups: groups.length,\n wait: params.wait,\n concurrency: params.concurrency,\n pollIntervalMs: params.pollIntervalMs,\n timeoutMs: params.timeoutMs,\n });\n\n await runWithConcurrency(tasks, params.concurrency);\n return byCustomId;\n}\n","import type { GeminiEmbeddingClient } from \"./embeddings.js\";\nimport { hashText } from \"../internal.js\";\n\nexport type GeminiBatchRequest = {\n custom_id: string;\n content: { parts: Array<{ text: string }> };\n taskType: \"RETRIEVAL_DOCUMENT\" | \"RETRIEVAL_QUERY\";\n};\n\nexport type GeminiBatchStatus = {\n name?: string;\n state?: string;\n outputConfig?: { file?: string; fileId?: string };\n metadata?: {\n output?: {\n responsesFile?: string;\n };\n };\n error?: { message?: string };\n};\n\nexport type GeminiBatchOutputLine = {\n key?: string;\n custom_id?: string;\n request_id?: string;\n embedding?: { values?: number[] };\n response?: {\n embedding?: { values?: number[] };\n error?: { message?: string };\n };\n error?: { message?: string };\n};\n\nconst GEMINI_BATCH_MAX_REQUESTS = 50000;\n\nfunction getGeminiBaseUrl(gemini: GeminiEmbeddingClient): string {\n return gemini.baseUrl?.replace(/\\/$/, \"\") ?? \"\";\n}\n\nfunction getGeminiHeaders(\n gemini: GeminiEmbeddingClient,\n params: { json: boolean },\n): Record<string, string> {\n const headers = gemini.headers ? { ...gemini.headers } : {};\n if (params.json) {\n if (!headers[\"Content-Type\"] && !headers[\"content-type\"]) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n } else {\n delete headers[\"Content-Type\"];\n delete headers[\"content-type\"];\n }\n return headers;\n}\n\nfunction getGeminiUploadUrl(baseUrl: string): string {\n if (baseUrl.includes(\"/v1beta\")) {\n return baseUrl.replace(/\\/v1beta\\/?$/, \"/upload/v1beta\");\n }\n return `${baseUrl.replace(/\\/$/, \"\")}/upload`;\n}\n\nfunction splitGeminiBatchRequests(requests: GeminiBatchRequest[]): GeminiBatchRequest[][] {\n if (requests.length <= GEMINI_BATCH_MAX_REQUESTS) return [requests];\n const groups: GeminiBatchRequest[][] = [];\n for (let i = 0; i < requests.length; i += GEMINI_BATCH_MAX_REQUESTS) {\n groups.push(requests.slice(i, i + GEMINI_BATCH_MAX_REQUESTS));\n }\n return groups;\n}\n\nfunction buildGeminiUploadBody(params: { jsonl: string; displayName: string }): {\n body: Blob;\n contentType: string;\n} {\n const boundary = `minimem-${hashText(params.displayName)}`;\n const jsonPart = JSON.stringify({\n file: {\n displayName: params.displayName,\n mimeType: \"application/jsonl\",\n },\n });\n const delimiter = `--${boundary}\\r\\n`;\n const closeDelimiter = `--${boundary}--\\r\\n`;\n const parts = [\n `${delimiter}Content-Type: application/json; charset=UTF-8\\r\\n\\r\\n${jsonPart}\\r\\n`,\n `${delimiter}Content-Type: application/jsonl; charset=UTF-8\\r\\n\\r\\n${params.jsonl}\\r\\n`,\n closeDelimiter,\n ];\n const body = new Blob([parts.join(\"\")], { type: \"multipart/related\" });\n return {\n body,\n contentType: `multipart/related; boundary=${boundary}`,\n };\n}\n\nasync function submitGeminiBatch(params: {\n gemini: GeminiEmbeddingClient;\n requests: GeminiBatchRequest[];\n source: string;\n}): Promise<GeminiBatchStatus> {\n const baseUrl = getGeminiBaseUrl(params.gemini);\n const jsonl = params.requests\n .map((request) =>\n JSON.stringify({\n key: request.custom_id,\n request: {\n content: request.content,\n task_type: request.taskType,\n },\n }),\n )\n .join(\"\\n\");\n const displayName = `memory-embeddings-${hashText(String(Date.now()))}`;\n const uploadPayload = buildGeminiUploadBody({ jsonl, displayName });\n\n const uploadUrl = `${getGeminiUploadUrl(baseUrl)}/files?uploadType=multipart`;\n const fileRes = await fetch(uploadUrl, {\n method: \"POST\",\n headers: {\n ...getGeminiHeaders(params.gemini, { json: false }),\n \"Content-Type\": uploadPayload.contentType,\n },\n body: uploadPayload.body,\n });\n if (!fileRes.ok) {\n const text = await fileRes.text();\n throw new Error(`gemini batch file upload failed: ${fileRes.status} ${text}`);\n }\n const filePayload = (await fileRes.json()) as { name?: string; file?: { name?: string } };\n const fileId = filePayload.name ?? filePayload.file?.name;\n if (!fileId) {\n throw new Error(\"gemini batch file upload failed: missing file id\");\n }\n\n const batchBody = {\n batch: {\n displayName: `memory-embeddings-${params.source}`,\n inputConfig: {\n file_name: fileId,\n },\n },\n };\n\n const batchEndpoint = `${baseUrl}/${params.gemini.modelPath}:asyncBatchEmbedContent`;\n const batchRes = await fetch(batchEndpoint, {\n method: \"POST\",\n headers: getGeminiHeaders(params.gemini, { json: true }),\n body: JSON.stringify(batchBody),\n });\n if (batchRes.ok) {\n return (await batchRes.json()) as GeminiBatchStatus;\n }\n const text = await batchRes.text();\n if (batchRes.status === 404) {\n throw new Error(\n \"gemini batch create failed: 404 (asyncBatchEmbedContent not available for this model/baseUrl). Disable batch.enabled or switch providers.\",\n );\n }\n throw new Error(`gemini batch create failed: ${batchRes.status} ${text}`);\n}\n\nasync function fetchGeminiBatchStatus(params: {\n gemini: GeminiEmbeddingClient;\n batchName: string;\n}): Promise<GeminiBatchStatus> {\n const baseUrl = getGeminiBaseUrl(params.gemini);\n const name = params.batchName.startsWith(\"batches/\")\n ? params.batchName\n : `batches/${params.batchName}`;\n const statusUrl = `${baseUrl}/${name}`;\n const res = await fetch(statusUrl, {\n headers: getGeminiHeaders(params.gemini, { json: true }),\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`gemini batch status failed: ${res.status} ${text}`);\n }\n return (await res.json()) as GeminiBatchStatus;\n}\n\nasync function fetchGeminiFileContent(params: {\n gemini: GeminiEmbeddingClient;\n fileId: string;\n}): Promise<string> {\n const baseUrl = getGeminiBaseUrl(params.gemini);\n const file = params.fileId.startsWith(\"files/\") ? params.fileId : `files/${params.fileId}`;\n const downloadUrl = `${baseUrl}/${file}:download`;\n const res = await fetch(downloadUrl, {\n headers: getGeminiHeaders(params.gemini, { json: true }),\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`gemini batch file content failed: ${res.status} ${text}`);\n }\n return await res.text();\n}\n\nfunction parseGeminiBatchOutput(text: string): GeminiBatchOutputLine[] {\n if (!text.trim()) return [];\n return text\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter(Boolean)\n .map((line) => JSON.parse(line) as GeminiBatchOutputLine);\n}\n\nasync function waitForGeminiBatch(params: {\n gemini: GeminiEmbeddingClient;\n batchName: string;\n wait: boolean;\n pollIntervalMs: number;\n timeoutMs: number;\n debug?: (message: string, data?: Record<string, unknown>) => void;\n initial?: GeminiBatchStatus;\n}): Promise<{ outputFileId: string }> {\n const start = Date.now();\n let current: GeminiBatchStatus | undefined = params.initial;\n while (true) {\n const status =\n current ??\n (await fetchGeminiBatchStatus({\n gemini: params.gemini,\n batchName: params.batchName,\n }));\n const state = status.state ?? \"UNKNOWN\";\n if ([\"SUCCEEDED\", \"COMPLETED\", \"DONE\"].includes(state)) {\n const outputFileId =\n status.outputConfig?.file ??\n status.outputConfig?.fileId ??\n status.metadata?.output?.responsesFile;\n if (!outputFileId) {\n throw new Error(`gemini batch ${params.batchName} completed without output file`);\n }\n return { outputFileId };\n }\n if ([\"FAILED\", \"CANCELLED\", \"CANCELED\", \"EXPIRED\"].includes(state)) {\n const message = status.error?.message ?? \"unknown error\";\n throw new Error(`gemini batch ${params.batchName} ${state}: ${message}`);\n }\n if (!params.wait) {\n throw new Error(`gemini batch ${params.batchName} still ${state}; wait disabled`);\n }\n if (Date.now() - start > params.timeoutMs) {\n throw new Error(`gemini batch ${params.batchName} timed out after ${params.timeoutMs}ms`);\n }\n params.debug?.(`gemini batch ${params.batchName} ${state}; waiting ${params.pollIntervalMs}ms`);\n await new Promise((resolve) => setTimeout(resolve, params.pollIntervalMs));\n current = undefined;\n }\n}\n\nasync function runWithConcurrency<T>(tasks: Array<() => Promise<T>>, limit: number): Promise<T[]> {\n if (tasks.length === 0) return [];\n const resolvedLimit = Math.max(1, Math.min(limit, tasks.length));\n const results: T[] = Array.from({ length: tasks.length });\n let next = 0;\n let firstError: unknown = null;\n\n const workers = Array.from({ length: resolvedLimit }, async () => {\n while (true) {\n if (firstError) return;\n const index = next;\n next += 1;\n if (index >= tasks.length) return;\n try {\n results[index] = await tasks[index]();\n } catch (err) {\n firstError = err;\n return;\n }\n }\n });\n\n await Promise.allSettled(workers);\n if (firstError) throw firstError;\n return results;\n}\n\nexport async function runGeminiEmbeddingBatches(params: {\n gemini: GeminiEmbeddingClient;\n source: string;\n requests: GeminiBatchRequest[];\n wait: boolean;\n pollIntervalMs: number;\n timeoutMs: number;\n concurrency: number;\n debug?: (message: string, data?: Record<string, unknown>) => void;\n}): Promise<Map<string, number[]>> {\n if (params.requests.length === 0) return new Map();\n const groups = splitGeminiBatchRequests(params.requests);\n const byCustomId = new Map<string, number[]>();\n\n const tasks = groups.map((group, groupIndex) => async () => {\n const batchInfo = await submitGeminiBatch({\n gemini: params.gemini,\n requests: group,\n source: params.source,\n });\n const batchName = batchInfo.name ?? \"\";\n if (!batchName) {\n throw new Error(\"gemini batch create failed: missing batch name\");\n }\n\n params.debug?.(\"memory embeddings: gemini batch created\", {\n batchName,\n state: batchInfo.state,\n group: groupIndex + 1,\n groups: groups.length,\n requests: group.length,\n });\n\n if (\n !params.wait &&\n batchInfo.state &&\n ![\"SUCCEEDED\", \"COMPLETED\", \"DONE\"].includes(batchInfo.state)\n ) {\n throw new Error(\n `gemini batch ${batchName} submitted; enable batch.wait to await completion`,\n );\n }\n\n const completed =\n batchInfo.state && [\"SUCCEEDED\", \"COMPLETED\", \"DONE\"].includes(batchInfo.state)\n ? {\n outputFileId:\n batchInfo.outputConfig?.file ??\n batchInfo.outputConfig?.fileId ??\n batchInfo.metadata?.output?.responsesFile ??\n \"\",\n }\n : await waitForGeminiBatch({\n gemini: params.gemini,\n batchName,\n wait: params.wait,\n pollIntervalMs: params.pollIntervalMs,\n timeoutMs: params.timeoutMs,\n debug: params.debug,\n initial: batchInfo,\n });\n if (!completed.outputFileId) {\n throw new Error(`gemini batch ${batchName} completed without output file`);\n }\n\n const content = await fetchGeminiFileContent({\n gemini: params.gemini,\n fileId: completed.outputFileId,\n });\n const outputLines = parseGeminiBatchOutput(content);\n const errors: string[] = [];\n const remaining = new Set(group.map((request) => request.custom_id));\n\n for (const line of outputLines) {\n const customId = line.key ?? line.custom_id ?? line.request_id;\n if (!customId) continue;\n remaining.delete(customId);\n if (line.error?.message) {\n errors.push(`${customId}: ${line.error.message}`);\n continue;\n }\n if (line.response?.error?.message) {\n errors.push(`${customId}: ${line.response.error.message}`);\n continue;\n }\n const embedding = line.embedding?.values ?? line.response?.embedding?.values ?? [];\n if (embedding.length === 0) {\n errors.push(`${customId}: empty embedding`);\n continue;\n }\n byCustomId.set(customId, embedding);\n }\n\n if (errors.length > 0) {\n throw new Error(`gemini batch ${batchName} failed: ${errors.join(\"; \")}`);\n }\n if (remaining.size > 0) {\n throw new Error(`gemini batch ${batchName} missing ${remaining.size} embedding responses`);\n }\n });\n\n params.debug?.(\"memory embeddings: gemini batch submit\", {\n requests: params.requests.length,\n groups: groups.length,\n wait: params.wait,\n concurrency: params.concurrency,\n pollIntervalMs: params.pollIntervalMs,\n timeoutMs: params.timeoutMs,\n });\n\n await runWithConcurrency(tasks, params.concurrency);\n return byCustomId;\n}\n","/**\n * Tool definitions for memory operations\n *\n * These tools are compatible with:\n * - MCP (Model Context Protocol)\n * - Anthropic Claude tool use\n * - OpenAI function calling\n *\n * Note: Only memory_search is provided since the memory system is file-based.\n * Agents can use filesystem tools directly for read/write operations.\n */\n\nimport type { Minimem, MinimemSearchResult } from \"../minimem.js\";\n\n/**\n * JSON Schema for tool parameters (MCP/OpenAI/Anthropic compatible)\n */\nexport type ToolInputSchema = {\n type: \"object\";\n properties: Record<\n string,\n {\n type: string;\n description?: string;\n enum?: string[];\n items?: { type: string };\n default?: unknown;\n }\n >;\n required?: string[];\n};\n\n/**\n * Tool definition compatible with MCP, Anthropic, and OpenAI\n */\nexport type ToolDefinition = {\n name: string;\n description: string;\n inputSchema: ToolInputSchema;\n};\n\n/**\n * Tool execution result\n */\nexport type ToolResult = {\n content: Array<{ type: \"text\"; text: string }>;\n isError?: boolean;\n};\n\n/**\n * Memory search tool parameters\n */\nexport type MemorySearchParams = {\n query: string;\n maxResults?: number;\n minScore?: number;\n directories?: string[];\n /** \"compact\" returns lightweight index; \"full\" returns complete snippets (default: \"compact\") */\n detail?: \"compact\" | \"full\";\n /** Filter by observation type (e.g., \"decision\", \"bugfix\", \"feature\", \"discovery\") */\n type?: string;\n};\n\n/**\n * Memory get details tool parameters\n */\nexport type MemoryGetDetailsParams = {\n results: Array<{ path: string; startLine: number; endLine: number }>;\n directories?: string[];\n};\n\n/**\n * Knowledge search tool parameters\n */\nexport type KnowledgeSearchParams = {\n query: string;\n domain?: string[];\n entities?: string[];\n minConfidence?: number;\n knowledgeType?: string;\n maxResults?: number;\n minScore?: number;\n directories?: string[];\n};\n\n/**\n * Knowledge graph traversal parameters\n */\nexport type KnowledgeGraphParams = {\n nodeId: string;\n depth?: number;\n relation?: string;\n layer?: string;\n directories?: string[];\n};\n\n/**\n * Knowledge path parameters\n */\nexport type KnowledgePathParams = {\n fromId: string;\n toId: string;\n maxDepth?: number;\n directories?: string[];\n};\n\n/**\n * Search result with source directory\n */\ntype SearchResultWithSource = MinimemSearchResult & {\n memoryDir: string;\n};\n\nexport const MEMORY_SEARCH_TOOL: ToolDefinition = {\n name: \"memory_search\",\n description:\n \"Semantically search through memory files (MEMORY.md and memory/*.md). \" +\n \"Use this to recall prior decisions, facts, preferences, people, dates, or context. \" +\n \"Returns ranked snippets with file paths and line numbers. \" +\n \"When multiple memory directories are configured, searches all by default.\",\n inputSchema: {\n type: \"object\",\n properties: {\n query: {\n type: \"string\",\n description: \"Natural language search query\",\n },\n maxResults: {\n type: \"number\",\n description: \"Maximum number of results to return (default: 10)\",\n },\n minScore: {\n type: \"number\",\n description: \"Minimum relevance score threshold 0-1 (default: 0.3)\",\n },\n directories: {\n type: \"array\",\n items: { type: \"string\" },\n description:\n \"Optional: filter to specific memory directories by name/path. \" +\n \"If omitted, searches all configured directories.\",\n },\n detail: {\n type: \"string\",\n enum: [\"compact\", \"full\"],\n description:\n \"Result detail level. 'compact' returns a lightweight index with short previews (~80 chars). \" +\n \"'full' returns complete snippets. Use 'compact' first, then memory_get_details for selected results. \" +\n \"(default: 'compact')\",\n },\n type: {\n type: \"string\",\n description:\n \"Filter by observation type. Matches <!-- type: X --> comments in memory entries. \" +\n \"Common types: decision, bugfix, feature, discovery, context, note.\",\n },\n },\n required: [\"query\"],\n },\n};\n\nexport const MEMORY_GET_DETAILS_TOOL: ToolDefinition = {\n name: \"memory_get_details\",\n description:\n \"Fetch full text for specific memory chunks identified by path and line range. \" +\n \"Use after memory_search with compact results to get details for selected items only. \" +\n \"This two-step approach significantly reduces token usage.\",\n inputSchema: {\n type: \"object\",\n properties: {\n results: {\n type: \"array\",\n items: { type: \"object\" },\n description:\n \"Array of { path, startLine, endLine } objects from compact search results.\",\n },\n directories: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Optional: filter to specific memory directories.\",\n },\n },\n required: [\"results\"],\n },\n};\n\nexport const KNOWLEDGE_SEARCH_TOOL: ToolDefinition = {\n name: \"knowledge_search\",\n description:\n \"Search memory with knowledge metadata filters. \" +\n \"Filter by domain, entities, confidence level, or knowledge type (observation, entity, domain-summary). \" +\n \"Combines semantic search with structured knowledge filtering.\",\n inputSchema: {\n type: \"object\",\n properties: {\n query: {\n type: \"string\",\n description: \"Natural language search query\",\n },\n domain: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Filter to entries in these knowledge domains\",\n },\n entities: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Filter to entries referencing these entities\",\n },\n minConfidence: {\n type: \"number\",\n description: \"Minimum confidence threshold (0-1)\",\n },\n knowledgeType: {\n type: \"string\",\n description: \"Filter by knowledge type: observation, entity, domain-summary\",\n },\n maxResults: {\n type: \"number\",\n description: \"Maximum number of results (default: 10)\",\n },\n minScore: {\n type: \"number\",\n description: \"Minimum relevance score 0-1 (default: 0.3)\",\n },\n directories: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Optional: filter to specific memory directories\",\n },\n },\n required: [\"query\"],\n },\n};\n\nexport const KNOWLEDGE_GRAPH_TOOL: ToolDefinition = {\n name: \"knowledge_graph\",\n description:\n \"Traverse knowledge graph links from a note. \" +\n \"Returns neighbor nodes connected by typed relationships (e.g., relates-to, supports, contradicts). \" +\n \"Use depth parameter for multi-hop traversal.\",\n inputSchema: {\n type: \"object\",\n properties: {\n nodeId: {\n type: \"string\",\n description: \"The knowledge node ID to start traversal from\",\n },\n depth: {\n type: \"number\",\n description: \"Maximum traversal depth (default: 1, max: 3)\",\n default: 1,\n },\n relation: {\n type: \"string\",\n description: \"Optional: filter to specific relation type\",\n },\n layer: {\n type: \"string\",\n description: \"Optional: filter to specific graph layer\",\n },\n directories: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Optional: filter to specific memory directories\",\n },\n },\n required: [\"nodeId\"],\n },\n};\n\nexport const KNOWLEDGE_PATH_TOOL: ToolDefinition = {\n name: \"knowledge_path\",\n description:\n \"Find the shortest path between two knowledge nodes in the graph. \" +\n \"Uses BFS traversal up to a configurable max depth. \" +\n \"Returns the sequence of links connecting the two nodes.\",\n inputSchema: {\n type: \"object\",\n properties: {\n fromId: {\n type: \"string\",\n description: \"Starting knowledge node ID\",\n },\n toId: {\n type: \"string\",\n description: \"Target knowledge node ID\",\n },\n maxDepth: {\n type: \"number\",\n description: \"Maximum path length (default: 3)\",\n default: 3,\n },\n directories: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Optional: filter to specific memory directories\",\n },\n },\n required: [\"fromId\", \"toId\"],\n },\n};\n\n/**\n * All available memory tools\n */\nexport const MEMORY_TOOLS: ToolDefinition[] = [\n MEMORY_SEARCH_TOOL,\n MEMORY_GET_DETAILS_TOOL,\n KNOWLEDGE_SEARCH_TOOL,\n KNOWLEDGE_GRAPH_TOOL,\n KNOWLEDGE_PATH_TOOL,\n];\n\n/**\n * Get tool definitions for use with LLM APIs\n */\nexport function getToolDefinitions(): ToolDefinition[] {\n return MEMORY_TOOLS;\n}\n\n/**\n * Memory instance with its directory path\n */\nexport type MemoryInstance = {\n minimem: Minimem;\n memoryDir: string;\n name?: string;\n};\n\n/**\n * Tool executor that handles memory search across multiple directories\n */\nexport class MemoryToolExecutor {\n private instances: MemoryInstance[];\n\n constructor(instances: Minimem | MemoryInstance | MemoryInstance[]) {\n // Normalize to array of MemoryInstance\n if (Array.isArray(instances)) {\n this.instances = instances;\n } else if (\"minimem\" in instances) {\n this.instances = [instances];\n } else {\n // Legacy: single Minimem instance without directory info\n this.instances = [{ minimem: instances, memoryDir: \"default\" }];\n }\n }\n\n /**\n * Get list of configured directory names/paths\n */\n getDirectories(): string[] {\n return this.instances.map((i) => i.name ?? i.memoryDir);\n }\n\n /**\n * Execute a tool by name with given parameters\n */\n async execute(\n toolName: string,\n params: Record<string, unknown>,\n ): Promise<ToolResult> {\n try {\n switch (toolName) {\n case \"memory_search\":\n return await this.memorySearch(params as MemorySearchParams);\n case \"memory_get_details\":\n return await this.memoryGetDetails(params as MemoryGetDetailsParams);\n case \"knowledge_search\":\n return await this.knowledgeSearch(params as KnowledgeSearchParams);\n case \"knowledge_graph\":\n return await this.knowledgeGraph(params as KnowledgeGraphParams);\n case \"knowledge_path\":\n return await this.knowledgePath(params as KnowledgePathParams);\n default:\n return {\n content: [{ type: \"text\", text: `Unknown tool: ${toolName}` }],\n isError: true,\n };\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n content: [{ type: \"text\", text: `Error: ${message}` }],\n isError: true,\n };\n }\n }\n\n /**\n * Filter instances by directory names/paths\n */\n private filterInstances(directories?: string[]): MemoryInstance[] | null {\n if (!directories || directories.length === 0) return this.instances;\n\n const dirFilter = new Set(directories.map((d) => d.toLowerCase()));\n const filtered = this.instances.filter((i) => {\n const name = (i.name ?? i.memoryDir).toLowerCase();\n const dir = i.memoryDir.toLowerCase();\n return (\n dirFilter.has(name) ||\n dirFilter.has(dir) ||\n [...dirFilter].some((f) => dir.includes(f) || name.includes(f))\n );\n });\n\n return filtered.length > 0 ? filtered : null;\n }\n\n private async memorySearch(params: MemorySearchParams): Promise<ToolResult> {\n const maxResults = params.maxResults ?? 10;\n const minScore = params.minScore;\n const detail = params.detail ?? \"compact\";\n\n const instancesToSearch = this.filterInstances(params.directories);\n if (!instancesToSearch) {\n const available = this.getDirectories().join(\", \");\n return {\n content: [\n {\n type: \"text\",\n text: `No matching directories found. Available: ${available}`,\n },\n ],\n isError: true,\n };\n }\n\n // Search all matching instances\n const allResults: SearchResultWithSource[] = [];\n\n for (const instance of instancesToSearch) {\n const perDirMax = Math.ceil(maxResults * 1.5);\n const results = await instance.minimem.search(params.query, {\n maxResults: perDirMax,\n minScore,\n type: params.type,\n });\n\n for (const result of results) {\n allResults.push({\n ...result,\n memoryDir: instance.name ?? instance.memoryDir,\n });\n }\n }\n\n // Sort by score and limit\n allResults.sort((a, b) => b.score - a.score);\n const topResults = allResults.slice(0, maxResults);\n\n if (topResults.length === 0) {\n return {\n content: [{ type: \"text\", text: \"No results found.\" }],\n };\n }\n\n const showSource = instancesToSearch.length > 1;\n\n if (detail === \"compact\") {\n return this.formatCompactResults(topResults, showSource, instancesToSearch.length);\n }\n\n return this.formatFullResults(topResults, showSource, instancesToSearch.length);\n }\n\n private formatCompactResults(\n results: SearchResultWithSource[],\n showSource: boolean,\n dirCount: number,\n ): ToolResult {\n const formatted = results\n .map((r, i) => {\n const location = `${r.path}:${r.startLine}-${r.endLine}`;\n const score = (r.score * 100).toFixed(0);\n const source = showSource ? ` [${r.memoryDir}]` : \"\";\n const preview = compactPreview(r.snippet);\n return `[${i}] ${location}${source} (${score}%) — ${preview}`;\n })\n .join(\"\\n\");\n\n const hint = \"\\n\\nUse memory_get_details to fetch full text for selected results.\";\n const dirSummary = dirCount > 1 ? `\\n(Searched ${dirCount} directories)` : \"\";\n\n return {\n content: [{ type: \"text\", text: formatted + dirSummary + hint }],\n };\n }\n\n private formatFullResults(\n results: SearchResultWithSource[],\n showSource: boolean,\n dirCount: number,\n ): ToolResult {\n const formatted = results\n .map((r, i) => {\n const location = `${r.path}:${r.startLine}-${r.endLine}`;\n const score = (r.score * 100).toFixed(1);\n const source = showSource ? ` [${r.memoryDir}]` : \"\";\n return `[${i + 1}] ${location}${source} (${score}% match)\\n${r.snippet}`;\n })\n .join(\"\\n\\n\");\n\n const dirSummary =\n dirCount > 1 ? `\\n\\n(Searched ${dirCount} directories)` : \"\";\n\n return {\n content: [{ type: \"text\", text: formatted + dirSummary }],\n };\n }\n\n private async memoryGetDetails(params: MemoryGetDetailsParams): Promise<ToolResult> {\n if (!params.results || params.results.length === 0) {\n return {\n content: [{ type: \"text\", text: \"No results specified.\" }],\n isError: true,\n };\n }\n\n const instancesToSearch = this.filterInstances(params.directories);\n if (!instancesToSearch) {\n const available = this.getDirectories().join(\", \");\n return {\n content: [\n {\n type: \"text\",\n text: `No matching directories found. Available: ${available}`,\n },\n ],\n isError: true,\n };\n }\n\n const details: string[] = [];\n\n for (const ref of params.results) {\n let found = false;\n\n for (const instance of instancesToSearch) {\n const lineCount = ref.endLine - ref.startLine + 1;\n const result = await instance.minimem.readLines(ref.path, {\n from: ref.startLine,\n lines: lineCount,\n });\n\n if (result) {\n const location = `${ref.path}:${result.startLine}-${result.endLine}`;\n details.push(`--- ${location} ---\\n${result.content}`);\n found = true;\n break;\n }\n }\n\n if (!found) {\n details.push(`--- ${ref.path}:${ref.startLine}-${ref.endLine} ---\\n(not found)`);\n }\n }\n\n return {\n content: [{ type: \"text\", text: details.join(\"\\n\\n\") }],\n };\n }\n\n private async knowledgeSearch(params: KnowledgeSearchParams): Promise<ToolResult> {\n const instancesToSearch = this.filterInstances(params.directories);\n if (!instancesToSearch) {\n const available = this.getDirectories().join(\", \");\n return {\n content: [{ type: \"text\", text: `No matching directories found. Available: ${available}` }],\n isError: true,\n };\n }\n\n const maxResults = params.maxResults ?? 10;\n const allResults: SearchResultWithSource[] = [];\n\n for (const instance of instancesToSearch) {\n const results = await instance.minimem.knowledgeSearch(params.query, {\n maxResults: Math.ceil(maxResults * 1.5),\n minScore: params.minScore,\n domain: params.domain,\n entities: params.entities,\n minConfidence: params.minConfidence,\n knowledgeType: params.knowledgeType,\n });\n\n for (const result of results) {\n allResults.push({\n ...result,\n memoryDir: instance.name ?? instance.memoryDir,\n });\n }\n }\n\n allResults.sort((a, b) => b.score - a.score);\n const topResults = allResults.slice(0, maxResults);\n\n if (topResults.length === 0) {\n return { content: [{ type: \"text\", text: \"No knowledge results found.\" }] };\n }\n\n const formatted = topResults\n .map((r, i) => {\n const location = `${r.path}:${r.startLine}-${r.endLine}`;\n const score = (r.score * 100).toFixed(0);\n const preview = compactPreview(r.snippet);\n return `[${i}] ${location} (${score}%) — ${preview}`;\n })\n .join(\"\\n\");\n\n return { content: [{ type: \"text\", text: formatted }] };\n }\n\n private async knowledgeGraph(params: KnowledgeGraphParams): Promise<ToolResult> {\n const instancesToSearch = this.filterInstances(params.directories);\n if (!instancesToSearch) {\n const available = this.getDirectories().join(\", \");\n return {\n content: [{ type: \"text\", text: `No matching directories found. Available: ${available}` }],\n isError: true,\n };\n }\n\n const depth = Math.min(params.depth ?? 1, 3);\n const allNeighbors: Array<{ id: string; depth: number; relation: string; layer: string | null; memoryDir: string }> = [];\n\n for (const instance of instancesToSearch) {\n const neighbors = instance.minimem.getGraphNeighbors(params.nodeId, depth, {\n relation: params.relation,\n layer: params.layer,\n });\n\n for (const n of neighbors) {\n allNeighbors.push({\n id: n.id,\n depth: n.depth,\n relation: n.link.relation,\n layer: n.link.layer,\n memoryDir: instance.name ?? instance.memoryDir,\n });\n }\n }\n\n if (allNeighbors.length === 0) {\n return { content: [{ type: \"text\", text: `No neighbors found for node \"${params.nodeId}\".` }] };\n }\n\n const formatted = allNeighbors\n .map((n) => ` [depth=${n.depth}] ${n.id} —(${n.relation})${n.layer ? ` [${n.layer}]` : \"\"}`)\n .join(\"\\n\");\n\n return {\n content: [{ type: \"text\", text: `Neighbors of \"${params.nodeId}\":\\n${formatted}` }],\n };\n }\n\n private async knowledgePath(params: KnowledgePathParams): Promise<ToolResult> {\n const instancesToSearch = this.filterInstances(params.directories);\n if (!instancesToSearch) {\n const available = this.getDirectories().join(\", \");\n return {\n content: [{ type: \"text\", text: `No matching directories found. Available: ${available}` }],\n isError: true,\n };\n }\n\n const maxDepth = Math.min(params.maxDepth ?? 3, 5);\n\n // Try each instance until a path is found\n for (const instance of instancesToSearch) {\n const path = instance.minimem.getGraphPath(params.fromId, params.toId, maxDepth);\n if (path.length > 0) {\n const steps = path\n .map((link) => ` ${link.fromId} —(${link.relation})→ ${link.toId}`)\n .join(\"\\n\");\n return {\n content: [{\n type: \"text\",\n text: `Path from \"${params.fromId}\" to \"${params.toId}\" (${path.length} steps):\\n${steps}`,\n }],\n };\n }\n }\n\n return {\n content: [{\n type: \"text\",\n text: `No path found from \"${params.fromId}\" to \"${params.toId}\" within depth ${maxDepth}.`,\n }],\n };\n }\n}\n\n/**\n * Generate a compact preview from a snippet (~80 chars).\n * Prefers the first heading or first non-empty line.\n */\nfunction compactPreview(snippet: string): string {\n const maxLen = 80;\n const lines = snippet.split(\"\\n\").filter((l) => l.trim());\n if (lines.length === 0) return \"(empty)\";\n\n // Prefer a heading line\n const heading = lines.find((l) => l.startsWith(\"#\"));\n const text = heading ?? lines[0];\n // Strip markdown heading markers for cleaner display\n const cleaned = text.replace(/^#+\\s*/, \"\").trim();\n\n if (cleaned.length <= maxLen) return `\"${cleaned}\"`;\n return `\"${cleaned.slice(0, maxLen - 3)}...\"`;\n}\n\n/**\n * Create a tool executor for the given Minimem instance(s)\n */\nexport function createToolExecutor(\n instances: Minimem | MemoryInstance | MemoryInstance[],\n): MemoryToolExecutor {\n return new MemoryToolExecutor(instances);\n}\n","/**\n * MCP (Model Context Protocol) Server for Minimem\n *\n * Provides memory tools via JSON-RPC 2.0 over stdio.\n * Compatible with Claude Desktop, Cursor, and other MCP clients.\n *\n * Usage:\n * import { Minimem } from \"minimem\";\n * import { createMcpServer, runMcpServer } from \"minimem/mcp\";\n *\n * const minimem = await Minimem.create({ ... });\n * const server = createMcpServer(minimem);\n * await runMcpServer(server); // Runs over stdio\n */\n\nimport * as readline from \"node:readline\";\nimport type { Minimem } from \"../minimem.js\";\nimport {\n MEMORY_TOOLS,\n type ToolDefinition,\n type ToolResult,\n type MemoryInstance,\n MemoryToolExecutor,\n} from \"./tools.js\";\n\nconst PROTOCOL_VERSION = \"2024-11-05\";\nconst SERVER_NAME = \"minimem\";\nconst SERVER_VERSION = \"0.1.0\";\n\n/**\n * JSON-RPC 2.0 request\n */\ntype JsonRpcRequest = {\n jsonrpc: \"2.0\";\n id: string | number;\n method: string;\n params?: Record<string, unknown>;\n};\n\n/**\n * JSON-RPC 2.0 response\n */\ntype JsonRpcResponse = {\n jsonrpc: \"2.0\";\n id: string | number | null;\n result?: unknown;\n error?: {\n code: number;\n message: string;\n data?: unknown;\n };\n};\n\n/**\n * JSON-RPC 2.0 notification (no id)\n */\ntype JsonRpcNotification = {\n jsonrpc: \"2.0\";\n method: string;\n params?: Record<string, unknown>;\n};\n\n/**\n * MCP Server capabilities\n */\ntype ServerCapabilities = {\n tools?: {\n listChanged?: boolean;\n };\n};\n\n/**\n * MCP Server info\n */\ntype ServerInfo = {\n name: string;\n version: string;\n};\n\n/**\n * MCP Initialize result\n */\ntype InitializeResult = {\n protocolVersion: string;\n capabilities: ServerCapabilities;\n serverInfo: ServerInfo;\n};\n\n/**\n * MCP Tool in list format\n */\ntype McpTool = {\n name: string;\n description: string;\n inputSchema: {\n type: \"object\";\n properties: Record<string, unknown>;\n required?: string[];\n };\n};\n\n/**\n * MCP Server implementation\n */\nexport class McpServer {\n private executor: MemoryToolExecutor;\n private initialized = false;\n\n constructor(instances: Minimem | MemoryInstance | MemoryInstance[]) {\n this.executor = new MemoryToolExecutor(instances);\n }\n\n /**\n * Handle a JSON-RPC request and return a response\n */\n async handleRequest(request: JsonRpcRequest): Promise<JsonRpcResponse> {\n try {\n const result = await this.dispatch(request.method, request.params);\n return {\n jsonrpc: \"2.0\",\n id: request.id,\n result,\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n const code = err instanceof McpError ? err.code : -32603;\n return {\n jsonrpc: \"2.0\",\n id: request.id,\n error: { code, message },\n };\n }\n }\n\n /**\n * Dispatch a method call\n */\n private async dispatch(\n method: string,\n params?: Record<string, unknown>,\n ): Promise<unknown> {\n switch (method) {\n case \"initialize\":\n return this.initialize(params);\n case \"initialized\":\n // Notification, no response needed\n return {};\n case \"tools/list\":\n return this.listTools();\n case \"tools/call\":\n return this.callTool(params);\n case \"ping\":\n return {};\n default:\n throw new McpError(-32601, `Method not found: ${method}`);\n }\n }\n\n /**\n * Handle initialize request\n */\n private initialize(\n params?: Record<string, unknown>,\n ): InitializeResult {\n this.initialized = true;\n return {\n protocolVersion: PROTOCOL_VERSION,\n capabilities: {\n tools: {\n listChanged: false,\n },\n },\n serverInfo: {\n name: SERVER_NAME,\n version: SERVER_VERSION,\n },\n };\n }\n\n /**\n * List available tools\n */\n private listTools(): { tools: McpTool[] } {\n const tools: McpTool[] = MEMORY_TOOLS.map((tool) => ({\n name: tool.name,\n description: tool.description,\n inputSchema: tool.inputSchema,\n }));\n return { tools };\n }\n\n /**\n * Call a tool\n */\n private async callTool(\n params?: Record<string, unknown>,\n ): Promise<{ content: Array<{ type: string; text: string }>; isError?: boolean }> {\n if (!params?.name || typeof params.name !== \"string\") {\n throw new McpError(-32602, \"Missing tool name\");\n }\n\n const toolName = params.name;\n const toolParams = (params.arguments ?? {}) as Record<string, unknown>;\n\n const result = await this.executor.execute(toolName, toolParams);\n return result;\n }\n}\n\n/**\n * Custom error class for MCP errors\n */\nclass McpError extends Error {\n constructor(\n public code: number,\n message: string,\n ) {\n super(message);\n this.name = \"McpError\";\n }\n}\n\n/**\n * Create an MCP server for the given Minimem instance(s)\n */\nexport function createMcpServer(\n instances: Minimem | MemoryInstance | MemoryInstance[],\n): McpServer {\n return new McpServer(instances);\n}\n\n/**\n * Run the MCP server over stdio\n */\nexport async function runMcpServer(server: McpServer): Promise<void> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n terminal: false,\n });\n\n const send = (message: JsonRpcResponse | JsonRpcNotification) => {\n const json = JSON.stringify(message);\n process.stdout.write(json + \"\\n\");\n };\n\n rl.on(\"line\", async (line) => {\n if (!line.trim()) return;\n\n try {\n const request = JSON.parse(line) as JsonRpcRequest;\n\n if (request.jsonrpc !== \"2.0\") {\n send({\n jsonrpc: \"2.0\",\n id: request.id ?? null,\n error: { code: -32600, message: \"Invalid JSON-RPC version\" },\n });\n return;\n }\n\n // Handle notification (no id)\n if (request.id === undefined) {\n await server.handleRequest({ ...request, id: 0 });\n return;\n }\n\n const response = await server.handleRequest(request);\n send(response);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n send({\n jsonrpc: \"2.0\",\n id: null,\n error: { code: -32700, message: `Parse error: ${message}` },\n });\n }\n });\n\n rl.on(\"close\", () => {\n process.exit(0);\n });\n\n // Keep the process alive\n await new Promise(() => {});\n}\n\n/**\n * MCP server configuration for claude_desktop_config.json\n *\n * Example:\n * {\n * \"mcpServers\": {\n * \"minimem\": {\n * \"command\": \"node\",\n * \"args\": [\"path/to/your/mcp-server.js\"],\n * \"env\": {\n * \"MEMORY_DIR\": \"/path/to/memory\"\n * }\n * }\n * }\n * }\n */\nexport type McpServerConfig = {\n command: string;\n args: string[];\n env?: Record<string, string>;\n};\n\n/**\n * Generate MCP server config for Claude Desktop\n */\nexport function generateMcpConfig(opts: {\n serverPath: string;\n memoryDir: string;\n embeddingProvider?: \"openai\" | \"gemini\" | \"local\" | \"auto\";\n}): McpServerConfig {\n return {\n command: \"node\",\n args: [opts.serverPath],\n env: {\n MEMORY_DIR: opts.memoryDir,\n ...(opts.embeddingProvider ? { EMBEDDING_PROVIDER: opts.embeddingProvider } : {}),\n },\n };\n}\n","/**\n * MemoryIndexer - Handles file indexing and embedding management\n *\n * Responsible for:\n * - Processing memory files into chunks\n * - Computing and caching embeddings\n * - Managing file records in the database\n * - Detecting stale content\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { DatabaseSync } from \"node:sqlite\";\n\nimport {\n buildFileEntry,\n chunkMarkdown,\n hashText,\n listMemoryFiles,\n type MemoryChunk,\n type MemoryFileEntry,\n parseEmbedding,\n vectorToBlob,\n type DebugFn,\n} from \"../internal.js\";\nimport type {\n EmbeddingProvider,\n OpenAiEmbeddingClient,\n GeminiEmbeddingClient,\n} from \"../embeddings/embeddings.js\";\nimport {\n runOpenAiEmbeddingBatches,\n type OpenAiBatchRequest,\n OPENAI_BATCH_ENDPOINT,\n} from \"../embeddings/batch-openai.js\";\nimport { runGeminiEmbeddingBatches, type GeminiBatchRequest } from \"../embeddings/batch-gemini.js\";\n\nconst META_KEY = \"memory_index_meta_v1\";\nconst EMBEDDING_CACHE_TABLE = \"embedding_cache\";\nconst VECTOR_TABLE = \"chunks_vec\";\nconst FTS_TABLE = \"chunks_fts\";\nconst EMBEDDING_RETRY_MAX_ATTEMPTS = 3;\nconst EMBEDDING_RETRY_BASE_DELAY_MS = 500;\nconst EMBEDDING_RETRY_MAX_DELAY_MS = 8000;\n\nexport type IndexerConfig = {\n memoryDir: string;\n chunking: { tokens: number; overlap: number };\n cache: { enabled: boolean; maxEntries: number };\n batch: {\n enabled: boolean;\n wait: boolean;\n concurrency: number;\n pollIntervalMs: number;\n timeoutMs: number;\n };\n ftsEnabled: boolean;\n debug?: DebugFn;\n};\n\nexport type MemoryIndexMeta = {\n model: string;\n provider: string;\n providerKey?: string;\n chunkTokens: number;\n chunkOverlap: number;\n vectorDims?: number;\n};\n\nexport type IndexStats = {\n filesProcessed: number;\n chunksCreated: number;\n staleRemoved: number;\n};\n\n/**\n * MemoryIndexer handles file indexing, chunking, and embedding management\n */\nexport class MemoryIndexer {\n private readonly config: IndexerConfig;\n private readonly db: DatabaseSync;\n private readonly provider: EmbeddingProvider;\n private readonly providerKey: string;\n private readonly openAi?: OpenAiEmbeddingClient;\n private readonly gemini?: GeminiEmbeddingClient;\n\n // Vector/FTS state (shared with parent)\n private vectorState: {\n available: boolean;\n dims?: number;\n };\n private ftsAvailable: boolean;\n\n constructor(\n db: DatabaseSync,\n provider: EmbeddingProvider,\n config: IndexerConfig,\n options?: {\n openAi?: OpenAiEmbeddingClient;\n gemini?: GeminiEmbeddingClient;\n vectorState?: { available: boolean; dims?: number };\n ftsAvailable?: boolean;\n }\n ) {\n this.db = db;\n this.provider = provider;\n this.config = config;\n this.openAi = options?.openAi;\n this.gemini = options?.gemini;\n this.vectorState = options?.vectorState ?? { available: false };\n this.ftsAvailable = options?.ftsAvailable ?? false;\n this.providerKey = this.computeProviderKey();\n }\n\n /**\n * Update vector/FTS availability (called by parent when extensions load)\n */\n setVectorState(state: { available: boolean; dims?: number }): void {\n this.vectorState = state;\n }\n\n setFtsAvailable(available: boolean): void {\n this.ftsAvailable = available;\n }\n\n getVectorDims(): number | undefined {\n return this.vectorState.dims;\n }\n\n /**\n * Compute a unique key for the current provider configuration\n */\n private computeProviderKey(): string {\n const parts: string[] = [this.provider.id, this.provider.model];\n if (this.openAi) {\n parts.push(this.openAi.baseUrl);\n }\n if (this.gemini) {\n parts.push(this.gemini.baseUrl);\n }\n return hashText(parts.join(\":\"));\n }\n\n /**\n * Read index metadata from database\n */\n readMeta(): MemoryIndexMeta | null {\n try {\n const row = this.db.prepare(`SELECT value FROM meta WHERE key = ?`).get(META_KEY) as\n | { value: string }\n | undefined;\n if (!row?.value) return null;\n return JSON.parse(row.value) as MemoryIndexMeta;\n } catch {\n return null;\n }\n }\n\n /**\n * Write index metadata to database\n */\n writeMeta(meta: MemoryIndexMeta): void {\n this.db\n .prepare(`INSERT OR REPLACE INTO meta (key, value) VALUES (?, ?)`)\n .run(META_KEY, JSON.stringify(meta));\n }\n\n /**\n * Check if the index is stale by comparing file mtimes\n */\n async isStale(): Promise<boolean> {\n try {\n const files = await listMemoryFiles(this.config.memoryDir);\n\n const stored = this.db\n .prepare(`SELECT path, mtime FROM files WHERE source = ?`)\n .all(\"memory\") as Array<{ path: string; mtime: number }>;\n\n if (files.length !== stored.length) {\n this.config.debug?.(`Stale: file count changed (${stored.length} -> ${files.length})`);\n return true;\n }\n\n const storedMap = new Map(stored.map((f) => [f.path, f.mtime]));\n\n for (const absPath of files) {\n const relPath = path.relative(this.config.memoryDir, absPath).replace(/\\\\/g, \"/\");\n const storedMtime = storedMap.get(relPath);\n\n if (storedMtime === undefined) {\n this.config.debug?.(`Stale: new file ${relPath}`);\n return true;\n }\n\n const stat = await fs.stat(absPath);\n const currentMtime = Math.floor(stat.mtimeMs);\n if (currentMtime !== storedMtime) {\n this.config.debug?.(`Stale: mtime changed for ${relPath}`);\n return true;\n }\n }\n\n return false;\n } catch (err) {\n this.config.debug?.(`Stale check failed: ${String(err)}`);\n return true;\n }\n }\n\n /**\n * Check if a full reindex is needed based on configuration changes\n */\n needsFullReindex(force?: boolean): boolean {\n const meta = this.readMeta();\n return (\n force === true ||\n !meta ||\n meta.model !== this.provider.model ||\n meta.provider !== this.provider.id ||\n meta.providerKey !== this.providerKey ||\n meta.chunkTokens !== this.config.chunking.tokens ||\n meta.chunkOverlap !== this.config.chunking.overlap ||\n (this.vectorState.available && !meta?.vectorDims)\n );\n }\n\n /**\n * Index all memory files, returns stats\n */\n async indexAll(force?: boolean): Promise<IndexStats> {\n const needsFullReindex = this.needsFullReindex(force);\n const files = await listMemoryFiles(this.config.memoryDir);\n const activePaths = new Set<string>();\n let filesProcessed = 0;\n let chunksCreated = 0;\n\n for (const absPath of files) {\n const entry = await buildFileEntry(absPath, this.config.memoryDir);\n activePaths.add(entry.path);\n\n const record = this.db\n .prepare(`SELECT hash FROM files WHERE path = ? AND source = ?`)\n .get(entry.path, \"memory\") as { hash: string } | undefined;\n\n if (!needsFullReindex && record?.hash === entry.hash) {\n continue;\n }\n\n const chunkCount = await this.indexFile(entry);\n filesProcessed++;\n chunksCreated += chunkCount;\n }\n\n // Delete stale entries\n const staleRemoved = this.removeStaleEntries(activePaths);\n\n // Write meta\n this.writeMeta({\n model: this.provider.model,\n provider: this.provider.id,\n providerKey: this.providerKey,\n chunkTokens: this.config.chunking.tokens,\n chunkOverlap: this.config.chunking.overlap,\n vectorDims: this.vectorState.dims,\n });\n\n // Prune embedding cache\n this.pruneEmbeddingCacheIfNeeded();\n\n return { filesProcessed, chunksCreated, staleRemoved };\n }\n\n /**\n * Index a single file\n */\n async indexFile(entry: MemoryFileEntry): Promise<number> {\n const content = await fs.readFile(entry.absPath, \"utf-8\");\n const chunks = chunkMarkdown(content, this.config.chunking);\n\n const embeddings = await this.embedChunks(chunks);\n\n // Update files table\n this.db\n .prepare(\n `INSERT OR REPLACE INTO files (path, source, hash, mtime, size) VALUES (?, ?, ?, ?, ?)`\n )\n .run(entry.path, \"memory\", entry.hash, Math.floor(entry.mtimeMs), entry.size);\n\n // Delete old chunks\n this.deleteChunksForFile(entry.path);\n\n // Insert new chunks\n const now = Date.now();\n for (let i = 0; i < chunks.length; i++) {\n const chunk = chunks[i];\n const embedding = embeddings[i] ?? [];\n this.insertChunk(entry.path, chunk, embedding, now);\n }\n\n return chunks.length;\n }\n\n /**\n * Delete all chunks for a file\n */\n private deleteChunksForFile(filePath: string): void {\n try {\n this.db\n .prepare(\n `DELETE FROM ${VECTOR_TABLE} WHERE id IN (SELECT id FROM chunks WHERE path = ? AND source = ?)`\n )\n .run(filePath, \"memory\");\n } catch {\n // Vector table may not exist\n }\n this.db.prepare(`DELETE FROM chunks WHERE path = ? AND source = ?`).run(filePath, \"memory\");\n if (this.config.ftsEnabled && this.ftsAvailable) {\n try {\n this.db\n .prepare(`DELETE FROM ${FTS_TABLE} WHERE path = ? AND source = ? AND model = ?`)\n .run(filePath, \"memory\", this.provider.model);\n } catch {\n // FTS table may not exist\n }\n }\n }\n\n /**\n * Insert a chunk into the database\n */\n private insertChunk(\n filePath: string,\n chunk: MemoryChunk,\n embedding: number[],\n timestamp: number\n ): void {\n const chunkId = randomUUID();\n\n this.db\n .prepare(\n `INSERT INTO chunks (id, path, source, start_line, end_line, hash, model, text, embedding, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`\n )\n .run(\n chunkId,\n filePath,\n \"memory\",\n chunk.startLine,\n chunk.endLine,\n chunk.hash,\n this.provider.model,\n chunk.text,\n JSON.stringify(embedding),\n timestamp\n );\n\n // Insert into vector table if available\n if (this.vectorState.available && embedding.length > 0) {\n if (!this.vectorState.dims) {\n this.vectorState.dims = embedding.length;\n this.ensureVectorTable(embedding.length);\n }\n try {\n this.db\n .prepare(`INSERT INTO ${VECTOR_TABLE} (id, embedding) VALUES (?, ?)`)\n .run(chunkId, vectorToBlob(embedding));\n } catch {\n // Vector insertion may fail\n }\n }\n\n // Insert into FTS table if available\n if (this.config.ftsEnabled && this.ftsAvailable) {\n try {\n this.db\n .prepare(\n `INSERT INTO ${FTS_TABLE} (text, id, path, source, model, start_line, end_line)\n VALUES (?, ?, ?, ?, ?, ?, ?)`\n )\n .run(\n chunk.text,\n chunkId,\n filePath,\n \"memory\",\n this.provider.model,\n chunk.startLine,\n chunk.endLine\n );\n } catch {\n // FTS insertion may fail\n }\n }\n }\n\n /**\n * Remove stale file entries that no longer exist\n */\n private removeStaleEntries(activePaths: Set<string>): number {\n const staleRows = this.db\n .prepare(`SELECT path FROM files WHERE source = ?`)\n .all(\"memory\") as Array<{ path: string }>;\n\n let removed = 0;\n for (const stale of staleRows) {\n if (activePaths.has(stale.path)) continue;\n\n this.db\n .prepare(`DELETE FROM files WHERE path = ? AND source = ?`)\n .run(stale.path, \"memory\");\n this.deleteChunksForFile(stale.path);\n removed++;\n }\n\n return removed;\n }\n\n /**\n * Create vector table with the given dimensions\n */\n ensureVectorTable(dimensions: number): void {\n if (!this.vectorState.available) return;\n try {\n this.db.exec(\n `CREATE VIRTUAL TABLE IF NOT EXISTS ${VECTOR_TABLE} USING vec0(\n id TEXT PRIMARY KEY,\n embedding FLOAT[${dimensions}]\n )`\n );\n } catch (err) {\n this.config.debug?.(`vector table creation failed: ${String(err)}`);\n }\n }\n\n /**\n * Get embeddings for chunks, using cache when available\n */\n async embedChunks(chunks: MemoryChunk[]): Promise<number[][]> {\n if (chunks.length === 0) return [];\n\n const hashes = chunks.map((c) => c.hash);\n const cached = this.loadEmbeddingCache(hashes);\n const missing: Array<{ index: number; chunk: MemoryChunk }> = [];\n\n for (let i = 0; i < chunks.length; i++) {\n if (!cached.has(hashes[i])) {\n missing.push({ index: i, chunk: chunks[i] });\n }\n }\n\n if (missing.length > 0) {\n const texts = missing.map((m) => m.chunk.text);\n const newEmbeddings = await this.embedBatchWithRetry(texts);\n\n for (let i = 0; i < missing.length; i++) {\n const hash = missing[i].chunk.hash;\n const embedding = newEmbeddings[i] ?? [];\n cached.set(hash, embedding);\n this.upsertEmbeddingCache(hash, embedding);\n }\n }\n\n return hashes.map((h) => cached.get(h) ?? []);\n }\n\n /**\n * Embed texts with retry logic\n */\n private async embedBatchWithRetry(texts: string[]): Promise<number[][]> {\n if (texts.length === 0) return [];\n\n // Try batch API first if enabled\n if (this.config.batch.enabled) {\n try {\n return await this.embedWithBatchApi(texts);\n } catch (err) {\n this.config.debug?.(`batch embedding failed, falling back to direct: ${String(err)}`);\n }\n }\n\n // Fall back to direct embedding\n let lastError: Error | null = null;\n for (let attempt = 0; attempt < EMBEDDING_RETRY_MAX_ATTEMPTS; attempt++) {\n try {\n return await this.provider.embedBatch(texts);\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err));\n if (attempt < EMBEDDING_RETRY_MAX_ATTEMPTS - 1) {\n const delay = Math.min(\n EMBEDDING_RETRY_MAX_DELAY_MS,\n EMBEDDING_RETRY_BASE_DELAY_MS * Math.pow(2, attempt)\n );\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n }\n throw lastError;\n }\n\n /**\n * Use batch API for large embedding jobs\n */\n private async embedWithBatchApi(texts: string[]): Promise<number[][]> {\n if (this.openAi) {\n const requests: OpenAiBatchRequest[] = texts.map((text, i) => ({\n custom_id: `chunk-${i}`,\n method: \"POST\",\n url: OPENAI_BATCH_ENDPOINT,\n body: { model: this.openAi!.model, input: text },\n }));\n\n const results = await runOpenAiEmbeddingBatches({\n openAi: this.openAi,\n source: \"minimem\",\n requests,\n wait: this.config.batch.wait,\n pollIntervalMs: this.config.batch.pollIntervalMs,\n timeoutMs: this.config.batch.timeoutMs,\n concurrency: this.config.batch.concurrency,\n debug: this.config.debug,\n });\n\n return texts.map((_, i) => results.get(`chunk-${i}`) ?? []);\n }\n\n if (this.gemini) {\n const requests: GeminiBatchRequest[] = texts.map((text, i) => ({\n custom_id: `chunk-${i}`,\n content: { parts: [{ text }] },\n taskType: \"RETRIEVAL_DOCUMENT\",\n }));\n\n const results = await runGeminiEmbeddingBatches({\n gemini: this.gemini,\n source: \"minimem\",\n requests,\n wait: this.config.batch.wait,\n pollIntervalMs: this.config.batch.pollIntervalMs,\n timeoutMs: this.config.batch.timeoutMs,\n concurrency: this.config.batch.concurrency,\n debug: this.config.debug,\n });\n\n return texts.map((_, i) => results.get(`chunk-${i}`) ?? []);\n }\n\n throw new Error(\"Batch API not available for local embeddings\");\n }\n\n /**\n * Load embeddings from cache\n */\n private loadEmbeddingCache(hashes: string[]): Map<string, number[]> {\n const result = new Map<string, number[]>();\n if (!this.config.cache.enabled || hashes.length === 0) return result;\n\n const placeholders = hashes.map(() => \"?\").join(\",\");\n const rows = this.db\n .prepare(\n `SELECT hash, embedding FROM ${EMBEDDING_CACHE_TABLE}\n WHERE provider = ? AND model = ? AND provider_key = ? AND hash IN (${placeholders})`\n )\n .all(this.provider.id, this.provider.model, this.providerKey, ...hashes) as Array<{\n hash: string;\n embedding: string;\n }>;\n\n const now = Date.now();\n for (const row of rows) {\n result.set(row.hash, parseEmbedding(row.embedding));\n // Touch for LRU\n this.db\n .prepare(\n `UPDATE ${EMBEDDING_CACHE_TABLE} SET updated_at = ?\n WHERE provider = ? AND model = ? AND provider_key = ? AND hash = ?`\n )\n .run(now, this.provider.id, this.provider.model, this.providerKey, row.hash);\n }\n\n return result;\n }\n\n /**\n * Save embedding to cache\n */\n private upsertEmbeddingCache(hash: string, embedding: number[]): void {\n if (!this.config.cache.enabled) return;\n const now = Date.now();\n this.db\n .prepare(\n `INSERT OR REPLACE INTO ${EMBEDDING_CACHE_TABLE}\n (provider, model, provider_key, hash, embedding, dims, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?)`\n )\n .run(\n this.provider.id,\n this.provider.model,\n this.providerKey,\n hash,\n JSON.stringify(embedding),\n embedding.length,\n now\n );\n }\n\n /**\n * Prune old cache entries if over limit\n */\n private pruneEmbeddingCacheIfNeeded(): void {\n if (!this.config.cache.enabled) return;\n const row = this.db\n .prepare(`SELECT COUNT(*) as count FROM ${EMBEDDING_CACHE_TABLE}`)\n .get() as { count: number };\n if (row.count <= this.config.cache.maxEntries) return;\n\n const excess = row.count - this.config.cache.maxEntries;\n this.db\n .prepare(\n `DELETE FROM ${EMBEDDING_CACHE_TABLE}\n WHERE rowid IN (\n SELECT rowid FROM ${EMBEDDING_CACHE_TABLE}\n ORDER BY updated_at ASC\n LIMIT ?\n )`\n )\n .run(excess);\n }\n}\n","/**\n * MemorySearcher - Handles search operations\n *\n * Responsible for:\n * - Executing vector searches\n * - Executing keyword (FTS) searches\n * - Merging results with hybrid scoring\n */\n\nimport type { DatabaseSync } from \"node:sqlite\";\n\nimport { bm25RankToScore, buildFtsQuery, mergeHybridResults } from \"../search/hybrid.js\";\nimport { searchKeyword, searchVector } from \"../search/search.js\";\nimport type { EmbeddingProvider } from \"../embeddings/embeddings.js\";\nimport type { DebugFn } from \"../internal.js\";\n\nconst SNIPPET_MAX_CHARS = 700;\nconst VECTOR_TABLE = \"chunks_vec\";\nconst FTS_TABLE = \"chunks_fts\";\nconst EMBEDDING_QUERY_TIMEOUT_REMOTE_MS = 60_000;\nconst EMBEDDING_QUERY_TIMEOUT_LOCAL_MS = 5 * 60_000;\n\nexport type SearchConfig = {\n hybrid: {\n enabled: boolean;\n vectorWeight: number;\n textWeight: number;\n candidateMultiplier: number;\n };\n query: {\n maxResults: number;\n minScore: number;\n };\n debug?: DebugFn;\n};\n\nexport type SearchResult = {\n path: string;\n startLine: number;\n endLine: number;\n score: number;\n snippet: string;\n};\n\n/**\n * MemorySearcher handles search queries against the indexed memory\n */\nexport class MemorySearcher {\n private readonly db: DatabaseSync;\n private readonly provider: EmbeddingProvider;\n private readonly config: SearchConfig;\n\n // State from parent\n private vectorState: {\n available: boolean;\n dims?: number;\n };\n private ftsAvailable: boolean;\n\n // Callback to ensure vector is ready\n private ensureVectorReadyFn?: (dims?: number) => Promise<boolean>;\n\n constructor(\n db: DatabaseSync,\n provider: EmbeddingProvider,\n config: SearchConfig,\n options?: {\n vectorState?: { available: boolean; dims?: number };\n ftsAvailable?: boolean;\n ensureVectorReady?: (dims?: number) => Promise<boolean>;\n }\n ) {\n this.db = db;\n this.provider = provider;\n this.config = config;\n this.vectorState = options?.vectorState ?? { available: false };\n this.ftsAvailable = options?.ftsAvailable ?? false;\n this.ensureVectorReadyFn = options?.ensureVectorReady;\n }\n\n /**\n * Update vector/FTS availability (called by parent when extensions load)\n */\n setVectorState(state: { available: boolean; dims?: number }): void {\n this.vectorState = state;\n }\n\n setFtsAvailable(available: boolean): void {\n this.ftsAvailable = available;\n }\n\n /**\n * Execute a search query\n */\n async search(\n query: string,\n opts?: { maxResults?: number; minScore?: number }\n ): Promise<SearchResult[]> {\n const cleaned = query.trim();\n if (!cleaned) return [];\n\n const minScore = opts?.minScore ?? this.config.query.minScore;\n const maxResults = opts?.maxResults ?? this.config.query.maxResults;\n const candidates = Math.min(\n 200,\n Math.max(1, Math.floor(maxResults * this.config.hybrid.candidateMultiplier))\n );\n\n const sourceFilter = { sql: \"\", params: [] as string[] };\n\n // Execute keyword search if hybrid is enabled\n const keywordResults =\n this.config.hybrid.enabled && this.ftsAvailable\n ? await searchKeyword({\n db: this.db,\n ftsTable: FTS_TABLE,\n providerModel: this.provider.model,\n query: cleaned,\n limit: candidates,\n snippetMaxChars: SNIPPET_MAX_CHARS,\n sourceFilter,\n buildFtsQuery,\n bm25RankToScore,\n }).catch(() => [])\n : [];\n\n // Embed query and execute vector search\n const queryVec = await this.embedQueryWithTimeout(cleaned);\n const hasVector = queryVec.some((v) => v !== 0);\n const vectorResults = hasVector\n ? await searchVector({\n db: this.db,\n vectorTable: VECTOR_TABLE,\n providerModel: this.provider.model,\n queryVec,\n limit: candidates,\n snippetMaxChars: SNIPPET_MAX_CHARS,\n ensureVectorReady: (dims) => this.ensureVectorReady(dims),\n sourceFilterVec: sourceFilter,\n sourceFilterChunks: sourceFilter,\n }).catch(() => [])\n : [];\n\n // If hybrid is disabled, return vector results only\n if (!this.config.hybrid.enabled) {\n return vectorResults\n .filter((entry) => entry.score >= minScore)\n .slice(0, maxResults)\n .map((r) => ({\n path: r.path,\n startLine: r.startLine,\n endLine: r.endLine,\n score: r.score,\n snippet: r.snippet,\n }));\n }\n\n // Merge results with hybrid scoring\n const merged = mergeHybridResults({\n vector: vectorResults.map((r) => ({\n id: r.id,\n path: r.path,\n startLine: r.startLine,\n endLine: r.endLine,\n source: r.source,\n snippet: r.snippet,\n vectorScore: r.score,\n })),\n keyword: keywordResults.map((r) => ({\n id: r.id,\n path: r.path,\n startLine: r.startLine,\n endLine: r.endLine,\n source: r.source,\n snippet: r.snippet,\n textScore: r.textScore,\n })),\n vectorWeight: this.config.hybrid.vectorWeight,\n textWeight: this.config.hybrid.textWeight,\n });\n\n return merged\n .filter((entry) => entry.score >= minScore)\n .slice(0, maxResults)\n .map((r) => ({\n path: r.path,\n startLine: r.startLine,\n endLine: r.endLine,\n score: r.score,\n snippet: r.snippet,\n }));\n }\n\n /**\n * Embed a query string with timeout\n */\n private async embedQueryWithTimeout(text: string): Promise<number[]> {\n const timeout =\n this.provider.id === \"local\"\n ? EMBEDDING_QUERY_TIMEOUT_LOCAL_MS\n : EMBEDDING_QUERY_TIMEOUT_REMOTE_MS;\n\n return Promise.race([\n this.provider.embedQuery(text),\n new Promise<number[]>((_, reject) =>\n setTimeout(() => reject(new Error(\"embedding query timeout\")), timeout)\n ),\n ]);\n }\n\n /**\n * Ensure vector extension is ready\n */\n private async ensureVectorReady(dims?: number): Promise<boolean> {\n if (this.vectorState.available) return true;\n if (this.ensureVectorReadyFn) {\n return this.ensureVectorReadyFn(dims);\n }\n return false;\n }\n}\n"],"mappings":"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","names":["path","path","payload","provider","client","text","runWithConcurrency","path","path","randomUUID","fs","path","META_KEY","EMBEDDING_CACHE_TABLE","VECTOR_TABLE","FTS_TABLE","EMBEDDING_RETRY_MAX_ATTEMPTS","EMBEDDING_RETRY_BASE_DELAY_MS","EMBEDDING_RETRY_MAX_DELAY_MS","path","fs","randomUUID","SNIPPET_MAX_CHARS","VECTOR_TABLE","FTS_TABLE","EMBEDDING_QUERY_TIMEOUT_REMOTE_MS","EMBEDDING_QUERY_TIMEOUT_LOCAL_MS"]}
|