@synth-coder/memhub 0.2.3 → 0.2.5

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 (118) hide show
  1. package/.github/workflows/ci.yml +48 -12
  2. package/.github/workflows/release.yml +70 -0
  3. package/AGENTS.md +71 -73
  4. package/README.md +284 -195
  5. package/README.zh-CN.md +90 -30
  6. package/dist/src/cli/agents/claude-code.d.ts +5 -0
  7. package/dist/src/cli/agents/claude-code.d.ts.map +1 -0
  8. package/dist/src/cli/agents/claude-code.js +14 -0
  9. package/dist/src/cli/agents/claude-code.js.map +1 -0
  10. package/dist/src/cli/agents/cline.d.ts +5 -0
  11. package/dist/src/cli/agents/cline.d.ts.map +1 -0
  12. package/dist/src/cli/agents/cline.js +14 -0
  13. package/dist/src/cli/agents/cline.js.map +1 -0
  14. package/dist/src/cli/agents/cursor.d.ts +5 -0
  15. package/dist/src/cli/agents/cursor.d.ts.map +1 -0
  16. package/dist/src/cli/agents/cursor.js +14 -0
  17. package/dist/src/cli/agents/cursor.js.map +1 -0
  18. package/dist/src/cli/agents/factory-droid.d.ts +5 -0
  19. package/dist/src/cli/agents/factory-droid.d.ts.map +1 -0
  20. package/dist/src/cli/agents/factory-droid.js +14 -0
  21. package/dist/src/cli/agents/factory-droid.js.map +1 -0
  22. package/dist/src/cli/agents/gemini-cli.d.ts +5 -0
  23. package/dist/src/cli/agents/gemini-cli.d.ts.map +1 -0
  24. package/dist/src/cli/agents/gemini-cli.js +14 -0
  25. package/dist/src/cli/agents/gemini-cli.js.map +1 -0
  26. package/dist/src/cli/agents/index.d.ts +13 -0
  27. package/dist/src/cli/agents/index.d.ts.map +1 -0
  28. package/dist/src/cli/agents/index.js +27 -0
  29. package/dist/src/cli/agents/index.js.map +1 -0
  30. package/dist/src/cli/agents/windsurf.d.ts +5 -0
  31. package/dist/src/cli/agents/windsurf.d.ts.map +1 -0
  32. package/dist/src/cli/agents/windsurf.js +14 -0
  33. package/dist/src/cli/agents/windsurf.js.map +1 -0
  34. package/dist/src/cli/index.d.ts +8 -0
  35. package/dist/src/cli/index.d.ts.map +1 -0
  36. package/dist/src/cli/index.js +168 -0
  37. package/dist/src/cli/index.js.map +1 -0
  38. package/dist/src/cli/init.d.ts +34 -0
  39. package/dist/src/cli/init.d.ts.map +1 -0
  40. package/dist/src/cli/init.js +140 -0
  41. package/dist/src/cli/init.js.map +1 -0
  42. package/dist/src/cli/instructions.d.ts +29 -0
  43. package/dist/src/cli/instructions.d.ts.map +1 -0
  44. package/dist/src/cli/instructions.js +141 -0
  45. package/dist/src/cli/instructions.js.map +1 -0
  46. package/dist/src/cli/types.d.ts +22 -0
  47. package/dist/src/cli/types.d.ts.map +1 -0
  48. package/dist/src/cli/types.js +75 -0
  49. package/dist/src/cli/types.js.map +1 -0
  50. package/dist/src/contracts/mcp.js +34 -34
  51. package/dist/src/contracts/schemas.js.map +1 -1
  52. package/dist/src/server/mcp-server.d.ts.map +1 -1
  53. package/dist/src/server/mcp-server.js +7 -14
  54. package/dist/src/server/mcp-server.js.map +1 -1
  55. package/dist/src/services/embedding-service.d.ts.map +1 -1
  56. package/dist/src/services/embedding-service.js +1 -1
  57. package/dist/src/services/embedding-service.js.map +1 -1
  58. package/dist/src/services/memory-service.d.ts.map +1 -1
  59. package/dist/src/services/memory-service.js.map +1 -1
  60. package/dist/src/storage/markdown-storage.d.ts.map +1 -1
  61. package/dist/src/storage/markdown-storage.js +1 -1
  62. package/dist/src/storage/markdown-storage.js.map +1 -1
  63. package/dist/src/storage/vector-index.d.ts.map +1 -1
  64. package/dist/src/storage/vector-index.js +4 -5
  65. package/dist/src/storage/vector-index.js.map +1 -1
  66. package/docs/README.md +21 -0
  67. package/docs/mcp-tools.md +136 -0
  68. package/docs/user-guide.md +184 -0
  69. package/package.json +61 -59
  70. package/src/cli/agents/claude-code.ts +14 -0
  71. package/src/cli/agents/cline.ts +14 -0
  72. package/src/cli/agents/codex.ts +14 -0
  73. package/src/cli/agents/cursor.ts +14 -0
  74. package/src/cli/agents/factory-droid.ts +14 -0
  75. package/src/cli/agents/gemini-cli.ts +14 -0
  76. package/src/cli/agents/index.ts +36 -0
  77. package/src/cli/agents/windsurf.ts +14 -0
  78. package/src/cli/index.ts +192 -0
  79. package/src/cli/init.ts +218 -0
  80. package/src/cli/instructions.ts +156 -0
  81. package/src/cli/types.ts +112 -0
  82. package/src/contracts/index.ts +12 -12
  83. package/src/contracts/mcp.ts +223 -223
  84. package/src/contracts/schemas.ts +307 -307
  85. package/src/contracts/types.ts +410 -410
  86. package/src/index.ts +8 -8
  87. package/src/server/index.ts +5 -5
  88. package/src/server/mcp-server.ts +169 -186
  89. package/src/services/embedding-service.ts +114 -114
  90. package/src/services/index.ts +5 -5
  91. package/src/services/memory-service.ts +656 -663
  92. package/src/storage/frontmatter-parser.ts +243 -243
  93. package/src/storage/index.ts +6 -6
  94. package/src/storage/markdown-storage.ts +228 -236
  95. package/src/storage/vector-index.ts +159 -160
  96. package/src/utils/index.ts +5 -5
  97. package/src/utils/slugify.ts +63 -63
  98. package/test/cli/init.test.ts +402 -0
  99. package/test/contracts/schemas.test.ts +313 -313
  100. package/test/contracts/types.test.ts +21 -21
  101. package/test/frontmatter-parser-more.test.ts +94 -94
  102. package/test/server/mcp-server.test.ts +211 -210
  103. package/test/services/memory-service-edge.test.ts +248 -248
  104. package/test/services/memory-service.test.ts +291 -279
  105. package/test/storage/frontmatter-parser.test.ts +223 -223
  106. package/test/storage/markdown-storage.test.ts +226 -217
  107. package/test/storage/storage-edge.test.ts +238 -238
  108. package/test/storage/vector-index.test.ts +149 -153
  109. package/test/utils/slugify-edge.test.ts +94 -94
  110. package/test/utils/slugify.test.ts +72 -68
  111. package/docs/architecture-diagrams.md +0 -368
  112. package/docs/architecture.md +0 -381
  113. package/docs/contracts.md +0 -190
  114. package/docs/prompt-template.md +0 -33
  115. package/docs/proposals/mcp-typescript-sdk-refactor.md +0 -568
  116. package/docs/proposals/proposal-close-gates.md +0 -58
  117. package/docs/tool-calling-policy.md +0 -101
  118. package/docs/vector-search.md +0 -306
@@ -1,217 +1,226 @@
1
- /**
2
- * Markdown Storage Tests
3
- * Tests for the MarkdownStorage class
4
- */
5
-
6
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
7
- import { mkdtempSync, rmSync, existsSync, readFileSync } from 'fs';
8
- import { tmpdir } from 'os';
9
- import { join } from 'path';
10
- import { MarkdownStorage, StorageError } from '../../src/storage/markdown-storage.js';
11
- import type { Memory } from '../../src/contracts/types.js';
12
-
13
- describe('MarkdownStorage', () => {
14
- let tempDir: string;
15
- let storage: MarkdownStorage;
16
-
17
- beforeEach(() => {
18
- tempDir = mkdtempSync(join(tmpdir(), 'memhub-storage-test-'));
19
- storage = new MarkdownStorage({ storagePath: tempDir });
20
- });
21
-
22
- afterEach(() => {
23
- rmSync(tempDir, { recursive: true, force: true });
24
- });
25
-
26
- describe('write', () => {
27
- const sampleMemory: Memory = {
28
- id: '550e8400-e29b-41d4-a716-446655440000',
29
- createdAt: '2024-03-15T10:30:00Z',
30
- updatedAt: '2024-03-15T10:30:00Z',
31
- sessionId: '550e8400-e29b-41d4-a716-446655440999',
32
- tags: ['test', 'memory'],
33
- category: 'testing',
34
- importance: 3,
35
- title: 'Test Memory',
36
- content: 'This is the content of the test memory.',
37
- };
38
-
39
- it('should write memory to markdown file', async () => {
40
- const result = await storage.write(sampleMemory);
41
- expect(existsSync(result)).toBe(true);
42
- expect(result).toContain(`${sampleMemory.createdAt.split('T')[0]}`);
43
- expect(result).toContain(sampleMemory.sessionId as string);
44
- });
45
-
46
- it('should write valid YAML front matter', async () => {
47
- const filePath = await storage.write(sampleMemory);
48
- const content = readFileSync(filePath, 'utf-8');
49
- expect(content).toMatch(/^---\n/);
50
- expect(content).toContain('id: "550e8400-e29b-41d4-a716-446655440000"');
51
- expect(content).toContain('created_at: "2024-03-15T10:30:00Z"');
52
- expect(content).toContain('session_id: "550e8400-e29b-41d4-a716-446655440999"');
53
- });
54
-
55
- it('should write markdown body with title', async () => {
56
- const filePath = await storage.write(sampleMemory);
57
- const content = readFileSync(filePath, 'utf-8');
58
- expect(content).toContain('# Test Memory');
59
- expect(content).toContain('This is the content');
60
- });
61
-
62
- it('should write tags as YAML array', async () => {
63
- const filePath = await storage.write(sampleMemory);
64
- const content = readFileSync(filePath, 'utf-8');
65
- expect(content).toContain('tags:');
66
- expect(content).toContain('test');
67
- expect(content).toContain('memory');
68
- });
69
-
70
- it('should return nested file path', async () => {
71
- const result = await storage.write(sampleMemory);
72
- expect(result).toContain('test-memory.md');
73
- expect(result).toContain('2024-03-15');
74
- expect(result).toContain('550e8400-e29b-41d4-a716-446655440999');
75
- });
76
- });
77
-
78
- describe('read', () => {
79
- it('should read memory from markdown file', async () => {
80
- // Create a test file first
81
- const testContent = `---
82
- id: "550e8400-e29b-41d4-a716-446655440000"
83
- created_at: "2024-03-15T10:30:00Z"
84
- updated_at: "2024-03-15T10:30:00Z"
85
- tags:
86
- - test
87
- category: "testing"
88
- importance: 3
89
- ---
90
-
91
- # Test Memory
92
-
93
- This is the content.
94
- `;
95
- const filePath = join(tempDir, 'test.md');
96
- // Use sync write for test setup
97
- const { writeFileSync } = await import('fs');
98
- writeFileSync(filePath, testContent);
99
-
100
- const memory = await storage.read('550e8400-e29b-41d4-a716-446655440000');
101
- expect(memory.id).toBe('550e8400-e29b-41d4-a716-446655440000');
102
- expect(memory.title).toBe('Test Memory');
103
- });
104
-
105
- it('should throw error when file not found', async () => {
106
- await expect(
107
- storage.read('550e8400-e29b-41d4-a716-446655440000')
108
- ).rejects.toThrow(StorageError);
109
- });
110
-
111
- it('should parse front matter correctly', async () => {
112
- const testContent = `---
113
- id: "550e8400-e29b-41d4-a716-446655440000"
114
- created_at: "2024-03-15T10:30:00Z"
115
- updated_at: "2024-03-15T14:20:00Z"
116
- tags:
117
- - tag1
118
- - tag2
119
- category: "work"
120
- importance: 4
121
- ---
122
-
123
- # Test Title
124
-
125
- Test content.
126
- `;
127
- const { writeFileSync } = await import('fs');
128
- writeFileSync(join(tempDir, 'test.md'), testContent);
129
-
130
- const memory = await storage.read('550e8400-e29b-41d4-a716-446655440000');
131
- expect(memory.tags).toEqual(['tag1', 'tag2']);
132
- expect(memory.category).toBe('work');
133
- expect(memory.importance).toBe(4);
134
- });
135
- });
136
-
137
- describe('delete', () => {
138
- it('should delete memory file', async () => {
139
- // Create a test file first
140
- const testContent = `---
141
- id: "550e8400-e29b-41d4-a716-446655440000"
142
- created_at: "2024-03-15T10:30:00Z"
143
- updated_at: "2024-03-15T10:30:00Z"
144
- tags: []
145
- category: "general"
146
- importance: 3
147
- ---
148
-
149
- # Test
150
- `;
151
- const filePath = join(tempDir, 'test.md');
152
- const { writeFileSync } = await import('fs');
153
- writeFileSync(filePath, testContent);
154
-
155
- await storage.delete('550e8400-e29b-41d4-a716-446655440000');
156
- expect(existsSync(filePath)).toBe(false);
157
- });
158
-
159
- it('should throw error when file not found', async () => {
160
- await expect(
161
- storage.delete('550e8400-e29b-41d4-a716-446655440000')
162
- ).rejects.toThrow(StorageError);
163
- });
164
- });
165
-
166
- describe('list', () => {
167
- it('should list all memory files', async () => {
168
- const { writeFileSync } = await import('fs');
169
- writeFileSync(join(tempDir, '2024-03-15-a.md'), '---\nid: "a"\ncreated_at: "2024-03-15T10:30:00Z"\nupdated_at: "2024-03-15T10:30:00Z"\ntags: []\ncategory: "general"\nimportance: 3\n---\n\n# A');
170
- writeFileSync(join(tempDir, '2024-03-16-b.md'), '---\nid: "b"\ncreated_at: "2024-03-16T10:30:00Z"\nupdated_at: "2024-03-16T10:30:00Z"\ntags: []\ncategory: "general"\nimportance: 3\n---\n\n# B');
171
-
172
- const files = await storage.list();
173
- expect(files).toHaveLength(2);
174
- });
175
-
176
- it('should return empty array when no files exist', async () => {
177
- const files = await storage.list();
178
- expect(files).toEqual([]);
179
- });
180
-
181
- it('should only include .md files', async () => {
182
- const { writeFileSync } = await import('fs');
183
- writeFileSync(join(tempDir, 'test.md'), '---\nid: "test"\ncreated_at: "2024-03-15T10:30:00Z"\nupdated_at: "2024-03-15T10:30:00Z"\ntags: []\ncategory: "general"\nimportance: 3\n---\n\n# Test');
184
- writeFileSync(join(tempDir, 'test.txt'), 'not markdown');
185
-
186
- const files = await storage.list();
187
- expect(files).toHaveLength(1);
188
- expect(files[0].filename).toBe('test.md');
189
- });
190
- });
191
-
192
- describe('findById', () => {
193
- it('should find file by memory ID', async () => {
194
- const testContent = `---
195
- id: "550e8400-e29b-41d4-a716-446655440000"
196
- created_at: "2024-03-15T10:30:00Z"
197
- updated_at: "2024-03-15T10:30:00Z"
198
- tags: []
199
- category: "general"
200
- importance: 3
201
- ---
202
-
203
- # Test
204
- `;
205
- const { writeFileSync } = await import('fs');
206
- writeFileSync(join(tempDir, 'test.md'), testContent);
207
-
208
- const filePath = await storage.findById('550e8400-e29b-41d4-a716-446655440000');
209
- expect(filePath).toContain('test.md');
210
- });
211
-
212
- it('should return null when ID not found', async () => {
213
- const filePath = await storage.findById('550e8400-e29b-41d4-a716-446655440000');
214
- expect(filePath).toBeNull();
215
- });
216
- });
217
- });
1
+ /**
2
+ * Markdown Storage Tests
3
+ * Tests for the MarkdownStorage class
4
+ */
5
+
6
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
7
+ import { mkdtempSync, rmSync, existsSync, readFileSync } from 'fs';
8
+ import { tmpdir } from 'os';
9
+ import { join } from 'path';
10
+ import { MarkdownStorage, StorageError } from '../../src/storage/markdown-storage.js';
11
+ import type { Memory } from '../../src/contracts/types.js';
12
+
13
+ describe('MarkdownStorage', () => {
14
+ let tempDir: string;
15
+ let storage: MarkdownStorage;
16
+
17
+ beforeEach(() => {
18
+ tempDir = mkdtempSync(join(tmpdir(), 'memhub-storage-test-'));
19
+ storage = new MarkdownStorage({ storagePath: tempDir });
20
+ });
21
+
22
+ afterEach(() => {
23
+ rmSync(tempDir, { recursive: true, force: true });
24
+ });
25
+
26
+ describe('write', () => {
27
+ const sampleMemory: Memory = {
28
+ id: '550e8400-e29b-41d4-a716-446655440000',
29
+ createdAt: '2024-03-15T10:30:00Z',
30
+ updatedAt: '2024-03-15T10:30:00Z',
31
+ sessionId: '550e8400-e29b-41d4-a716-446655440999',
32
+ tags: ['test', 'memory'],
33
+ category: 'testing',
34
+ importance: 3,
35
+ title: 'Test Memory',
36
+ content: 'This is the content of the test memory.',
37
+ };
38
+
39
+ it('should write memory to markdown file', async () => {
40
+ const result = await storage.write(sampleMemory);
41
+ expect(existsSync(result)).toBe(true);
42
+ expect(result).toContain(`${sampleMemory.createdAt.split('T')[0]}`);
43
+ expect(result).toContain(sampleMemory.sessionId as string);
44
+ });
45
+
46
+ it('should write valid YAML front matter', async () => {
47
+ const filePath = await storage.write(sampleMemory);
48
+ const content = readFileSync(filePath, 'utf-8');
49
+ expect(content).toMatch(/^---\n/);
50
+ expect(content).toContain('id: "550e8400-e29b-41d4-a716-446655440000"');
51
+ expect(content).toContain('created_at: "2024-03-15T10:30:00Z"');
52
+ expect(content).toContain('session_id: "550e8400-e29b-41d4-a716-446655440999"');
53
+ });
54
+
55
+ it('should write markdown body with title', async () => {
56
+ const filePath = await storage.write(sampleMemory);
57
+ const content = readFileSync(filePath, 'utf-8');
58
+ expect(content).toContain('# Test Memory');
59
+ expect(content).toContain('This is the content');
60
+ });
61
+
62
+ it('should write tags as YAML array', async () => {
63
+ const filePath = await storage.write(sampleMemory);
64
+ const content = readFileSync(filePath, 'utf-8');
65
+ expect(content).toContain('tags:');
66
+ expect(content).toContain('test');
67
+ expect(content).toContain('memory');
68
+ });
69
+
70
+ it('should return nested file path', async () => {
71
+ const result = await storage.write(sampleMemory);
72
+ expect(result).toContain('test-memory.md');
73
+ expect(result).toContain('2024-03-15');
74
+ expect(result).toContain('550e8400-e29b-41d4-a716-446655440999');
75
+ });
76
+ });
77
+
78
+ describe('read', () => {
79
+ it('should read memory from markdown file', async () => {
80
+ // Create a test file first
81
+ const testContent = `---
82
+ id: "550e8400-e29b-41d4-a716-446655440000"
83
+ created_at: "2024-03-15T10:30:00Z"
84
+ updated_at: "2024-03-15T10:30:00Z"
85
+ tags:
86
+ - test
87
+ category: "testing"
88
+ importance: 3
89
+ ---
90
+
91
+ # Test Memory
92
+
93
+ This is the content.
94
+ `;
95
+ const filePath = join(tempDir, 'test.md');
96
+ // Use sync write for test setup
97
+ const { writeFileSync } = await import('fs');
98
+ writeFileSync(filePath, testContent);
99
+
100
+ const memory = await storage.read('550e8400-e29b-41d4-a716-446655440000');
101
+ expect(memory.id).toBe('550e8400-e29b-41d4-a716-446655440000');
102
+ expect(memory.title).toBe('Test Memory');
103
+ });
104
+
105
+ it('should throw error when file not found', async () => {
106
+ await expect(storage.read('550e8400-e29b-41d4-a716-446655440000')).rejects.toThrow(
107
+ StorageError
108
+ );
109
+ });
110
+
111
+ it('should parse front matter correctly', async () => {
112
+ const testContent = `---
113
+ id: "550e8400-e29b-41d4-a716-446655440000"
114
+ created_at: "2024-03-15T10:30:00Z"
115
+ updated_at: "2024-03-15T14:20:00Z"
116
+ tags:
117
+ - tag1
118
+ - tag2
119
+ category: "work"
120
+ importance: 4
121
+ ---
122
+
123
+ # Test Title
124
+
125
+ Test content.
126
+ `;
127
+ const { writeFileSync } = await import('fs');
128
+ writeFileSync(join(tempDir, 'test.md'), testContent);
129
+
130
+ const memory = await storage.read('550e8400-e29b-41d4-a716-446655440000');
131
+ expect(memory.tags).toEqual(['tag1', 'tag2']);
132
+ expect(memory.category).toBe('work');
133
+ expect(memory.importance).toBe(4);
134
+ });
135
+ });
136
+
137
+ describe('delete', () => {
138
+ it('should delete memory file', async () => {
139
+ // Create a test file first
140
+ const testContent = `---
141
+ id: "550e8400-e29b-41d4-a716-446655440000"
142
+ created_at: "2024-03-15T10:30:00Z"
143
+ updated_at: "2024-03-15T10:30:00Z"
144
+ tags: []
145
+ category: "general"
146
+ importance: 3
147
+ ---
148
+
149
+ # Test
150
+ `;
151
+ const filePath = join(tempDir, 'test.md');
152
+ const { writeFileSync } = await import('fs');
153
+ writeFileSync(filePath, testContent);
154
+
155
+ await storage.delete('550e8400-e29b-41d4-a716-446655440000');
156
+ expect(existsSync(filePath)).toBe(false);
157
+ });
158
+
159
+ it('should throw error when file not found', async () => {
160
+ await expect(storage.delete('550e8400-e29b-41d4-a716-446655440000')).rejects.toThrow(
161
+ StorageError
162
+ );
163
+ });
164
+ });
165
+
166
+ describe('list', () => {
167
+ it('should list all memory files', async () => {
168
+ const { writeFileSync } = await import('fs');
169
+ writeFileSync(
170
+ join(tempDir, '2024-03-15-a.md'),
171
+ '---\nid: "a"\ncreated_at: "2024-03-15T10:30:00Z"\nupdated_at: "2024-03-15T10:30:00Z"\ntags: []\ncategory: "general"\nimportance: 3\n---\n\n# A'
172
+ );
173
+ writeFileSync(
174
+ join(tempDir, '2024-03-16-b.md'),
175
+ '---\nid: "b"\ncreated_at: "2024-03-16T10:30:00Z"\nupdated_at: "2024-03-16T10:30:00Z"\ntags: []\ncategory: "general"\nimportance: 3\n---\n\n# B'
176
+ );
177
+
178
+ const files = await storage.list();
179
+ expect(files).toHaveLength(2);
180
+ });
181
+
182
+ it('should return empty array when no files exist', async () => {
183
+ const files = await storage.list();
184
+ expect(files).toEqual([]);
185
+ });
186
+
187
+ it('should only include .md files', async () => {
188
+ const { writeFileSync } = await import('fs');
189
+ writeFileSync(
190
+ join(tempDir, 'test.md'),
191
+ '---\nid: "test"\ncreated_at: "2024-03-15T10:30:00Z"\nupdated_at: "2024-03-15T10:30:00Z"\ntags: []\ncategory: "general"\nimportance: 3\n---\n\n# Test'
192
+ );
193
+ writeFileSync(join(tempDir, 'test.txt'), 'not markdown');
194
+
195
+ const files = await storage.list();
196
+ expect(files).toHaveLength(1);
197
+ expect(files[0].filename).toBe('test.md');
198
+ });
199
+ });
200
+
201
+ describe('findById', () => {
202
+ it('should find file by memory ID', async () => {
203
+ const testContent = `---
204
+ id: "550e8400-e29b-41d4-a716-446655440000"
205
+ created_at: "2024-03-15T10:30:00Z"
206
+ updated_at: "2024-03-15T10:30:00Z"
207
+ tags: []
208
+ category: "general"
209
+ importance: 3
210
+ ---
211
+
212
+ # Test
213
+ `;
214
+ const { writeFileSync } = await import('fs');
215
+ writeFileSync(join(tempDir, 'test.md'), testContent);
216
+
217
+ const filePath = await storage.findById('550e8400-e29b-41d4-a716-446655440000');
218
+ expect(filePath).toContain('test.md');
219
+ });
220
+
221
+ it('should return null when ID not found', async () => {
222
+ const filePath = await storage.findById('550e8400-e29b-41d4-a716-446655440000');
223
+ expect(filePath).toBeNull();
224
+ });
225
+ });
226
+ });