import { ContentType, IndexStats, KnowledgeOrigin, KnowledgeRecord, SearchResult, SourceType } from "../../core/dist/index.js"; import BetterSqlite3 from "better-sqlite3"; //#region packages/store/src/graph-store.interface.d.ts /** * Knowledge graph store abstraction — typed nodes + edges for entity-relationship storage. * Complements the vector store: vector search finds similar content, * graph traversal finds connected concepts. */ /** A node in the knowledge graph (entity, concept, service, etc.) */ interface GraphNode { /** Unique identifier */ id: string; /** Node type (e.g., 'entity', 'service', 'api', 'concept', 'decision') */ type: string; /** Display name */ name: string; /** Arbitrary properties */ properties: Record; /** Back-link to KnowledgeRecord.id that produced this node */ sourceRecordId?: string; /** Source file path (for cleanup on re-index) */ sourcePath?: string; /** ISO timestamp */ createdAt?: string; /** Community/cluster label from community detection */ community?: string; } /** An edge connecting two nodes */ interface GraphEdge { /** Unique identifier */ id: string; /** Source node ID */ fromId: string; /** Target node ID */ toId: string; /** Relationship type (e.g., 'depends-on', 'implements', 'calls', 'affects') */ type: string; /** Optional weight (0-1) */ weight?: number; /** Optional confidence score (0-1) for relationship certainty */ confidence?: number; /** Arbitrary properties */ properties?: Record; } /** Options for graph traversal */ interface GraphTraversalOptions { /** Relationship type filter — single type or array of types */ edgeType?: string | string[]; /** Max traversal depth (default: 2) */ maxDepth?: number; /** Direction: outgoing from start, incoming to start, or both */ direction?: 'outgoing' | 'incoming' | 'both'; /** Max total nodes returned (default: 50) */ limit?: number; } /** Result of a graph traversal */ interface GraphTraversalResult { nodes: GraphNode[]; edges: GraphEdge[]; } /** Graph statistics */ interface GraphStats { nodeCount: number; edgeCount: number; nodeTypes: Record; edgeTypes: Record; /** Community label → node IDs */ communities?: Record; /** Number of detected communities */ communityCount?: number; } /** Result of graph validation */ interface GraphValidationResult { valid: boolean; orphanNodes: string[]; danglingEdges: Array<{ edgeId: string; missingNodeId: string; }>; stats: GraphStats; } /** Depth-grouped traversal result — nodes bucketed by distance from start */ interface DepthGroupedResult { [depth: number]: GraphNode[]; } /** Execution flow / process info */ interface ProcessInfo { id: string; entryNodeId: string; label: string; properties: Record; steps: string[]; createdAt?: string; } /** 360-degree symbol view — full context around a node */ interface Symbol360 { node: GraphNode; incoming: GraphEdge[]; outgoing: GraphEdge[]; community: string | null; processes: ProcessInfo[]; } /** Knowledge graph store interface */ interface IGraphStore { /** Initialize the store (create tables, indices) */ initialize(): Promise; /** Add or update a single node */ upsertNode(node: GraphNode): Promise; /** Add or update a single edge */ upsertEdge(edge: GraphEdge): Promise; /** Batch add/update nodes */ upsertNodes(nodes: GraphNode[]): Promise; /** Batch add/update edges */ upsertEdges(edges: GraphEdge[]): Promise; /** Get a node by ID */ getNode(id: string): Promise; /** Batch-get nodes by IDs */ getNodes(ids: string[]): Promise; /** Get direct neighbors of a node */ getNeighbors(nodeId: string, options?: GraphTraversalOptions): Promise; /** Multi-hop traversal from a starting node */ traverse(startId: string, options?: GraphTraversalOptions): Promise; /** Find nodes by type and/or name pattern */ findNodes(filter: { type?: string; namePattern?: string; sourcePath?: string; limit?: number; }): Promise; /** Find edges by type between optional node filters */ findEdges(filter: { type?: string; fromId?: string; toId?: string; limit?: number; }): Promise; /** Delete a node and all its edges */ deleteNode(id: string): Promise; /** Delete all nodes/edges originating from a source path */ deleteBySourcePath(sourcePath: string): Promise; /** Delete all nodes and edges (full reset) */ clear(): Promise; /** Get graph statistics */ getStats(): Promise; /** Validate graph integrity — check for orphan nodes and dangling edges */ validate(): Promise; /** Set community label on a node */ setNodeCommunity(nodeId: string, community: string): Promise; /** Run label-propagation community detection, returns community -> nodeId[] map */ detectCommunities(): Promise>; /** Trace execution flow from entry node via outgoing 'calls' edges, store as process */ traceProcess(entryNodeId: string, label: string): Promise; /** List processes, optionally filtered to those containing a specific node */ getProcesses(nodeId?: string): Promise; /** Delete a process and its steps */ deleteProcess(processId: string): Promise; /** Traverse with results grouped by depth: { 1: [...], 2: [...], 3: [...] } */ depthGroupedTraversal(startId: string, maxDepth?: number, options?: GraphTraversalOptions): Promise; /** Cohesion score for a community: internal edges / (internal + external edges) */ getCohesionScore(community: string): Promise; /** 360-degree view of a node: incoming, outgoing, community, processes */ getSymbol360(nodeId: string): Promise; /** Release cached memory without closing the connection (lightweight idle cleanup). */ releaseMemory?(): void; /** Close the store */ close(): Promise; } //#endregion //#region packages/store/src/sqlite-adapter.types.d.ts /** Which legacy adapter implementation is active */ type SqliteAdapterType = 'node-sqlite' | 'better-sqlite3' | 'sql.js'; /** * Legacy SQLite adapter interface. * * Prefer SqlDatabase for new code. ISqliteAdapter exists for backward * compatibility with consumers that were written before SqlDatabase. */ interface ISqliteAdapter { /** Which adapter implementation is active */ readonly type: SqliteAdapterType; /** * True when the underlying engine can execute vector-search queries * (native SQLite with the sqlite-vec extension loaded). False on sql.js or * when extension loading failed. */ readonly vectorCapable: boolean; /** Open or create the database at the given file path */ open(dbPath: string): Promise; /** Execute DDL or multi-statement SQL (CREATE TABLE, BEGIN, COMMIT, etc.) */ exec(sql: string): void; /** Set a PRAGMA value */ pragma(pragma: string): void; /** Run a parameterized SELECT, return all rows */ queryAll>(sql: string, params?: unknown[]): T[]; /** Run a parameterized INSERT/UPDATE/DELETE */ run(sql: string, params?: unknown[]): void; /** Flush to disk — no-op for file-backed engines, required for in-memory engines */ flush(): void; /** Close the database connection */ close(): void; } //#endregion //#region packages/store/src/sqlite-adapter.d.ts /** * Create the project's SQLite adapter. * * Prefers better-sqlite3 (native, mmap-backed, supports sqlite-vec). Falls * back to sql.js (WASM, vector search disabled) if the native binary cannot * be loaded — typically because the platform has no prebuild and the native * compile failed during install. In that case the consumer should disable * vector-dependent code paths via `adapter.vectorCapable`. * * ## Auto-healing (ABI mismatch) * * When the Node.js version changes (e.g., Node 24 → Node 22), the native * .node binary is incompatible. This adapter detects the mismatch BEFORE * loading the module in-process (via a child process probe) so the file * remains unlocked and can be deleted + rebuilt cleanly. */ declare function createSqliteAdapter(dbPath: string): Promise; /** * Force-create a sql.js adapter (used by tests that need to assert fallback * behavior without monkey-patching `require`). */ declare function createSqlJsAdapter(dbPath: string): Promise; //#endregion //#region packages/store/src/migrations.d.ts type MigrationDb = Pick; interface Migration { version: number; name: string; up: (db: MigrationDb) => void; } declare function runMigrations(db: MigrationDb, migrations: readonly Migration[]): void; declare const allMigrations: readonly Migration[]; //#endregion //#region packages/store/src/state-partition.d.ts type PartitionKind = 'content' | 'control'; interface StatePartitionConfig { /** When true, control-state data can be routed to a separate database. */ splitEnabled: boolean; /** Path for content DB (knowledge, vectors, graph). Defaults to the main DB path. */ contentDbPath?: string; /** * Path for control DB (sessions, stash, checkpoints, signals). * Defaults to the main DB path unless split mode derives a sibling control DB. */ controlDbPath?: string; } interface ResolvedStatePartitionConfig { splitEnabled: boolean; contentDbPath: string; controlDbPath: string; } declare const CONTROL_TABLES: Set; /** * Determines which partition a table belongs to. */ declare function getTablePartition(tableName: string): PartitionKind; declare function resolveStatePartitionConfig(mainDbPath: string, config?: Partial): ResolvedStatePartitionConfig; declare function readStatePartitionConfigFromEnv(mainDbPath: string, env?: NodeJS.ProcessEnv): ResolvedStatePartitionConfig; //#endregion //#region packages/store/src/partition-migrator.d.ts /** * Migrates from single-DB to split-DB mode. * Copies control tables to a new database. * Safe to run multiple times (idempotent). */ declare function migrateToSplitState(config: StatePartitionConfig): Promise; //#endregion //#region packages/store/src/sqlite-graph-store.d.ts declare class SqliteGraphStore implements IGraphStore { private adapter; private reopenPromise; private readonly dbPath; private readonly externalAdapter; /** * Create a graph store backed by SQLite. * * Two construction modes: * - `{ path }` — creates and owns its own adapter at `/graph.db`. * Used standalone (legacy). * - `{ adapter }` — uses an externally-managed adapter that is shared with * other stores (e.g. `SqliteVecStore`). The caller owns the adapter * lifecycle and must have already configured pragmas. */ constructor(options?: { path?: string; adapter?: ISqliteAdapter; }); initialize(): Promise; private configureAdapter; private createTables; private migrateSchema; private getAdapter; /** * Ensure the adapter is open, lazily re-opening after close(). * Must be called from any public async method that may be invoked after close(). */ private ensureOpen; private reopenAdapter; private query; private run; upsertNode(node: GraphNode): Promise; upsertEdge(edge: GraphEdge): Promise; upsertNodes(nodes: GraphNode[]): Promise; upsertEdges(edges: GraphEdge[]): Promise; getNode(id: string): Promise; getNodes(ids: string[]): Promise; getNeighbors(nodeId: string, options?: GraphTraversalOptions): Promise; traverse(startId: string, options?: GraphTraversalOptions): Promise; findNodes(filter: { type?: string; namePattern?: string; sourcePath?: string; limit?: number; }): Promise; findEdges(filter: { type?: string; fromId?: string; toId?: string; limit?: number; }): Promise; deleteNode(id: string): Promise; deleteBySourcePath(sourcePath: string): Promise; clear(): Promise; getStats(): Promise; validate(): Promise; setNodeCommunity(nodeId: string, community: string): Promise; detectCommunities(): Promise>; traceProcess(entryNodeId: string, label: string): Promise; getProcesses(nodeId?: string): Promise; deleteProcess(processId: string): Promise; depthGroupedTraversal(startId: string, maxDepth?: number, options?: GraphTraversalOptions): Promise; getCohesionScore(community: string): Promise; getSymbol360(nodeId: string): Promise; /** * Release cached memory without closing the connection. * Called during idle periods to reduce memory footprint while keeping the store usable. */ releaseMemory(): void; close(): Promise; } //#endregion //#region packages/store/src/store.interface.d.ts /** Options for searching the store */ interface SearchOptions { /** Maximum number of results to return */ limit?: number; /** Minimum similarity score (0-1) */ minScore?: number; /** Filter by content type */ contentType?: ContentType; /** Filter by coarse source type (source, documentation, test, config, generated) */ sourceType?: SourceType; /** Filter by origin */ origin?: KnowledgeOrigin; /** Filter by category */ category?: string; /** Filter by exact tag membership (any supplied tag may match) */ tags?: string[]; } interface IKnowledgeStore { /** Initialize the store (create tables, etc.) */ initialize(): Promise; /** Add or update records with their embedding vectors */ upsert(records: KnowledgeRecord[], vectors: Float32Array[]): Promise; /** Add or update records with priority over bulk indexing writes */ upsertInteractive(records: KnowledgeRecord[], vectors: Float32Array[]): Promise; /** Add or update a record by reusing an existing vector instead of embedding again */ upsertWithoutVector?(record: KnowledgeRecord, sourceRecordId: string): Promise; /** Search by vector similarity */ search(queryVector: Float32Array, options?: SearchOptions): Promise; /** Coarse vector search using reduced-dimension embeddings (multi-resolution matryoshka) */ coarseSearch?(queryVector: Float32Array, options?: SearchOptions): Promise; /** Get a specific record by ID */ getById(id: string): Promise; /** Delete records by source path (used during re-indexing) */ deleteBySourcePath(sourcePath: string): Promise; /** Delete a specific record by ID */ deleteById(id: string): Promise; /** Delete a specific record by ID with priority over bulk indexing writes */ deleteByIdInteractive(id: string): Promise; /** Get all records for a source path */ getBySourcePath(sourcePath: string): Promise; /** Get index statistics */ getStats(): Promise; /** List all unique source paths in the store */ listSourcePaths(): Promise; /** Create a full-text search index on the content column for keyword search */ createFtsIndex(): Promise; /** Full-text keyword search (requires FTS index) */ ftsSearch(query: string, options?: SearchOptions): Promise; /** Drop the backing table entirely — used for hard resets (e.g. dimension changes) */ dropTable(): Promise; /** Release cached memory without closing the connection (lightweight idle cleanup). */ releaseMemory?(): void; /** Register a callback invoked synchronously before the store closes. */ onBeforeClose?(fn: () => void): void; /** Close the store connection */ close(): Promise; } //#endregion //#region packages/store/src/sqlite-vec-store.d.ts interface EmbeddingProfile$1 { model: string; version?: string; nativeDim: number; dimensions: number; queryPrefix: string; /** Pooling strategy ('mean' for xsmall, 'cls' for large). Used for migration detection. */ pooling?: 'mean' | 'cls'; /** Whether embeddings are L2-normalized. */ normalize?: boolean; } interface SqliteVecStoreOptions { /** Path to the .db file (file is created if missing) */ path?: string; /** Full embedding profile from runtime; takes precedence over embeddingDim. */ embeddingProfile?: EmbeddingProfile$1; /** Embedding dimension — must match the embedder configuration */ embeddingDim?: number; /** Externally-managed adapter (shared with graph store). When omitted, the store creates its own. */ adapter?: ISqliteAdapter; /** Optional state-partition config for future split-db deployments. */ partition?: StatePartitionConfig; /** Profile name for scoped vector table naming (e.g., vec_knowledge_) */ profileName?: string; } declare class SqliteVecStore implements IKnowledgeStore { private adapter; private readonly externalAdapter; private readonly dbPath; private readonly embeddingDim; private readonly embeddingProfile; /** Coarse embedding dimension for multi-resolution search (matryoshka). */ private readonly coarseDim; /** Vector table name (scoped by profileName if configured). */ private readonly vecTableName; /** Coarse vector table name (scoped by profileName if configured). */ private readonly vecTableCoarseName; private vectorEnabled; private ftsEnabled; private warnedVectorDisabled; private _drainState; private _priorityQueue; private _normalQueue; private _closeWaiter; private _onCloseHooks; /** Set to true at the start of close() to reject any new enqueueWrite calls. */ private _closing; constructor(options?: SqliteVecStoreOptions); initialize(): Promise; private configureConnectionPragmas; /** * Diagnostics for the status tool. Returns runtime info about the underlying * adapter and DB file (read-only; safe to call after initialize()). */ getDiagnostics(): { adapterType: string; vectorSearchEnabled: boolean; ftsEnabled: boolean; degradedMode: boolean; dbPath: string; dbSizeBytes: number | null; embeddingDim: number; vectorDtype: string; embeddingModel: string; embeddingProfile: EmbeddingProfile$1; }; private createKnowledgeTable; private createKnowledgeTagsTable; private createFtsTable; private createEmbeddingProfileTable; private getStoredEmbeddingProfile; private saveEmbeddingProfile; private dropVectorTables; private ensureVecTable; /** * Backfill canonical memory_embeddings from existing vec0 tables. * Runs only when memory_embeddings is empty and vec0 tables exist. * Updates vector_index_metadata after successful backfill. */ private backfillCanonicalEmbeddingsIfNeeded; private enqueueWrite; private _drain; upsert(records: KnowledgeRecord[], vectors: Float32Array[]): Promise; upsertInteractive(records: KnowledgeRecord[], vectors: Float32Array[]): Promise; /** * Insert a knowledge record and copy the vector from an existing record. * Used for chunk dedup — when content hash matches, skip re-embedding. */ upsertWithoutVector(record: KnowledgeRecord, sourceRecordId: string): Promise; private upsertKnowledgeRow; private replaceKnowledgeTags; private _upsertImpl; search(queryVector: Float32Array, options?: SearchOptions): Promise; coarseSearch(queryVector: Float32Array, options?: SearchOptions): Promise; ftsSearch(query: string, options?: SearchOptions): Promise; getById(id: string): Promise; deleteBySourcePath(sourcePath: string): Promise; private _deleteBySourcePathImpl; deleteById(id: string): Promise; deleteByIdInteractive(id: string): Promise; private _deleteByIdImpl; getBySourcePath(sourcePath: string): Promise; getStats(): Promise; listSourcePaths(): Promise; createFtsIndex(): Promise; dropTable(): Promise; private _dropTableImpl; /** * Release cached memory without closing the connection. * Called during idle periods to reduce memory footprint while keeping the store usable. */ releaseMemory(): void; /** Register a callback invoked synchronously before the store closes. */ onBeforeClose(fn: () => void): void; close(timeoutMs?: number): Promise; private getAdapter; private runAdaptiveVectorSearch; private queryVectorRows; private buildVectorSearchPlan; private rowsToSearchResults; /** * Build a SQL filter suffix from SearchOptions. * @param whereOnly when true the caller already has a WHERE clause and we emit `AND ...` * otherwise we emit `WHERE ...`. */ private buildFilterSqlSuffix; private fromRow; } //#endregion //#region packages/store/src/state-store.d.ts interface MemoryMeta { entryId: string; tier: string; retentionScore: number; accessCount: number; lastAccessedAt: string | null; createdAt: string; promotedAt: string | null; supersededBy: string | null; confidence: number; } interface MemoryMetaListOptions { tier?: string; belowScore?: number; limit?: number; } interface StateStore { stashGet(key: string): string | undefined; stashSet(key: string, value: string): void; stashList(): Array<{ key: string; value: string; updatedAt: string; }>; stashDelete(key: string): boolean; stashClear(): void; signalPost(workspace: string, key: string, value: string, agent?: string, ttlSeconds?: number): number; signalGet(workspace: string, key: string): Array<{ id: number; value: string; agent?: string; createdAt: string; expiresAt: string; }>; signalList(workspace: string): Array<{ id: number; key: string; value: string; agent?: string; createdAt: string; }>; signalClear(workspace: string, key?: string): number; signalCleanExpired(): number; leaseAcquire(resource: string, holder: string, workspace: string, intent?: string, ttlMinutes?: number): boolean; leaseRelease(resource: string, holder: string, workspace: string): boolean; leaseGet(resource: string, workspace: string): { resource: string; holder: string; intent?: string; workspace: string; acquiredAt: string; expiresAt: string; } | undefined; leaseList(workspace: string): Array<{ resource: string; holder: string; intent?: string; acquiredAt: string; expiresAt: string; }>; leaseCleanExpired(): number; sessionCreate(sessionId: string, metadata?: Record): void; sessionTouch(sessionId: string): void; sessionGet(sessionId: string): { sessionId: string; createdAt: string; lastActivity: string; metadata?: string; } | undefined; sessionList(): Array<{ sessionId: string; createdAt: string; lastActivity: string; }>; sessionDelete(sessionId: string): boolean; sessionDeleteStale(maxInactiveMinutes: number): number; checkpointSave(id: string, label: string, data: string, notes?: string): void; checkpointLoad(id: string): { id: string; label: string; data: string; notes?: string; createdAt: string; } | undefined; checkpointList(label?: string, limit?: number): Array<{ id: string; label: string; createdAt: string; notes?: string; }>; checkpointLatest(label?: string): { id: string; label: string; data: string; notes?: string; createdAt: string; } | undefined; checkpointDelete(id: string): boolean; checkpointDiff(fromId: string, toId: string): { from: string; to: string; } | undefined; checkpointHistory(label?: string, limit?: number): Array<{ id: string; label: string; createdAt: string; notes?: string; }>; checkpointGc(keepLast?: number, maxAgeDays?: number): number; memoryMetaCreate(entryId: string, tier?: string): void; memoryMetaGet(entryId: string): MemoryMeta | undefined; memoryMetaTouch(entryId: string): void; memoryMetaUpdateScore(entryId: string, score: number): void; memoryMetaUpdateConfidence(entryId: string, confidence: number): void; memoryMetaUpdateTier(entryId: string, tier: string): void; memoryMetaSetSuperseded(entryId: string, supersededBy: string): void; memoryMetaList(options?: MemoryMetaListOptions): MemoryMeta[]; } declare function createStateStore(db: BetterSqlite3.Database): StateStore; declare function createStateStore(db: ISqliteAdapter): StateStore; //#endregion //#region packages/store/src/store-factory.d.ts type StoreBackend = 'lancedb' | 'sqlite-vec'; interface EmbeddingProfile { model: string; nativeDim: number; dimensions: number; queryPrefix: string; /** Pooling strategy used by the embedding model. 'mean' averages token embeddings, 'cls' uses the [CLS] token. */ pooling?: 'mean' | 'cls'; /** Whether embeddings are L2-normalized. */ normalize?: boolean; } interface StoreConfig { backend: StoreBackend; path: string; options?: Record; /** Optional shared adapter (only used by the sqlite-vec backend) */ adapter?: ISqliteAdapter; /** Embedding dimension (only used by the sqlite-vec backend) */ embeddingDim?: number; /** Full embedding profile (only used by the sqlite-vec backend). */ embeddingProfile?: EmbeddingProfile; /** Profile name for scoped vector table naming (e.g., "quality", "lightweight"). * When set, vector tables use `vec_knowledge_` instead of the default. * When unset, the default table name is used for backward compatibility. */ profileName?: string; /** Optional control/content partition config for sqlite-backed stores. */ partition?: StatePartitionConfig; /** * SQLite driver mode: auto (default) or forced. * When unset, reads AI_KIT_SQLITE_DRIVER env var. */ sqliteDriver?: 'auto' | 'node-sqlite' | 'better-sqlite3' | 'sqljs'; /** * Allow fallback chain when a forced mode fails (default: true). * When unset, reads AI_KIT_SQLITE_ALLOW_FALLBACK env var. */ allowFallback?: boolean; } declare function createStore(config: StoreConfig): Promise; //#endregion export { CONTROL_TABLES, type DepthGroupedResult, type GraphEdge, type GraphNode, type GraphStats, type GraphTraversalOptions, type GraphTraversalResult, type GraphValidationResult, type IGraphStore, type IKnowledgeStore, type ISqliteAdapter, type MemoryMeta, type Migration, type MigrationDb, type PartitionKind, type ProcessInfo, type ResolvedStatePartitionConfig, type SearchOptions, type SqliteAdapterType, SqliteGraphStore, SqliteVecStore, type SqliteVecStoreOptions, type StatePartitionConfig, type StateStore, type StoreBackend, type StoreConfig, type Symbol360, allMigrations, createSqlJsAdapter, createSqliteAdapter, createStateStore, createStore, getTablePartition, migrateToSplitState, readStatePartitionConfigFromEnv, resolveStatePartitionConfig, runMigrations };