minimem 0.0.7 → 0.1.1

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/minimem.ts","../../src/internal.ts","../../src/search/hybrid.ts","../../src/search/search.ts","../../src/db/schema.ts","../../src/session.ts","../../src/search/graph.ts","../../src/db/sqlite-vec.ts","../../src/embeddings/embeddings.ts","../../src/embeddings/batch-openai.ts","../../src/embeddings/batch-gemini.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport fs from \"node:fs/promises\";\nimport fsSync from \"node:fs\";\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\n/**\n * Resolve which subdirectory holds minimem config/data.\n * Priority: MINIMEM_CONFIG_DIR env var > contained (config.json at root) > .swarm/minimem > .minimem\n */\nfunction resolveMinimemSubdir(memoryDir: string): string {\n const envDir = process.env.MINIMEM_CONFIG_DIR;\n if (envDir) return envDir;\n // Contained layout: config.json directly in memoryDir (no subdir)\n if (fsSync.existsSync(path.join(memoryDir, \"config.json\"))) return \".\";\n const swarmDir = path.join(memoryDir, \".swarm\", \"minimem\");\n if (fsSync.existsSync(path.join(swarmDir, \"config.json\"))) return path.join(\".swarm\", \"minimem\");\n return \".minimem\";\n}\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, resolveMinimemSubdir(this.memoryDir), \"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","import crypto from \"node:crypto\";\nimport fsSync from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\n/**\n * Debug function type for optional logging\n */\nexport type DebugFn = (message: string, data?: Record<string, unknown>) => void;\n\n/**\n * Log an error with context (for debugging).\n * Only logs if a debug function is provided.\n *\n * @param context - A short identifier for where the error occurred\n * @param error - The error object or message\n * @param debug - Optional debug function to log to\n */\nexport function logError(\n context: string,\n error: unknown,\n debug?: DebugFn\n): void {\n if (!debug) return;\n\n const message = error instanceof Error ? error.message : String(error);\n debug(`[${context}] Error: ${message}`);\n}\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\n/**\n * Ensure a directory exists, creating it if necessary.\n *\n * @param dir - The directory path to ensure exists\n * @param debug - Optional debug function for logging errors\n * @returns The directory path\n */\nexport function ensureDir(dir: string, debug?: DebugFn): string {\n try {\n fsSync.mkdirSync(dir, { recursive: true });\n } catch (error) {\n // Only swallow EEXIST errors (directory already exists)\n // Log other errors for debugging\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code !== \"EEXIST\") {\n logError(\"ensureDir\", error, debug);\n }\n }\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 const hasUpper = await exists(memoryFile);\n const hasLower = await exists(altMemoryFile);\n\n // Prevent ambiguity: both MEMORY.md and memory.md cannot coexist\n // (unless they resolve to the same file on case-insensitive filesystems)\n if (hasUpper && hasLower) {\n let upperReal = memoryFile;\n let lowerReal = altMemoryFile;\n try { upperReal = await fs.realpath(memoryFile); } catch {}\n try { lowerReal = await fs.realpath(altMemoryFile); } catch {}\n if (upperReal !== lowerReal) {\n throw new Error(\n `Both MEMORY.md and memory.md exist in ${memoryDir}. ` +\n `Please remove one to avoid ambiguity.`\n );\n }\n // Same file (case-insensitive FS) — only include once\n result.push(memoryFile);\n } else if (hasUpper) {\n result.push(memoryFile);\n } else if (hasLower) {\n result.push(altMemoryFile);\n }\n\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\n/**\n * Strip content between <private>...</private> tags.\n * Replaces private blocks with the same number of empty lines to preserve line numbering.\n */\nexport function stripPrivateContent(content: string): string {\n return content.replace(/<private>[\\s\\S]*?<\\/private>/gi, (match) => {\n const lineCount = match.split(\"\\n\").length;\n return \"\\n\".repeat(lineCount - 1);\n });\n}\n\nexport function chunkMarkdown(\n content: string,\n chunking: { tokens: number; overlap: number },\n): MemoryChunk[] {\n const stripped = stripPrivateContent(content);\n const lines = stripped.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\n/**\n * Extract metadata from a chunk's text content.\n * Looks for HTML comments like <!-- type: decision --> in the chunk.\n */\nexport function extractChunkMetadata(text: string): { type?: string } {\n const typeMatch = text.match(/<!--\\s*type:\\s*([\\w-]+)\\s*-->/i);\n return typeMatch ? { type: typeMatch[1].toLowerCase() } : {};\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\n/**\n * Convert a numeric embedding vector to a Buffer suitable for sqlite-vec storage.\n * Uses Float32 encoding, which is the format expected by sqlite-vec's vector functions.\n */\nexport function vectorToBlob(embedding: number[]): Buffer {\n return Buffer.from(new Float32Array(embedding).buffer);\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","/**\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 * Source provenance for a knowledge entry\n */\nexport type KnowledgeSource = {\n origin?: string;\n trajectories?: string[];\n agentId?: string;\n};\n\n/**\n * A directional link from this entry to another knowledge node\n */\nexport type KnowledgeLink = {\n target: string;\n relation: string;\n layer?: 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 /** Knowledge node identifier */\n id?: string;\n /** Knowledge entry type */\n type?: \"observation\" | \"entity\" | \"domain-summary\" | string;\n /** Domain tags for this knowledge entry */\n domain?: string[];\n /** Entity references in this knowledge entry */\n entities?: string[];\n /** Confidence score 0-1 */\n confidence?: number;\n /** Source provenance */\n source?: KnowledgeSource;\n /** Links to other knowledge nodes */\n links?: KnowledgeLink[];\n /** ID of the entry this supersedes */\n supersedes?: string | null;\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 *\n * **Limitations** (by design — keeps the dependency count at zero):\n * - Does not handle multi-line strings (block scalars `|` / `>`)\n * - Does not preserve comments\n * - Keys must be simple `\\w+` identifiers (no quoted or special-char keys)\n *\n * Supports:\n * - Multi-level nesting (objects within objects)\n * - Inline arrays `[a, b]`\n * - YAML list items with `- ` syntax (including `- {key: val}` objects)\n * - Null values via `~` or `null`\n */\nfunction parseSimpleYaml(yaml: string): MemoryFrontmatter {\n const lines = yaml.split(\"\\n\");\n return parseYamlBlock(lines, 0, 0, lines.length).value as MemoryFrontmatter;\n}\n\n/**\n * Parse a block of YAML lines at a given indentation level into an object.\n * Returns the parsed value and the line index where parsing stopped.\n */\nfunction parseYamlBlock(\n lines: string[],\n indent: number,\n startIdx: number,\n endIdx: number,\n): { value: Record<string, unknown>; nextIdx: number } {\n const result: Record<string, unknown> = {};\n let i = startIdx;\n\n while (i < endIdx) {\n const line = lines[i];\n if (!line || !line.trim()) {\n i++;\n continue;\n }\n\n const lineIndent = getIndent(line);\n // If we've dedented back beyond our level, stop\n if (lineIndent < indent) break;\n // Skip lines indented deeper than expected (shouldn't happen at top of block)\n if (lineIndent > indent) {\n i++;\n continue;\n }\n\n // Match a key: value line\n const keyMatch = line.match(/^(\\s*)([\\w-]+):\\s*(.*)?$/);\n if (!keyMatch) {\n i++;\n continue;\n }\n\n const [, , key, rawValue] = keyMatch;\n const value = rawValue?.trim() ?? \"\";\n\n if (value === \"\" || value === undefined) {\n // Could be an object or a list starting on next lines\n const nextNonEmpty = findNextNonEmptyLine(lines, i + 1, endIdx);\n if (nextNonEmpty < endIdx) {\n const nextLine = lines[nextNonEmpty]!;\n const nextIndent = getIndent(nextLine);\n if (nextIndent > indent) {\n // Check if it's a list (starts with \"- \")\n if (nextLine.trimStart().startsWith(\"- \")) {\n const listResult = parseYamlList(lines, nextIndent, i + 1, endIdx);\n result[key] = listResult.value;\n i = listResult.nextIdx;\n } else {\n // Nested object\n const blockResult = parseYamlBlock(lines, nextIndent, i + 1, endIdx);\n result[key] = blockResult.value;\n i = blockResult.nextIdx;\n }\n continue;\n }\n }\n // Empty value, no nested content\n result[key] = null;\n i++;\n } else {\n result[key] = parseYamlValue(value);\n i++;\n }\n }\n\n return { value: result, nextIdx: i };\n}\n\n/**\n * Parse a YAML list (lines starting with \"- \") at a given indentation level.\n */\nfunction parseYamlList(\n lines: string[],\n indent: number,\n startIdx: number,\n endIdx: number,\n): { value: unknown[]; nextIdx: number } {\n const result: unknown[] = [];\n let i = startIdx;\n\n while (i < endIdx) {\n const line = lines[i];\n if (!line || !line.trim()) {\n i++;\n continue;\n }\n\n const lineIndent = getIndent(line);\n if (lineIndent < indent) break;\n if (lineIndent > indent) {\n i++;\n continue;\n }\n\n const trimmed = line.trimStart();\n if (!trimmed.startsWith(\"- \")) break;\n\n // Get content after \"- \"\n const itemContent = trimmed.slice(2).trim();\n\n if (itemContent === \"\" || itemContent === undefined) {\n // Sub-block under this list item\n const nextNonEmpty = findNextNonEmptyLine(lines, i + 1, endIdx);\n if (nextNonEmpty < endIdx) {\n const nextIndent = getIndent(lines[nextNonEmpty]!);\n if (nextIndent > indent) {\n const blockResult = parseYamlBlock(lines, nextIndent, i + 1, endIdx);\n result.push(blockResult.value);\n i = blockResult.nextIdx;\n continue;\n }\n }\n result.push(null);\n i++;\n } else {\n // Check for inline key: value (object item like \"- target: foo\")\n const kvMatch = itemContent.match(/^([\\w-]+):\\s*(.*)$/);\n if (kvMatch) {\n // This list item is an object — collect all keys at this item's indent + 2\n const obj: Record<string, unknown> = {};\n const [, firstKey, firstVal] = kvMatch;\n obj[firstKey] = parseYamlValue(firstVal?.trim() ?? \"\");\n\n // Look for continuation keys indented further\n const itemKeyIndent = indent + 2;\n let j = i + 1;\n while (j < endIdx) {\n const nextLine = lines[j];\n if (!nextLine || !nextLine.trim()) {\n j++;\n continue;\n }\n const nextLineIndent = getIndent(nextLine);\n if (nextLineIndent < itemKeyIndent) break;\n if (nextLineIndent === itemKeyIndent) {\n const nextKv = nextLine.match(/^\\s*([\\w-]+):\\s*(.*)$/);\n if (nextKv) {\n const [, nk, nv] = nextKv;\n obj[nk] = parseYamlValue(nv?.trim() ?? \"\");\n j++;\n continue;\n }\n }\n break;\n }\n result.push(obj);\n i = j;\n } else {\n result.push(parseYamlValue(itemContent));\n i++;\n }\n }\n }\n\n return { value: result, nextIdx: i };\n}\n\nfunction getIndent(line: string): number {\n const match = line.match(/^(\\s*)/);\n return match ? match[1].length : 0;\n}\n\nfunction findNextNonEmptyLine(lines: string[], from: number, end: number): number {\n for (let i = from; i < end; i++) {\n if (lines[i]?.trim()) return i;\n }\n return end;\n}\n\n/**\n * Parse a YAML value (handles strings, numbers, booleans, null, arrays)\n */\nfunction parseYamlValue(value: string): unknown {\n // Empty string\n if (value === \"\") return null;\n\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 // Null\n if (value === \"null\" || value === \"~\") return null;\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 if (inner.trim() === \"\") return [];\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.id) {\n lines.push(`id: ${frontmatter.id}`);\n }\n\n if (frontmatter.type) {\n lines.push(`type: ${frontmatter.type}`);\n }\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 if (frontmatter.domain && frontmatter.domain.length > 0) {\n lines.push(`domain: [${frontmatter.domain.join(\", \")}]`);\n }\n\n if (frontmatter.entities && frontmatter.entities.length > 0) {\n lines.push(`entities: [${frontmatter.entities.join(\", \")}]`);\n }\n\n if (frontmatter.confidence !== undefined) {\n lines.push(`confidence: ${frontmatter.confidence}`);\n }\n\n if (frontmatter.source) {\n lines.push(\"source:\");\n if (frontmatter.source.origin) lines.push(` origin: ${frontmatter.source.origin}`);\n if (frontmatter.source.trajectories && frontmatter.source.trajectories.length > 0) {\n lines.push(` trajectories: [${frontmatter.source.trajectories.join(\", \")}]`);\n }\n if (frontmatter.source.agentId) lines.push(` agentId: ${frontmatter.source.agentId}`);\n }\n\n if (frontmatter.links && frontmatter.links.length > 0) {\n lines.push(\"links:\");\n for (const link of frontmatter.links) {\n lines.push(` - target: ${link.target}`);\n lines.push(` relation: ${link.relation}`);\n if (link.layer) lines.push(` layer: ${link.layer}`);\n }\n }\n\n if (frontmatter.supersedes !== undefined) {\n lines.push(`supersedes: ${frontmatter.supersedes === null ? \"~\" : frontmatter.supersedes}`);\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","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"],"mappings":"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","names":["fs","fsSync","path","path","fsSync","path","os","payload","provider","client","text","runWithConcurrency","fsSync","path","path","fs"]}