minimem 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,3 +1,61 @@
1
+ import { DatabaseSync } from 'node:sqlite';
2
+ import { DebugFn, MemoryFileEntry, MemoryChunk } from './internal.js';
3
+ export { buildFileEntry, chunkMarkdown, cosineSimilarity, extractChunkMetadata, hashText, isMemoryPath, listMemoryFiles, stripPrivateContent } from './internal.js';
4
+ export { KnowledgeLink, KnowledgeSource, MemoryFrontmatter, SessionContext, addFrontmatter, addSessionToContent, extractSession, parseFrontmatter, serializeFrontmatter } from './session.js';
5
+
6
+ /**
7
+ * A knowledge graph link between two nodes
8
+ */
9
+ type GraphLink = {
10
+ fromId: string;
11
+ toId: string;
12
+ relation: string;
13
+ layer: string | null;
14
+ weight: number;
15
+ sourcePath: string | null;
16
+ };
17
+ /**
18
+ * A neighbor node discovered during graph traversal
19
+ */
20
+ type GraphNeighbor = {
21
+ id: string;
22
+ depth: number;
23
+ link: GraphLink;
24
+ };
25
+ /**
26
+ * Get all outgoing links from a node.
27
+ */
28
+ declare function getLinksFrom(db: DatabaseSync, fromId: string, opts?: {
29
+ relation?: string;
30
+ layer?: string;
31
+ }): GraphLink[];
32
+ /**
33
+ * Get all incoming links to a node.
34
+ */
35
+ declare function getLinksTo(db: DatabaseSync, toId: string, opts?: {
36
+ relation?: string;
37
+ layer?: string;
38
+ }): GraphLink[];
39
+ /**
40
+ * BFS traversal to find neighbors up to a given depth.
41
+ *
42
+ * @param db - Database handle
43
+ * @param startId - The starting node ID
44
+ * @param depth - Maximum traversal depth (default: 1)
45
+ * @param opts - Optional filters for relation and layer
46
+ * @returns Array of neighbor nodes with their depth and connecting link
47
+ */
48
+ declare function getNeighbors(db: DatabaseSync, startId: string, depth?: number, opts?: {
49
+ relation?: string;
50
+ layer?: string;
51
+ }): GraphNeighbor[];
52
+ /**
53
+ * BFS shortest path between two nodes, max depth 3.
54
+ *
55
+ * @returns Array of links forming the path, or empty if no path found.
56
+ */
57
+ declare function getPathBetween(db: DatabaseSync, fromId: string, toId: string, maxDepth?: number): GraphLink[];
58
+
1
59
  type EmbeddingProvider = {
2
60
  id: string;
3
61
  model: string;
@@ -6,8 +64,8 @@ type EmbeddingProvider = {
6
64
  };
7
65
  type EmbeddingProviderResult = {
8
66
  provider: EmbeddingProvider;
9
- requestedProvider: "openai" | "local" | "gemini" | "auto";
10
- fallbackFrom?: "openai" | "local" | "gemini";
67
+ requestedProvider: "openai" | "local" | "gemini" | "auto" | "none";
68
+ fallbackFrom?: "openai" | "local" | "gemini" | "auto";
11
69
  fallbackReason?: string;
12
70
  openAi?: OpenAiEmbeddingClient;
13
71
  gemini?: GeminiEmbeddingClient;
@@ -148,6 +206,7 @@ declare class Minimem {
148
206
  private closed;
149
207
  private dirty;
150
208
  private syncing;
209
+ private syncLock;
151
210
  private embeddingOptions;
152
211
  private constructor();
153
212
  static create(config: MinimemConfig): Promise<Minimem>;
@@ -166,6 +225,7 @@ declare class Minimem {
166
225
  search(query: string, opts?: {
167
226
  maxResults?: number;
168
227
  minScore?: number;
228
+ type?: string;
169
229
  }): Promise<MinimemSearchResult[]>;
170
230
  sync(opts?: {
171
231
  reason?: string;
@@ -228,68 +288,39 @@ declare class Minimem {
228
288
  chunkCount: number;
229
289
  cacheCount: number;
230
290
  }>;
291
+ /**
292
+ * Search with knowledge metadata filters (domain, entities, confidence, type).
293
+ * Runs a standard search then post-filters by knowledge columns.
294
+ */
295
+ knowledgeSearch(query: string, opts?: {
296
+ maxResults?: number;
297
+ minScore?: number;
298
+ domain?: string[];
299
+ entities?: string[];
300
+ minConfidence?: number;
301
+ knowledgeType?: string;
302
+ }): Promise<MinimemSearchResult[]>;
303
+ /**
304
+ * Get knowledge graph links from or to a node.
305
+ */
306
+ getLinks(nodeId: string, direction?: "from" | "to", opts?: {
307
+ relation?: string;
308
+ layer?: string;
309
+ }): GraphLink[];
310
+ /**
311
+ * Get neighbor nodes via BFS traversal.
312
+ */
313
+ getGraphNeighbors(nodeId: string, depth?: number, opts?: {
314
+ relation?: string;
315
+ layer?: string;
316
+ }): GraphNeighbor[];
317
+ /**
318
+ * Find shortest path between two knowledge nodes.
319
+ */
320
+ getGraphPath(fromId: string, toId: string, maxDepth?: number): GraphLink[];
231
321
  close(): void;
232
322
  }
233
323
 
234
- type MemoryFileEntry = {
235
- path: string;
236
- absPath: string;
237
- mtimeMs: number;
238
- size: number;
239
- hash: string;
240
- };
241
- type MemoryChunk = {
242
- startLine: number;
243
- endLine: number;
244
- text: string;
245
- hash: string;
246
- };
247
- declare function normalizeRelPath(value: string): string;
248
- declare function isMemoryPath(relPath: string): boolean;
249
- declare function listMemoryFiles(memoryDir: string): Promise<string[]>;
250
- declare function hashText(value: string): string;
251
- declare function buildFileEntry(absPath: string, memoryDir: string): Promise<MemoryFileEntry>;
252
- declare function chunkMarkdown(content: string, chunking: {
253
- tokens: number;
254
- overlap: number;
255
- }): MemoryChunk[];
256
- declare function cosineSimilarity(a: number[], b: number[]): number;
257
-
258
- type HybridSource = string;
259
- type HybridVectorResult = {
260
- id: string;
261
- path: string;
262
- startLine: number;
263
- endLine: number;
264
- source: HybridSource;
265
- snippet: string;
266
- vectorScore: number;
267
- };
268
- type HybridKeywordResult = {
269
- id: string;
270
- path: string;
271
- startLine: number;
272
- endLine: number;
273
- source: HybridSource;
274
- snippet: string;
275
- textScore: number;
276
- };
277
- declare function buildFtsQuery(raw: string): string | null;
278
- declare function bm25RankToScore(rank: number): number;
279
- declare function mergeHybridResults(params: {
280
- vector: HybridVectorResult[];
281
- keyword: HybridKeywordResult[];
282
- vectorWeight: number;
283
- textWeight: number;
284
- }): Array<{
285
- path: string;
286
- startLine: number;
287
- endLine: number;
288
- score: number;
289
- snippet: string;
290
- source: HybridSource;
291
- }>;
292
-
293
324
  type OpenAiBatchRequest = {
294
325
  custom_id: string;
295
326
  method: "POST";
@@ -384,8 +415,59 @@ type MemorySearchParams = {
384
415
  maxResults?: number;
385
416
  minScore?: number;
386
417
  directories?: string[];
418
+ /** "compact" returns lightweight index; "full" returns complete snippets (default: "compact") */
419
+ detail?: "compact" | "full";
420
+ /** Filter by observation type (e.g., "decision", "bugfix", "feature", "discovery") */
421
+ type?: string;
422
+ };
423
+ /**
424
+ * Memory get details tool parameters
425
+ */
426
+ type MemoryGetDetailsParams = {
427
+ results: Array<{
428
+ path: string;
429
+ startLine: number;
430
+ endLine: number;
431
+ }>;
432
+ directories?: string[];
433
+ };
434
+ /**
435
+ * Knowledge search tool parameters
436
+ */
437
+ type KnowledgeSearchParams = {
438
+ query: string;
439
+ domain?: string[];
440
+ entities?: string[];
441
+ minConfidence?: number;
442
+ knowledgeType?: string;
443
+ maxResults?: number;
444
+ minScore?: number;
445
+ directories?: string[];
446
+ };
447
+ /**
448
+ * Knowledge graph traversal parameters
449
+ */
450
+ type KnowledgeGraphParams = {
451
+ nodeId: string;
452
+ depth?: number;
453
+ relation?: string;
454
+ layer?: string;
455
+ directories?: string[];
456
+ };
457
+ /**
458
+ * Knowledge path parameters
459
+ */
460
+ type KnowledgePathParams = {
461
+ fromId: string;
462
+ toId: string;
463
+ maxDepth?: number;
464
+ directories?: string[];
387
465
  };
388
466
  declare const MEMORY_SEARCH_TOOL: ToolDefinition;
467
+ declare const MEMORY_GET_DETAILS_TOOL: ToolDefinition;
468
+ declare const KNOWLEDGE_SEARCH_TOOL: ToolDefinition;
469
+ declare const KNOWLEDGE_GRAPH_TOOL: ToolDefinition;
470
+ declare const KNOWLEDGE_PATH_TOOL: ToolDefinition;
389
471
  /**
390
472
  * All available memory tools
391
473
  */
@@ -416,7 +498,17 @@ declare class MemoryToolExecutor {
416
498
  * Execute a tool by name with given parameters
417
499
  */
418
500
  execute(toolName: string, params: Record<string, unknown>): Promise<ToolResult>;
501
+ /**
502
+ * Filter instances by directory names/paths
503
+ */
504
+ private filterInstances;
419
505
  private memorySearch;
506
+ private formatCompactResults;
507
+ private formatFullResults;
508
+ private memoryGetDetails;
509
+ private knowledgeSearch;
510
+ private knowledgeGraph;
511
+ private knowledgePath;
420
512
  }
421
513
  /**
422
514
  * Create a tool executor for the given Minimem instance(s)
@@ -527,66 +619,240 @@ declare function generateMcpConfig(opts: {
527
619
  }): McpServerConfig;
528
620
 
529
621
  /**
530
- * Session tracking for memory entries
531
- *
532
- * Captures context about the originating session (Claude Code, VS Code, etc.)
533
- * and stores it as YAML frontmatter in memory files.
622
+ * Options for filtering search results by knowledge metadata
534
623
  */
535
- /**
536
- * Session metadata for memory entries
537
- */
538
- type SessionContext = {
539
- /** Session identifier (e.g., Claude Code session ID) */
540
- id?: string;
541
- /** Source application (claude-code, vscode, cursor, etc.) */
542
- source?: string;
543
- /** Project directory path */
544
- project?: string;
545
- /** Path to session transcript/log file */
546
- transcript?: string;
624
+ type KnowledgeSearchOptions = {
625
+ /** Filter to chunks matching any of these domains */
626
+ domain?: string[];
627
+ /** Filter to chunks referencing any of these entities */
628
+ entities?: string[];
629
+ /** Minimum confidence threshold */
630
+ minConfidence?: number;
631
+ /** Filter to a specific knowledge type */
632
+ knowledgeType?: string;
547
633
  };
548
634
  /**
549
- * Frontmatter structure for memory files
635
+ * Build SQL WHERE clause fragments for knowledge filters.
636
+ * Uses json_each() for array column filtering.
550
637
  */
551
- type MemoryFrontmatter = {
552
- session?: SessionContext;
553
- created?: string;
554
- updated?: string;
555
- tags?: string[];
638
+ declare function buildKnowledgeFilterSql(opts: KnowledgeSearchOptions): {
639
+ sql: string;
640
+ params: (string | number)[];
556
641
  };
642
+
557
643
  /**
558
- * Parse YAML frontmatter from content
644
+ * MemoryIndexer - Handles file indexing and embedding management
559
645
  *
560
- * Frontmatter is delimited by --- at the start and end:
561
- * ```
562
- * ---
563
- * session:
564
- * id: abc123
565
- * source: claude-code
566
- * created: 2024-01-27T14:30:00Z
567
- * ---
568
- * Actual content here...
569
- * ```
570
- */
571
- declare function parseFrontmatter(content: string): {
572
- frontmatter: MemoryFrontmatter | undefined;
573
- body: string;
574
- };
575
- /**
576
- * Serialize frontmatter to YAML string
646
+ * Responsible for:
647
+ * - Processing memory files into chunks
648
+ * - Computing and caching embeddings
649
+ * - Managing file records in the database
650
+ * - Detecting stale content
577
651
  */
578
- declare function serializeFrontmatter(frontmatter: MemoryFrontmatter): string;
652
+
653
+ type IndexerConfig = {
654
+ memoryDir: string;
655
+ chunking: {
656
+ tokens: number;
657
+ overlap: number;
658
+ };
659
+ cache: {
660
+ enabled: boolean;
661
+ maxEntries: number;
662
+ };
663
+ batch: {
664
+ enabled: boolean;
665
+ wait: boolean;
666
+ concurrency: number;
667
+ pollIntervalMs: number;
668
+ timeoutMs: number;
669
+ };
670
+ ftsEnabled: boolean;
671
+ debug?: DebugFn;
672
+ };
673
+ type MemoryIndexMeta = {
674
+ model: string;
675
+ provider: string;
676
+ providerKey?: string;
677
+ chunkTokens: number;
678
+ chunkOverlap: number;
679
+ vectorDims?: number;
680
+ };
681
+ type IndexStats = {
682
+ filesProcessed: number;
683
+ chunksCreated: number;
684
+ staleRemoved: number;
685
+ };
579
686
  /**
580
- * Add or update frontmatter in content
687
+ * MemoryIndexer handles file indexing, chunking, and embedding management
581
688
  */
582
- declare function addFrontmatter(content: string, frontmatter: MemoryFrontmatter): string;
689
+ declare class MemoryIndexer {
690
+ private readonly config;
691
+ private readonly db;
692
+ private readonly provider;
693
+ private readonly providerKey;
694
+ private readonly openAi?;
695
+ private readonly gemini?;
696
+ private vectorState;
697
+ private ftsAvailable;
698
+ constructor(db: DatabaseSync, provider: EmbeddingProvider, config: IndexerConfig, options?: {
699
+ openAi?: OpenAiEmbeddingClient;
700
+ gemini?: GeminiEmbeddingClient;
701
+ vectorState?: {
702
+ available: boolean;
703
+ dims?: number;
704
+ };
705
+ ftsAvailable?: boolean;
706
+ });
707
+ /**
708
+ * Update vector/FTS availability (called by parent when extensions load)
709
+ */
710
+ setVectorState(state: {
711
+ available: boolean;
712
+ dims?: number;
713
+ }): void;
714
+ setFtsAvailable(available: boolean): void;
715
+ getVectorDims(): number | undefined;
716
+ /**
717
+ * Compute a unique key for the current provider configuration
718
+ */
719
+ private computeProviderKey;
720
+ /**
721
+ * Read index metadata from database
722
+ */
723
+ readMeta(): MemoryIndexMeta | null;
724
+ /**
725
+ * Write index metadata to database
726
+ */
727
+ writeMeta(meta: MemoryIndexMeta): void;
728
+ /**
729
+ * Check if the index is stale by comparing file mtimes
730
+ */
731
+ isStale(): Promise<boolean>;
732
+ /**
733
+ * Check if a full reindex is needed based on configuration changes
734
+ */
735
+ needsFullReindex(force?: boolean): boolean;
736
+ /**
737
+ * Index all memory files, returns stats
738
+ */
739
+ indexAll(force?: boolean): Promise<IndexStats>;
740
+ /**
741
+ * Index a single file
742
+ */
743
+ indexFile(entry: MemoryFileEntry): Promise<number>;
744
+ /**
745
+ * Delete all chunks for a file
746
+ */
747
+ private deleteChunksForFile;
748
+ /**
749
+ * Insert a chunk into the database
750
+ */
751
+ private insertChunk;
752
+ /**
753
+ * Remove stale file entries that no longer exist
754
+ */
755
+ private removeStaleEntries;
756
+ /**
757
+ * Create vector table with the given dimensions
758
+ */
759
+ ensureVectorTable(dimensions: number): void;
760
+ /**
761
+ * Get embeddings for chunks, using cache when available
762
+ */
763
+ embedChunks(chunks: MemoryChunk[]): Promise<number[][]>;
764
+ /**
765
+ * Embed texts with retry logic
766
+ */
767
+ private embedBatchWithRetry;
768
+ /**
769
+ * Use batch API for large embedding jobs
770
+ */
771
+ private embedWithBatchApi;
772
+ /**
773
+ * Load embeddings from cache
774
+ */
775
+ private loadEmbeddingCache;
776
+ /**
777
+ * Save embedding to cache
778
+ */
779
+ private upsertEmbeddingCache;
780
+ /**
781
+ * Prune old cache entries if over limit
782
+ */
783
+ private pruneEmbeddingCacheIfNeeded;
784
+ }
785
+
583
786
  /**
584
- * Add session context as frontmatter to content
787
+ * MemorySearcher - Handles search operations
788
+ *
789
+ * Responsible for:
790
+ * - Executing vector searches
791
+ * - Executing keyword (FTS) searches
792
+ * - Merging results with hybrid scoring
585
793
  */
586
- declare function addSessionToContent(content: string, session: SessionContext): string;
794
+
795
+ type SearchConfig = {
796
+ hybrid: {
797
+ enabled: boolean;
798
+ vectorWeight: number;
799
+ textWeight: number;
800
+ candidateMultiplier: number;
801
+ };
802
+ query: {
803
+ maxResults: number;
804
+ minScore: number;
805
+ };
806
+ debug?: DebugFn;
807
+ };
808
+ type SearchResult = {
809
+ path: string;
810
+ startLine: number;
811
+ endLine: number;
812
+ score: number;
813
+ snippet: string;
814
+ };
587
815
  /**
588
- * Extract session context from file content
816
+ * MemorySearcher handles search queries against the indexed memory
589
817
  */
590
- declare function extractSession(content: string): SessionContext | undefined;
818
+ declare class MemorySearcher {
819
+ private readonly db;
820
+ private readonly provider;
821
+ private readonly config;
822
+ private vectorState;
823
+ private ftsAvailable;
824
+ private ensureVectorReadyFn?;
825
+ constructor(db: DatabaseSync, provider: EmbeddingProvider, config: SearchConfig, options?: {
826
+ vectorState?: {
827
+ available: boolean;
828
+ dims?: number;
829
+ };
830
+ ftsAvailable?: boolean;
831
+ ensureVectorReady?: (dims?: number) => Promise<boolean>;
832
+ });
833
+ /**
834
+ * Update vector/FTS availability (called by parent when extensions load)
835
+ */
836
+ setVectorState(state: {
837
+ available: boolean;
838
+ dims?: number;
839
+ }): void;
840
+ setFtsAvailable(available: boolean): void;
841
+ /**
842
+ * Execute a search query
843
+ */
844
+ search(query: string, opts?: {
845
+ maxResults?: number;
846
+ minScore?: number;
847
+ }): Promise<SearchResult[]>;
848
+ /**
849
+ * Embed a query string with timeout
850
+ */
851
+ private embedQueryWithTimeout;
852
+ /**
853
+ * Ensure vector extension is ready
854
+ */
855
+ private ensureVectorReady;
856
+ }
591
857
 
592
- export { type EmbeddingProvider, type EmbeddingProviderOptions, type EmbeddingProviderResult, type GeminiBatchRequest, type GeminiEmbeddingClient, MEMORY_SEARCH_TOOL, MEMORY_TOOLS, McpServer, type McpServerConfig, type MemoryChunk, type MemoryFileEntry, type MemoryFrontmatter, type MemoryInstance, type MemorySearchParams, MemoryToolExecutor, Minimem, type MinimemConfig, type MinimemSearchResult, type OpenAiBatchRequest, type OpenAiEmbeddingClient, type SessionContext, type ToolDefinition, type ToolInputSchema, type ToolResult, addFrontmatter, addSessionToContent, bm25RankToScore, buildFileEntry, buildFtsQuery, chunkMarkdown, cosineSimilarity, createEmbeddingProvider, createGeminiEmbeddingProvider, createMcpServer, createOpenAiEmbeddingProvider, createToolExecutor, extractSession, generateMcpConfig, getToolDefinitions, hashText, isMemoryPath, listMemoryFiles, mergeHybridResults, normalizeRelPath, parseFrontmatter, runGeminiEmbeddingBatches, runMcpServer, runOpenAiEmbeddingBatches, serializeFrontmatter };
858
+ export { type SearchResult as CoreSearchResult, DebugFn, type EmbeddingProvider, type EmbeddingProviderOptions, type EmbeddingProviderResult, type GeminiBatchRequest, type GeminiEmbeddingClient, type GraphLink, type GraphNeighbor, type IndexStats, type IndexerConfig, KNOWLEDGE_GRAPH_TOOL, KNOWLEDGE_PATH_TOOL, KNOWLEDGE_SEARCH_TOOL, type KnowledgeGraphParams, type KnowledgePathParams, type KnowledgeSearchOptions, type KnowledgeSearchParams, MEMORY_GET_DETAILS_TOOL, MEMORY_SEARCH_TOOL, MEMORY_TOOLS, McpServer, type McpServerConfig, MemoryChunk, MemoryFileEntry, type MemoryGetDetailsParams, type MemoryIndexMeta, MemoryIndexer, type MemoryInstance, type MemorySearchParams, MemorySearcher, MemoryToolExecutor, Minimem, type MinimemConfig, type MinimemSearchResult, type OpenAiBatchRequest, type OpenAiEmbeddingClient, type SearchConfig, type MinimemSearchResult as SearchResult, type ToolDefinition, type ToolInputSchema, type ToolResult, buildKnowledgeFilterSql, createEmbeddingProvider, createGeminiEmbeddingProvider, createMcpServer, createOpenAiEmbeddingProvider, createToolExecutor, generateMcpConfig, getLinksFrom, getLinksTo, getNeighbors, getPathBetween, getToolDefinitions, runGeminiEmbeddingBatches, runMcpServer, runOpenAiEmbeddingBatches };