@memextend/core 0.1.0

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.
Files changed (81) hide show
  1. package/dist/embedding/index.d.ts +3 -0
  2. package/dist/embedding/index.d.ts.map +1 -0
  3. package/dist/embedding/index.js +4 -0
  4. package/dist/embedding/index.js.map +1 -0
  5. package/dist/embedding/local.d.ts +54 -0
  6. package/dist/embedding/local.d.ts.map +1 -0
  7. package/dist/embedding/local.js +162 -0
  8. package/dist/embedding/local.js.map +1 -0
  9. package/dist/embedding/local.test.d.ts +2 -0
  10. package/dist/embedding/local.test.d.ts.map +1 -0
  11. package/dist/embedding/local.test.js +73 -0
  12. package/dist/embedding/local.test.js.map +1 -0
  13. package/dist/index.d.ts +5 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +7 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/memory/capture.d.ts +102 -0
  18. package/dist/memory/capture.d.ts.map +1 -0
  19. package/dist/memory/capture.js +249 -0
  20. package/dist/memory/capture.js.map +1 -0
  21. package/dist/memory/capture.test.d.ts +2 -0
  22. package/dist/memory/capture.test.d.ts.map +1 -0
  23. package/dist/memory/capture.test.js +168 -0
  24. package/dist/memory/capture.test.js.map +1 -0
  25. package/dist/memory/deduplicate.d.ts +31 -0
  26. package/dist/memory/deduplicate.d.ts.map +1 -0
  27. package/dist/memory/deduplicate.js +64 -0
  28. package/dist/memory/deduplicate.js.map +1 -0
  29. package/dist/memory/deduplicate.test.d.ts +2 -0
  30. package/dist/memory/deduplicate.test.d.ts.map +1 -0
  31. package/dist/memory/deduplicate.test.js +116 -0
  32. package/dist/memory/deduplicate.test.js.map +1 -0
  33. package/dist/memory/index.d.ts +8 -0
  34. package/dist/memory/index.d.ts.map +1 -0
  35. package/dist/memory/index.js +7 -0
  36. package/dist/memory/index.js.map +1 -0
  37. package/dist/memory/retrieve.d.ts +62 -0
  38. package/dist/memory/retrieve.d.ts.map +1 -0
  39. package/dist/memory/retrieve.js +218 -0
  40. package/dist/memory/retrieve.js.map +1 -0
  41. package/dist/memory/retrieve.test.d.ts +2 -0
  42. package/dist/memory/retrieve.test.d.ts.map +1 -0
  43. package/dist/memory/retrieve.test.js +177 -0
  44. package/dist/memory/retrieve.test.js.map +1 -0
  45. package/dist/memory/types.d.ts +36 -0
  46. package/dist/memory/types.d.ts.map +1 -0
  47. package/dist/memory/types.js +4 -0
  48. package/dist/memory/types.js.map +1 -0
  49. package/dist/memory/types.test.d.ts +2 -0
  50. package/dist/memory/types.test.d.ts.map +1 -0
  51. package/dist/memory/types.test.js +31 -0
  52. package/dist/memory/types.test.js.map +1 -0
  53. package/dist/storage/index.d.ts +4 -0
  54. package/dist/storage/index.d.ts.map +1 -0
  55. package/dist/storage/index.js +5 -0
  56. package/dist/storage/index.js.map +1 -0
  57. package/dist/storage/lancedb.d.ts +24 -0
  58. package/dist/storage/lancedb.d.ts.map +1 -0
  59. package/dist/storage/lancedb.js +106 -0
  60. package/dist/storage/lancedb.js.map +1 -0
  61. package/dist/storage/lancedb.test.d.ts +2 -0
  62. package/dist/storage/lancedb.test.d.ts.map +1 -0
  63. package/dist/storage/lancedb.test.js +67 -0
  64. package/dist/storage/lancedb.test.js.map +1 -0
  65. package/dist/storage/sqlite.d.ts +68 -0
  66. package/dist/storage/sqlite.d.ts.map +1 -0
  67. package/dist/storage/sqlite.js +354 -0
  68. package/dist/storage/sqlite.js.map +1 -0
  69. package/dist/storage/sqlite.test.d.ts +2 -0
  70. package/dist/storage/sqlite.test.d.ts.map +1 -0
  71. package/dist/storage/sqlite.test.js +137 -0
  72. package/dist/storage/sqlite.test.js.map +1 -0
  73. package/dist/utils/index.d.ts +2 -0
  74. package/dist/utils/index.d.ts.map +1 -0
  75. package/dist/utils/index.js +4 -0
  76. package/dist/utils/index.js.map +1 -0
  77. package/dist/utils/project.d.ts +13 -0
  78. package/dist/utils/project.d.ts.map +1 -0
  79. package/dist/utils/project.js +37 -0
  80. package/dist/utils/project.js.map +1 -0
  81. package/package.json +61 -0
@@ -0,0 +1,116 @@
1
+ // packages/core/src/memory/deduplicate.test.ts
2
+ // Copyright (c) 2026 ZodTTD LLC. MIT License.
3
+ import { describe, it, expect } from 'vitest';
4
+ import { deduplicateMemories, getDeduplicationStats } from './deduplicate.js';
5
+ describe('deduplicateMemories', () => {
6
+ const createMemory = (id, content, daysAgo) => {
7
+ const date = new Date();
8
+ date.setDate(date.getDate() - daysAgo);
9
+ return {
10
+ id,
11
+ projectId: 'test-project',
12
+ content,
13
+ type: 'manual',
14
+ sourceTool: null,
15
+ createdAt: date.toISOString(),
16
+ sessionId: null,
17
+ metadata: null
18
+ };
19
+ };
20
+ // Create normalized vectors (unit length)
21
+ const normalize = (v) => {
22
+ const norm = Math.sqrt(v.reduce((s, x) => s + x * x, 0));
23
+ return v.map(x => x / norm);
24
+ };
25
+ it('should return empty array for empty input', () => {
26
+ const result = deduplicateMemories([], new Map());
27
+ expect(result).toEqual([]);
28
+ });
29
+ it('should keep all memories when no vectors available', () => {
30
+ const memories = [
31
+ createMemory('1', 'First memory', 0),
32
+ createMemory('2', 'Second memory', 1)
33
+ ];
34
+ const result = deduplicateMemories(memories, new Map());
35
+ expect(result.length).toBe(2);
36
+ });
37
+ it('should keep all memories when they are dissimilar', () => {
38
+ const memories = [
39
+ createMemory('1', 'Topic A', 0),
40
+ createMemory('2', 'Topic B', 1)
41
+ ];
42
+ // Orthogonal vectors = 0 similarity
43
+ const vectors = new Map([
44
+ ['1', normalize([1, 0, 0])],
45
+ ['2', normalize([0, 1, 0])]
46
+ ]);
47
+ const result = deduplicateMemories(memories, vectors);
48
+ expect(result.length).toBe(2);
49
+ });
50
+ it('should keep newest when memories are similar', () => {
51
+ const memories = [
52
+ createMemory('1', 'JWT auth v1', 2), // oldest
53
+ createMemory('2', 'JWT auth v2', 1), // middle
54
+ createMemory('3', 'JWT auth v3', 0) // newest
55
+ ];
56
+ // All very similar (same direction)
57
+ const vectors = new Map([
58
+ ['1', normalize([1, 0.1, 0])],
59
+ ['2', normalize([1, 0.1, 0])],
60
+ ['3', normalize([1, 0.1, 0])]
61
+ ]);
62
+ const result = deduplicateMemories(memories, vectors, { similarityThreshold: 0.9 });
63
+ expect(result.length).toBe(1);
64
+ expect(result[0].id).toBe('3'); // Newest wins
65
+ });
66
+ it('should keep diverse memories even when some are similar', () => {
67
+ const memories = [
68
+ createMemory('1', 'Auth v1', 3),
69
+ createMemory('2', 'Auth v2', 2), // Similar to 1
70
+ createMemory('3', 'Database setup', 1), // Different topic
71
+ createMemory('4', 'Auth v3', 0) // Similar to 1 and 2
72
+ ];
73
+ const vectors = new Map([
74
+ ['1', normalize([1, 0, 0])],
75
+ ['2', normalize([1, 0.05, 0])], // Very similar to 1
76
+ ['3', normalize([0, 1, 0])], // Orthogonal (different topic)
77
+ ['4', normalize([1, 0.02, 0])] // Very similar to 1 and 2
78
+ ]);
79
+ const result = deduplicateMemories(memories, vectors, { similarityThreshold: 0.9 });
80
+ // Should keep: 4 (newest auth), 3 (database is different)
81
+ expect(result.length).toBe(2);
82
+ expect(result.map(m => m.id).sort()).toEqual(['3', '4']);
83
+ });
84
+ it('should use default threshold when not specified', () => {
85
+ const memories = [
86
+ createMemory('1', 'Old', 1),
87
+ createMemory('2', 'New', 0)
88
+ ];
89
+ // Similarity of ~0.95 (above default 0.85)
90
+ const vectors = new Map([
91
+ ['1', normalize([1, 0.1, 0])],
92
+ ['2', normalize([1, 0.15, 0])]
93
+ ]);
94
+ const result = deduplicateMemories(memories, vectors);
95
+ expect(result.length).toBe(1);
96
+ expect(result[0].id).toBe('2');
97
+ });
98
+ });
99
+ describe('getDeduplicationStats', () => {
100
+ it('should calculate removal stats correctly', () => {
101
+ const stats = getDeduplicationStats(10, 7);
102
+ expect(stats.removed).toBe(3);
103
+ expect(stats.percentage).toBe(30);
104
+ });
105
+ it('should handle zero original count', () => {
106
+ const stats = getDeduplicationStats(0, 0);
107
+ expect(stats.removed).toBe(0);
108
+ expect(stats.percentage).toBe(0);
109
+ });
110
+ it('should handle no removals', () => {
111
+ const stats = getDeduplicationStats(5, 5);
112
+ expect(stats.removed).toBe(0);
113
+ expect(stats.percentage).toBe(0);
114
+ });
115
+ });
116
+ //# sourceMappingURL=deduplicate.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deduplicate.test.js","sourceRoot":"","sources":["../../src/memory/deduplicate.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export * from './types.js';
2
+ export { TranscriptParser, formatMemoryContent, formatToolMemoryContent, formatCaptureContent, isTextCapture, isToolCapture, CONFIGURABLE_TOOLS } from './capture.js';
3
+ export type { ToolCapture, TextCapture, Capture, TranscriptEntry, TranscriptParserOptions, ToolCaptureConfig, ConfigurableTool } from './capture.js';
4
+ export { MemoryRetriever, formatContextForInjection } from './retrieve.js';
5
+ export type { EmbedFunction, MemoryRetrieverOptions, FormatOptions } from './retrieve.js';
6
+ export { deduplicateMemories, getDeduplicationStats } from './deduplicate.js';
7
+ export type { DeduplicationOptions } from './deduplicate.js';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/memory/index.ts"],"names":[],"mappings":"AAGA,cAAc,YAAY,CAAC;AAC3B,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,uBAAuB,EACvB,oBAAoB,EACpB,aAAa,EACb,aAAa,EACb,kBAAkB,EACnB,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,WAAW,EACX,WAAW,EACX,OAAO,EACP,eAAe,EACf,uBAAuB,EACvB,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,eAAe,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAC3E,YAAY,EAAE,aAAa,EAAE,sBAAsB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC1F,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAC9E,YAAY,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,7 @@
1
+ // packages/core/src/memory/index.ts
2
+ // Copyright (c) 2026 ZodTTD LLC. MIT License.
3
+ export * from './types.js';
4
+ export { TranscriptParser, formatMemoryContent, formatToolMemoryContent, formatCaptureContent, isTextCapture, isToolCapture, CONFIGURABLE_TOOLS } from './capture.js';
5
+ export { MemoryRetriever, formatContextForInjection } from './retrieve.js';
6
+ export { deduplicateMemories, getDeduplicationStats } from './deduplicate.js';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/memory/index.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,8CAA8C;AAE9C,cAAc,YAAY,CAAC;AAC3B,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,uBAAuB,EACvB,oBAAoB,EACpB,aAAa,EACb,aAAa,EACb,kBAAkB,EACnB,MAAM,cAAc,CAAC;AAUtB,OAAO,EAAE,eAAe,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAE3E,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,62 @@
1
+ import type { SQLiteStorage } from '../storage/sqlite.js';
2
+ import type { LanceDBStorage } from '../storage/lancedb.js';
3
+ import type { Memory, SearchResult, RetrievalOptions, GlobalProfile } from './types.js';
4
+ export type EmbedFunction = (text: string) => Promise<number[]>;
5
+ export interface MemoryRetrieverOptions {
6
+ defaultLimit?: number;
7
+ defaultRecentDays?: number;
8
+ rrfK?: number;
9
+ }
10
+ export declare class MemoryRetriever {
11
+ private sqlite;
12
+ private lancedb;
13
+ private embed;
14
+ private options;
15
+ constructor(sqlite: SQLiteStorage, lancedb: LanceDBStorage, embed: EmbedFunction, options?: MemoryRetrieverOptions);
16
+ /**
17
+ * Full-text search using FTS5
18
+ */
19
+ search(query: string, options?: RetrievalOptions): Promise<SearchResult[]>;
20
+ /**
21
+ * Vector similarity search using LanceDB
22
+ */
23
+ vectorSearch(query: string, options?: RetrievalOptions): Promise<SearchResult[]>;
24
+ /**
25
+ * Hybrid search combining FTS and vector search with RRF fusion
26
+ */
27
+ hybridSearch(query: string, options?: RetrievalOptions): Promise<SearchResult[]>;
28
+ /**
29
+ * Get recent memories for a project
30
+ */
31
+ getRecent(projectId: string | null, options?: RetrievalOptions): Memory[];
32
+ /**
33
+ * Get context for a new session - combines recent memories and global profile
34
+ */
35
+ getContextForSession(projectId: string, options?: RetrievalOptions): Promise<{
36
+ recentMemories: Memory[];
37
+ globalProfile: GlobalProfile[];
38
+ relevantMemories: SearchResult[];
39
+ }>;
40
+ }
41
+ export interface FormatOptions {
42
+ /**
43
+ * Maximum total characters for the formatted output.
44
+ * Memories are excluded if adding them would exceed this limit.
45
+ * Default: 0 (unlimited)
46
+ */
47
+ maxChars?: number;
48
+ /**
49
+ * Maximum characters per memory preview.
50
+ * Default: 200
51
+ */
52
+ previewLength?: number;
53
+ }
54
+ /**
55
+ * Format context for injection into a session
56
+ */
57
+ export declare function formatContextForInjection(context: {
58
+ recentMemories: Memory[];
59
+ globalProfile: GlobalProfile[];
60
+ relevantMemories?: SearchResult[];
61
+ }, options?: FormatOptions): string;
62
+ //# sourceMappingURL=retrieve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retrieve.d.ts","sourceRoot":"","sources":["../../src/memory/retrieve.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAExF,MAAM,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;AAEhE,MAAM,WAAW,sBAAsB;IACrC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,OAAO,CAAmC;gBAGhD,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,cAAc,EACvB,KAAK,EAAE,aAAa,EACpB,OAAO,GAAE,sBAA2B;IAYtC;;OAEG;IACG,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAKpF;;OAEG;IACG,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAuB1F;;OAEG;IACG,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAyC1F;;OAEG;IACH,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,GAAE,gBAAqB,GAAG,MAAM,EAAE;IAM7E;;OAEG;IACG,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC;QACrF,cAAc,EAAE,MAAM,EAAE,CAAC;QACzB,aAAa,EAAE,aAAa,EAAE,CAAC;QAC/B,gBAAgB,EAAE,YAAY,EAAE,CAAC;KAClC,CAAC;CA+BH;AAED,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE;IACP,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,aAAa,EAAE,aAAa,EAAE,CAAC;IAC/B,gBAAgB,CAAC,EAAE,YAAY,EAAE,CAAC;CACnC,EACD,OAAO,GAAE,aAAkB,GAC1B,MAAM,CAwFR"}
@@ -0,0 +1,218 @@
1
+ // packages/core/src/memory/retrieve.ts
2
+ // Copyright (c) 2026 ZodTTD LLC. MIT License.
3
+ export class MemoryRetriever {
4
+ sqlite;
5
+ lancedb;
6
+ embed;
7
+ options;
8
+ constructor(sqlite, lancedb, embed, options = {}) {
9
+ this.sqlite = sqlite;
10
+ this.lancedb = lancedb;
11
+ this.embed = embed;
12
+ this.options = {
13
+ defaultLimit: options.defaultLimit ?? 0, // 0 = unlimited
14
+ defaultRecentDays: options.defaultRecentDays ?? 0, // 0 = unlimited
15
+ rrfK: options.rrfK ?? 60,
16
+ };
17
+ }
18
+ /**
19
+ * Full-text search using FTS5
20
+ */
21
+ async search(query, options = {}) {
22
+ const limit = options.limit ?? this.options.defaultLimit;
23
+ return this.sqlite.searchFTS(query, limit);
24
+ }
25
+ /**
26
+ * Vector similarity search using LanceDB
27
+ */
28
+ async vectorSearch(query, options = {}) {
29
+ const limit = options.limit ?? this.options.defaultLimit;
30
+ const queryVector = await this.embed(query);
31
+ const vectorResults = await this.lancedb.search(queryVector, limit * 2);
32
+ const results = [];
33
+ for (const vr of vectorResults) {
34
+ const memory = this.sqlite.getMemory(vr.id);
35
+ if (memory) {
36
+ // Filter by project if specified
37
+ if (options.projectId && memory.projectId !== options.projectId) {
38
+ continue;
39
+ }
40
+ results.push({
41
+ memory,
42
+ score: vr.score,
43
+ source: 'vector'
44
+ });
45
+ }
46
+ }
47
+ return results.slice(0, limit);
48
+ }
49
+ /**
50
+ * Hybrid search combining FTS and vector search with RRF fusion
51
+ */
52
+ async hybridSearch(query, options = {}) {
53
+ const limit = options.limit ?? this.options.defaultLimit;
54
+ const k = this.options.rrfK;
55
+ // Get results from both sources in parallel
56
+ const [ftsResults, vectorResults] = await Promise.all([
57
+ this.search(query, { ...options, limit: limit * 2 }),
58
+ this.vectorSearch(query, { ...options, limit: limit * 2 })
59
+ ]);
60
+ // Apply Reciprocal Rank Fusion (RRF)
61
+ const scores = new Map();
62
+ const memories = new Map();
63
+ // Score FTS results
64
+ ftsResults.forEach((result, rank) => {
65
+ const rrfScore = 1 / (k + rank + 1);
66
+ scores.set(result.memory.id, (scores.get(result.memory.id) ?? 0) + rrfScore);
67
+ memories.set(result.memory.id, result.memory);
68
+ });
69
+ // Score vector results
70
+ vectorResults.forEach((result, rank) => {
71
+ const rrfScore = 1 / (k + rank + 1);
72
+ scores.set(result.memory.id, (scores.get(result.memory.id) ?? 0) + rrfScore);
73
+ memories.set(result.memory.id, result.memory);
74
+ });
75
+ // Sort by combined score and return top results
76
+ const combined = Array.from(scores.entries())
77
+ .sort((a, b) => b[1] - a[1])
78
+ .slice(0, limit)
79
+ .map(([id, score]) => ({
80
+ memory: memories.get(id),
81
+ score,
82
+ source: 'hybrid'
83
+ }));
84
+ return combined;
85
+ }
86
+ /**
87
+ * Get recent memories for a project
88
+ */
89
+ getRecent(projectId, options = {}) {
90
+ const limit = options.limit ?? this.options.defaultLimit;
91
+ const days = options.recentDays ?? this.options.defaultRecentDays;
92
+ return this.sqlite.getRecentMemories(projectId, limit, days);
93
+ }
94
+ /**
95
+ * Get context for a new session - combines recent memories and global profile
96
+ */
97
+ async getContextForSession(projectId, options = {}) {
98
+ const limit = options.limit ?? this.options.defaultLimit;
99
+ const includeGlobal = options.includeGlobal ?? true;
100
+ // Get recent project memories
101
+ const recentMemories = this.getRecent(projectId, {
102
+ limit: Math.floor(limit / 2),
103
+ recentDays: options.recentDays
104
+ });
105
+ // Get global profile if requested
106
+ const globalProfile = includeGlobal
107
+ ? this.sqlite.getGlobalProfiles(5)
108
+ : [];
109
+ // Get project info for semantic search
110
+ const project = this.sqlite.getProject(projectId);
111
+ const projectName = project?.name ?? 'project';
112
+ // Semantic search for relevant memories
113
+ const relevantMemories = await this.vectorSearch(projectName, {
114
+ projectId,
115
+ limit: Math.floor(limit / 2)
116
+ });
117
+ return {
118
+ recentMemories,
119
+ globalProfile,
120
+ relevantMemories
121
+ };
122
+ }
123
+ }
124
+ /**
125
+ * Format context for injection into a session
126
+ */
127
+ export function formatContextForInjection(context, options = {}) {
128
+ const maxChars = options.maxChars ?? 0; // 0 = unlimited
129
+ const previewLength = options.previewLength ?? 200;
130
+ const lines = ['<memextend-context>', '## Your Memory for This Project', ''];
131
+ let currentLength = lines.join('\n').length;
132
+ // Footer that will always be added
133
+ const footer = [
134
+ 'Use these memories naturally. Use `memextend_search` to find more details.',
135
+ 'Use `memextend_save` to remember important decisions for future sessions.',
136
+ '</memextend-context>'
137
+ ].join('\n');
138
+ const footerLength = footer.length + 1; // +1 for newline before footer
139
+ // Helper to check if we can add more content
140
+ const canAdd = (text) => {
141
+ if (maxChars === 0)
142
+ return true; // unlimited
143
+ return currentLength + text.length + footerLength <= maxChars;
144
+ };
145
+ // Recent work section
146
+ if (context.recentMemories.length > 0) {
147
+ const sectionHeader = '### Recent Work\n';
148
+ if (canAdd(sectionHeader)) {
149
+ lines.push('### Recent Work');
150
+ currentLength += sectionHeader.length;
151
+ for (const memory of context.recentMemories) {
152
+ const date = formatRelativeDate(memory.createdAt);
153
+ const preview = memory.content.split('\n')[0].slice(0, previewLength);
154
+ const line = `- [${date}] ${preview}\n`;
155
+ if (!canAdd(line))
156
+ break; // Stop if we'd exceed limit
157
+ lines.push(`- [${date}] ${preview}`);
158
+ currentLength += line.length;
159
+ }
160
+ lines.push('');
161
+ currentLength += 1;
162
+ }
163
+ }
164
+ // Global preferences section
165
+ if (context.globalProfile.length > 0) {
166
+ const sectionHeader = '### User Preferences (Global)\n';
167
+ if (canAdd(sectionHeader)) {
168
+ lines.push('### User Preferences (Global)');
169
+ currentLength += sectionHeader.length;
170
+ for (const profile of context.globalProfile) {
171
+ const line = `- ${profile.content}\n`;
172
+ if (!canAdd(line))
173
+ break;
174
+ lines.push(`- ${profile.content}`);
175
+ currentLength += line.length;
176
+ }
177
+ lines.push('');
178
+ currentLength += 1;
179
+ }
180
+ }
181
+ // Relevant memories section (if provided)
182
+ if (context.relevantMemories && context.relevantMemories.length > 0) {
183
+ const sectionHeader = '### Relevant Past Work\n';
184
+ if (canAdd(sectionHeader)) {
185
+ lines.push('### Relevant Past Work');
186
+ currentLength += sectionHeader.length;
187
+ for (const result of context.relevantMemories) {
188
+ const preview = result.memory.content.split('\n')[0].slice(0, previewLength);
189
+ const line = `- ${preview}\n`;
190
+ if (!canAdd(line))
191
+ break;
192
+ lines.push(`- ${preview}`);
193
+ currentLength += line.length;
194
+ }
195
+ lines.push('');
196
+ }
197
+ }
198
+ lines.push('Use these memories naturally. Use `memextend_search` to find more details.');
199
+ lines.push('Use `memextend_save` to remember important decisions for future sessions.');
200
+ lines.push('</memextend-context>');
201
+ return lines.join('\n');
202
+ }
203
+ function formatRelativeDate(isoDate) {
204
+ const date = new Date(isoDate);
205
+ const now = new Date();
206
+ const diffMs = now.getTime() - date.getTime();
207
+ const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
208
+ if (diffDays === 0)
209
+ return 'today';
210
+ if (diffDays === 1)
211
+ return 'yesterday';
212
+ if (diffDays < 7)
213
+ return `${diffDays} days ago`;
214
+ if (diffDays < 30)
215
+ return `${Math.floor(diffDays / 7)} weeks ago`;
216
+ return `${Math.floor(diffDays / 30)} months ago`;
217
+ }
218
+ //# sourceMappingURL=retrieve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retrieve.js","sourceRoot":"","sources":["../../src/memory/retrieve.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=retrieve.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retrieve.test.d.ts","sourceRoot":"","sources":["../../src/memory/retrieve.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,177 @@
1
+ // packages/core/src/memory/retrieve.test.ts
2
+ // Copyright (c) 2026 ZodTTD LLC. MIT License.
3
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
4
+ import { mkdtemp, rm } from 'fs/promises';
5
+ import { join } from 'path';
6
+ import { tmpdir } from 'os';
7
+ import { MemoryRetriever, formatContextForInjection } from './retrieve.js';
8
+ import { SQLiteStorage } from '../storage/sqlite.js';
9
+ import { LanceDBStorage } from '../storage/lancedb.js';
10
+ describe('MemoryRetriever', () => {
11
+ let tempDir;
12
+ let sqlite;
13
+ let lancedb;
14
+ let retriever;
15
+ // Mock embedding function for tests
16
+ const mockEmbed = async (text) => {
17
+ // Simple deterministic mock: hash the text to create a consistent vector
18
+ let hash = 0;
19
+ for (let i = 0; i < text.length; i++) {
20
+ hash = ((hash << 5) - hash) + text.charCodeAt(i);
21
+ hash = hash & hash;
22
+ }
23
+ return new Array(384).fill(0).map((_, i) => Math.sin(hash + i) * 0.5 + 0.5);
24
+ };
25
+ beforeEach(async () => {
26
+ tempDir = await mkdtemp(join(tmpdir(), 'memextend-retrieve-test-'));
27
+ sqlite = new SQLiteStorage(join(tempDir, 'test.db'));
28
+ lancedb = await LanceDBStorage.create(join(tempDir, 'vectors'));
29
+ retriever = new MemoryRetriever(sqlite, lancedb, mockEmbed);
30
+ // Seed test data
31
+ await seedTestMemories(sqlite, lancedb, mockEmbed);
32
+ });
33
+ afterEach(async () => {
34
+ sqlite.close();
35
+ await lancedb.close();
36
+ await rm(tempDir, { recursive: true });
37
+ });
38
+ it('should retrieve memories by FTS', async () => {
39
+ const results = await retriever.search('Redis caching', { limit: 5 });
40
+ expect(results.length).toBeGreaterThan(0);
41
+ expect(results[0].source).toBe('fts');
42
+ });
43
+ it('should retrieve memories by vector search', async () => {
44
+ const results = await retriever.vectorSearch('database caching', { limit: 5 });
45
+ expect(results.length).toBeGreaterThan(0);
46
+ expect(results[0].source).toBe('vector');
47
+ });
48
+ it('should retrieve recent memories for project', () => {
49
+ const results = retriever.getRecent('project-1', { limit: 5 });
50
+ expect(results.length).toBeGreaterThan(0);
51
+ expect(results.every(m => m.projectId === 'project-1')).toBe(true);
52
+ });
53
+ it('should perform hybrid search with RRF fusion', async () => {
54
+ const results = await retriever.hybridSearch('authentication JWT', { limit: 5 });
55
+ expect(results.length).toBeGreaterThan(0);
56
+ expect(results[0].source).toBe('hybrid');
57
+ expect(results[0].score).toBeGreaterThan(0);
58
+ });
59
+ it('should get context for session', async () => {
60
+ // Add a project first
61
+ sqlite.insertProject({
62
+ id: 'project-1',
63
+ name: 'my-project',
64
+ path: '/home/user/my-project',
65
+ createdAt: new Date().toISOString()
66
+ });
67
+ // Add global profile
68
+ sqlite.insertGlobalProfile({
69
+ id: 'pref-1',
70
+ key: 'preference',
71
+ content: 'Prefers Vitest over Jest',
72
+ createdAt: new Date().toISOString()
73
+ });
74
+ const context = await retriever.getContextForSession('project-1', { includeGlobal: true });
75
+ expect(context.recentMemories.length).toBeGreaterThanOrEqual(0);
76
+ expect(context.globalProfile.length).toBe(1);
77
+ expect(context.globalProfile[0].content).toBe('Prefers Vitest over Jest');
78
+ });
79
+ it('should filter vector search by project', async () => {
80
+ const results = await retriever.vectorSearch('express', { projectId: 'project-2', limit: 5 });
81
+ expect(results.every(r => r.memory.projectId === 'project-2')).toBe(true);
82
+ });
83
+ });
84
+ describe('formatContextForInjection', () => {
85
+ it('should format context with recent memories', () => {
86
+ const context = {
87
+ recentMemories: [
88
+ createMemory('mem-1', 'project-1', '[Edit] src/auth.ts - Added JWT validation'),
89
+ createMemory('mem-2', 'project-1', '[Bash] npm install jose')
90
+ ],
91
+ globalProfile: [],
92
+ relevantMemories: []
93
+ };
94
+ const formatted = formatContextForInjection(context);
95
+ expect(formatted).toContain('<memextend-context>');
96
+ expect(formatted).toContain('</memextend-context>');
97
+ expect(formatted).toContain('Recent Work');
98
+ expect(formatted).toContain('JWT validation');
99
+ });
100
+ it('should format context with global profile', () => {
101
+ const context = {
102
+ recentMemories: [],
103
+ globalProfile: [
104
+ { id: 'pref-1', key: 'preference', content: 'Prefers TypeScript', createdAt: new Date().toISOString() }
105
+ ],
106
+ relevantMemories: []
107
+ };
108
+ const formatted = formatContextForInjection(context);
109
+ expect(formatted).toContain('User Preferences');
110
+ expect(formatted).toContain('Prefers TypeScript');
111
+ });
112
+ it('should format context with relevant memories', () => {
113
+ const context = {
114
+ recentMemories: [],
115
+ globalProfile: [],
116
+ relevantMemories: [
117
+ { memory: createMemory('mem-1', 'project-1', '[Edit] Redis caching setup'), score: 0.9, source: 'vector' }
118
+ ]
119
+ };
120
+ const formatted = formatContextForInjection(context);
121
+ expect(formatted).toContain('Relevant Past Work');
122
+ expect(formatted).toContain('Redis caching');
123
+ });
124
+ });
125
+ // Helper functions
126
+ async function seedTestMemories(sqlite, lancedb, embed) {
127
+ const memories = [
128
+ {
129
+ id: 'mem-1',
130
+ projectId: 'project-1',
131
+ content: '[Edit] src/cache.ts - Added Redis caching layer',
132
+ type: 'tool_capture',
133
+ sourceTool: 'Edit',
134
+ createdAt: new Date().toISOString(),
135
+ sessionId: 'sess-1',
136
+ metadata: null
137
+ },
138
+ {
139
+ id: 'mem-2',
140
+ projectId: 'project-1',
141
+ content: '[Edit] src/auth.ts - Implemented JWT authentication',
142
+ type: 'tool_capture',
143
+ sourceTool: 'Edit',
144
+ createdAt: new Date().toISOString(),
145
+ sessionId: 'sess-1',
146
+ metadata: null
147
+ },
148
+ {
149
+ id: 'mem-3',
150
+ projectId: 'project-2',
151
+ content: '[Bash] npm install express',
152
+ type: 'tool_capture',
153
+ sourceTool: 'Bash',
154
+ createdAt: new Date().toISOString(),
155
+ sessionId: 'sess-2',
156
+ metadata: null
157
+ }
158
+ ];
159
+ for (const memory of memories) {
160
+ sqlite.insertMemory(memory);
161
+ const vector = await embed(memory.content);
162
+ await lancedb.insertVector(memory.id, vector);
163
+ }
164
+ }
165
+ function createMemory(id, projectId, content) {
166
+ return {
167
+ id,
168
+ projectId,
169
+ content,
170
+ type: 'tool_capture',
171
+ sourceTool: 'Edit',
172
+ createdAt: new Date().toISOString(),
173
+ sessionId: null,
174
+ metadata: null
175
+ };
176
+ }
177
+ //# sourceMappingURL=retrieve.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retrieve.test.js","sourceRoot":"","sources":["../../src/memory/retrieve.test.ts"],"names":[],"mappings":"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"}