@synth-coder/memhub 0.2.3 → 0.2.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.
Files changed (143) hide show
  1. package/.eslintrc.cjs +45 -45
  2. package/.factory/commands/opsx-apply.md +150 -150
  3. package/.factory/commands/opsx-archive.md +155 -155
  4. package/.factory/commands/opsx-explore.md +171 -171
  5. package/.factory/commands/opsx-propose.md +104 -104
  6. package/.factory/skills/openspec-apply-change/SKILL.md +156 -156
  7. package/.factory/skills/openspec-archive-change/SKILL.md +114 -114
  8. package/.factory/skills/openspec-explore/SKILL.md +288 -288
  9. package/.factory/skills/openspec-propose/SKILL.md +110 -110
  10. package/.github/workflows/ci.yml +110 -74
  11. package/.github/workflows/release.yml +67 -0
  12. package/.iflow/commands/opsx-apply.md +152 -152
  13. package/.iflow/commands/opsx-archive.md +157 -157
  14. package/.iflow/commands/opsx-explore.md +173 -173
  15. package/.iflow/commands/opsx-propose.md +106 -106
  16. package/.iflow/skills/openspec-apply-change/SKILL.md +156 -156
  17. package/.iflow/skills/openspec-archive-change/SKILL.md +114 -114
  18. package/.iflow/skills/openspec-explore/SKILL.md +288 -288
  19. package/.iflow/skills/openspec-propose/SKILL.md +110 -110
  20. package/.prettierrc +11 -11
  21. package/AGENTS.md +167 -169
  22. package/README.md +276 -195
  23. package/README.zh-CN.md +245 -193
  24. package/dist/src/cli/agents/claude-code.d.ts +5 -0
  25. package/dist/src/cli/agents/claude-code.d.ts.map +1 -0
  26. package/dist/src/cli/agents/claude-code.js +14 -0
  27. package/dist/src/cli/agents/claude-code.js.map +1 -0
  28. package/dist/src/cli/agents/cline.d.ts +5 -0
  29. package/dist/src/cli/agents/cline.d.ts.map +1 -0
  30. package/dist/src/cli/agents/cline.js +14 -0
  31. package/dist/src/cli/agents/cline.js.map +1 -0
  32. package/dist/src/cli/agents/codex.d.ts +5 -0
  33. package/dist/src/cli/agents/codex.d.ts.map +1 -0
  34. package/dist/src/cli/agents/codex.js +14 -0
  35. package/dist/src/cli/agents/codex.js.map +1 -0
  36. package/dist/src/cli/agents/cursor.d.ts +5 -0
  37. package/dist/src/cli/agents/cursor.d.ts.map +1 -0
  38. package/dist/src/cli/agents/cursor.js +14 -0
  39. package/dist/src/cli/agents/cursor.js.map +1 -0
  40. package/dist/src/cli/agents/factory-droid.d.ts +5 -0
  41. package/dist/src/cli/agents/factory-droid.d.ts.map +1 -0
  42. package/dist/src/cli/agents/factory-droid.js +14 -0
  43. package/dist/src/cli/agents/factory-droid.js.map +1 -0
  44. package/dist/src/cli/agents/gemini-cli.d.ts +5 -0
  45. package/dist/src/cli/agents/gemini-cli.d.ts.map +1 -0
  46. package/dist/src/cli/agents/gemini-cli.js +14 -0
  47. package/dist/src/cli/agents/gemini-cli.js.map +1 -0
  48. package/dist/src/cli/agents/index.d.ts +14 -0
  49. package/dist/src/cli/agents/index.d.ts.map +1 -0
  50. package/dist/src/cli/agents/index.js +30 -0
  51. package/dist/src/cli/agents/index.js.map +1 -0
  52. package/dist/src/cli/agents/windsurf.d.ts +5 -0
  53. package/dist/src/cli/agents/windsurf.d.ts.map +1 -0
  54. package/dist/src/cli/agents/windsurf.js +14 -0
  55. package/dist/src/cli/agents/windsurf.js.map +1 -0
  56. package/dist/src/cli/index.d.ts +8 -0
  57. package/dist/src/cli/index.d.ts.map +1 -0
  58. package/dist/src/cli/index.js +168 -0
  59. package/dist/src/cli/index.js.map +1 -0
  60. package/dist/src/cli/init.d.ts +34 -0
  61. package/dist/src/cli/init.d.ts.map +1 -0
  62. package/dist/src/cli/init.js +160 -0
  63. package/dist/src/cli/init.js.map +1 -0
  64. package/dist/src/cli/instructions.d.ts +29 -0
  65. package/dist/src/cli/instructions.d.ts.map +1 -0
  66. package/dist/src/cli/instructions.js +141 -0
  67. package/dist/src/cli/instructions.js.map +1 -0
  68. package/dist/src/cli/types.d.ts +22 -0
  69. package/dist/src/cli/types.d.ts.map +1 -0
  70. package/dist/src/cli/types.js +86 -0
  71. package/dist/src/cli/types.js.map +1 -0
  72. package/dist/src/contracts/mcp.js +34 -34
  73. package/dist/src/contracts/schemas.js.map +1 -1
  74. package/dist/src/server/mcp-server.d.ts.map +1 -1
  75. package/dist/src/server/mcp-server.js +7 -14
  76. package/dist/src/server/mcp-server.js.map +1 -1
  77. package/dist/src/services/embedding-service.d.ts.map +1 -1
  78. package/dist/src/services/embedding-service.js +1 -1
  79. package/dist/src/services/embedding-service.js.map +1 -1
  80. package/dist/src/services/memory-service.d.ts.map +1 -1
  81. package/dist/src/services/memory-service.js.map +1 -1
  82. package/dist/src/storage/markdown-storage.d.ts.map +1 -1
  83. package/dist/src/storage/markdown-storage.js +1 -1
  84. package/dist/src/storage/markdown-storage.js.map +1 -1
  85. package/dist/src/storage/vector-index.d.ts.map +1 -1
  86. package/dist/src/storage/vector-index.js +4 -5
  87. package/dist/src/storage/vector-index.js.map +1 -1
  88. package/docs/README.md +21 -0
  89. package/docs/mcp-tools.md +136 -0
  90. package/docs/user-guide.md +182 -0
  91. package/package.json +61 -59
  92. package/src/cli/agents/claude-code.ts +14 -0
  93. package/src/cli/agents/cline.ts +14 -0
  94. package/src/cli/agents/codex.ts +14 -0
  95. package/src/cli/agents/cursor.ts +14 -0
  96. package/src/cli/agents/factory-droid.ts +14 -0
  97. package/src/cli/agents/gemini-cli.ts +14 -0
  98. package/src/cli/agents/index.ts +36 -0
  99. package/src/cli/agents/windsurf.ts +14 -0
  100. package/src/cli/index.ts +192 -0
  101. package/src/cli/init.ts +218 -0
  102. package/src/cli/instructions.ts +156 -0
  103. package/src/cli/types.ts +112 -0
  104. package/src/contracts/index.ts +12 -12
  105. package/src/contracts/mcp.ts +223 -223
  106. package/src/contracts/schemas.ts +307 -307
  107. package/src/contracts/types.ts +410 -410
  108. package/src/index.ts +8 -8
  109. package/src/server/index.ts +5 -5
  110. package/src/server/mcp-server.ts +169 -186
  111. package/src/services/embedding-service.ts +114 -114
  112. package/src/services/index.ts +5 -5
  113. package/src/services/memory-service.ts +656 -663
  114. package/src/storage/frontmatter-parser.ts +243 -243
  115. package/src/storage/index.ts +6 -6
  116. package/src/storage/markdown-storage.ts +228 -236
  117. package/src/storage/vector-index.ts +159 -160
  118. package/src/utils/index.ts +5 -5
  119. package/src/utils/slugify.ts +63 -63
  120. package/test/cli/init.test.ts +380 -0
  121. package/test/contracts/schemas.test.ts +313 -313
  122. package/test/contracts/types.test.ts +21 -21
  123. package/test/frontmatter-parser-more.test.ts +94 -94
  124. package/test/server/mcp-server.test.ts +211 -210
  125. package/test/services/memory-service-edge.test.ts +248 -248
  126. package/test/services/memory-service.test.ts +291 -279
  127. package/test/storage/frontmatter-parser.test.ts +223 -223
  128. package/test/storage/markdown-storage.test.ts +226 -217
  129. package/test/storage/storage-edge.test.ts +238 -238
  130. package/test/storage/vector-index.test.ts +149 -153
  131. package/test/utils/slugify-edge.test.ts +94 -94
  132. package/test/utils/slugify.test.ts +72 -68
  133. package/tsconfig.json +25 -25
  134. package/tsconfig.test.json +8 -8
  135. package/vitest.config.ts +29 -29
  136. package/docs/architecture-diagrams.md +0 -368
  137. package/docs/architecture.md +0 -381
  138. package/docs/contracts.md +0 -190
  139. package/docs/prompt-template.md +0 -33
  140. package/docs/proposals/mcp-typescript-sdk-refactor.md +0 -568
  141. package/docs/proposals/proposal-close-gates.md +0 -58
  142. package/docs/tool-calling-policy.md +0 -101
  143. package/docs/vector-search.md +0 -306
@@ -1,223 +1,223 @@
1
- /**
2
- * FrontMatter Parser Tests
3
- * Tests for the FrontMatter parser
4
- */
5
-
6
- import { describe, it, expect } from 'vitest';
7
- import {
8
- parseFrontMatter,
9
- stringifyFrontMatter,
10
- memoryToFrontMatter,
11
- frontMatterToMemory,
12
- FrontMatterError,
13
- } from '../../src/storage/frontmatter-parser.js';
14
- import type { Memory, MemoryFrontMatter } from '../../src/contracts/types.js';
15
-
16
- describe('parseFrontMatter', () => {
17
- it('should parse valid front matter and content', () => {
18
- const markdown = `---
19
- id: "550e8400-e29b-41d4-a716-446655440000"
20
- created_at: "2024-03-15T10:30:00Z"
21
- updated_at: "2024-03-15T14:20:00Z"
22
- tags:
23
- - project
24
- - meeting
25
- category: "work"
26
- importance: 4
27
- ---
28
-
29
- # Project Meeting
30
-
31
- This is the meeting content.
32
-
33
- ## Action Items
34
-
35
- - Item 1
36
- - Item 2
37
- `;
38
-
39
- const result = parseFrontMatter(markdown);
40
- expect(result.frontMatter.id).toBe('550e8400-e29b-41d4-a716-446655440000');
41
- expect(result.frontMatter.category).toBe('work');
42
- expect(result.frontMatter.importance).toBe(4);
43
- expect(result.title).toBe('Project Meeting');
44
- expect(result.content).toContain('Action Items');
45
- });
46
-
47
- it('should parse front matter with empty tags', () => {
48
- const markdown = `---
49
- id: "550e8400-e29b-41d4-a716-446655440000"
50
- created_at: "2024-03-15T10:30:00Z"
51
- updated_at: "2024-03-15T10:30:00Z"
52
- tags: []
53
- category: "general"
54
- importance: 3
55
- ---
56
-
57
- # Empty Tags Test
58
-
59
- Content here.
60
- `;
61
-
62
- const result = parseFrontMatter(markdown);
63
- expect(result.frontMatter.tags).toEqual([]);
64
- });
65
-
66
- it('should throw error for missing front matter', () => {
67
- const markdown = `# No Front Matter
68
-
69
- This markdown has no front matter.
70
- `;
71
-
72
- expect(() => parseFrontMatter(markdown)).toThrow(FrontMatterError);
73
- expect(() => parseFrontMatter(markdown)).toThrow('Missing front matter delimiter');
74
- });
75
-
76
- it('should throw error for invalid YAML', () => {
77
- const markdown = `---
78
- id: "550e8400-e29b-41d4-a716-446655440000"
79
- created_at: [invalid yaml
80
- ---
81
-
82
- # Title
83
-
84
- Content.
85
- `;
86
-
87
- expect(() => parseFrontMatter(markdown)).toThrow(FrontMatterError);
88
- });
89
-
90
- it('should throw error for missing required fields', () => {
91
- const markdown = `---
92
- id: "550e8400-e29b-41d4-a716-446655440000"
93
- ---
94
-
95
- # Title
96
-
97
- Content.
98
- `;
99
-
100
- expect(() => parseFrontMatter(markdown)).toThrow(FrontMatterError);
101
- expect(() => parseFrontMatter(markdown)).toThrow('Missing required fields');
102
- });
103
-
104
- it('should handle multiline content correctly', () => {
105
- const markdown = `---
106
- id: "550e8400-e29b-41d4-a716-446655440000"
107
- created_at: "2024-03-15T10:30:00Z"
108
- updated_at: "2024-03-15T10:30:00Z"
109
- tags: []
110
- category: "general"
111
- importance: 3
112
- ---
113
-
114
- # Title
115
-
116
- Line 1
117
- Line 2
118
-
119
- Line 3 after blank
120
- `;
121
-
122
- const result = parseFrontMatter(markdown);
123
- expect(result.content).toContain('Line 1');
124
- expect(result.content).toContain('Line 3 after blank');
125
- });
126
- });
127
-
128
- describe('stringifyFrontMatter', () => {
129
- const frontMatter: MemoryFrontMatter = {
130
- id: '550e8400-e29b-41d4-a716-446655440000',
131
- created_at: '2024-03-15T10:30:00Z',
132
- updated_at: '2024-03-15T14:20:00Z',
133
- tags: ['project', 'meeting'],
134
- category: 'work',
135
- importance: 4,
136
- };
137
-
138
- it('should stringify front matter and content', () => {
139
- const result = stringifyFrontMatter(frontMatter, 'Title', 'Content here');
140
- expect(result).toContain('---');
141
- expect(result).toContain('id: "550e8400-e29b-41d4-a716-446655440000"');
142
- expect(result).toContain('# Title');
143
- expect(result).toContain('Content here');
144
- });
145
-
146
- it('should format tags as YAML array', () => {
147
- const result = stringifyFrontMatter(frontMatter, 'Title', 'Content');
148
- expect(result).toContain('tags:');
149
- expect(result).toContain('project');
150
- expect(result).toContain('meeting');
151
- });
152
-
153
- it('should use LF line endings', () => {
154
- const result = stringifyFrontMatter(frontMatter, 'Title', 'Content');
155
- expect(result).not.toContain('\r\n');
156
- expect(result).toContain('\n');
157
- });
158
-
159
- it('should add blank line between front matter and content', () => {
160
- const result = stringifyFrontMatter(frontMatter, 'Title', 'Content');
161
- expect(result).toMatch(/---\n\n# Title/);
162
- });
163
-
164
- it('should handle empty tags', () => {
165
- const fmWithEmptyTags: MemoryFrontMatter = { ...frontMatter, tags: [] };
166
- const result = stringifyFrontMatter(fmWithEmptyTags, 'Title', 'Content');
167
- expect(result).toContain('tags: []');
168
- });
169
-
170
- it('should handle multiline content', () => {
171
- const content = 'Line 1\n\nLine 2\n\nLine 3';
172
- const result = stringifyFrontMatter(frontMatter, 'Title', content);
173
- expect(result).toContain('Line 1');
174
- expect(result).toContain('Line 2');
175
- expect(result).toContain('Line 3');
176
- });
177
- });
178
-
179
- describe('memoryToFrontMatter', () => {
180
- it('should convert Memory to MemoryFrontMatter', () => {
181
- const memory: Memory = {
182
- id: '550e8400-e29b-41d4-a716-446655440000',
183
- createdAt: '2024-03-15T10:30:00Z',
184
- updatedAt: '2024-03-15T14:20:00Z',
185
- tags: ['test'],
186
- category: 'work',
187
- importance: 3,
188
- title: 'Test',
189
- content: 'Content',
190
- };
191
-
192
- const result = memoryToFrontMatter(memory);
193
- expect(result.id).toBe(memory.id);
194
- expect(result.created_at).toBe(memory.createdAt);
195
- expect(result.updated_at).toBe(memory.updatedAt);
196
- expect(result.tags).toEqual(memory.tags);
197
- expect(result.category).toBe(memory.category);
198
- expect(result.importance).toBe(memory.importance);
199
- });
200
- });
201
-
202
- describe('frontMatterToMemory', () => {
203
- it('should convert MemoryFrontMatter to Memory', () => {
204
- const fm: MemoryFrontMatter = {
205
- id: '550e8400-e29b-41d4-a716-446655440000',
206
- created_at: '2024-03-15T10:30:00Z',
207
- updated_at: '2024-03-15T14:20:00Z',
208
- tags: ['test'],
209
- category: 'work',
210
- importance: 3,
211
- };
212
-
213
- const result = frontMatterToMemory(fm, 'Title', 'Content');
214
- expect(result.id).toBe(fm.id);
215
- expect(result.createdAt).toBe(fm.created_at);
216
- expect(result.updatedAt).toBe(fm.updated_at);
217
- expect(result.tags).toEqual(fm.tags);
218
- expect(result.category).toBe(fm.category);
219
- expect(result.importance).toBe(fm.importance);
220
- expect(result.title).toBe('Title');
221
- expect(result.content).toBe('Content');
222
- });
223
- });
1
+ /**
2
+ * FrontMatter Parser Tests
3
+ * Tests for the FrontMatter parser
4
+ */
5
+
6
+ import { describe, it, expect } from 'vitest';
7
+ import {
8
+ parseFrontMatter,
9
+ stringifyFrontMatter,
10
+ memoryToFrontMatter,
11
+ frontMatterToMemory,
12
+ FrontMatterError,
13
+ } from '../../src/storage/frontmatter-parser.js';
14
+ import type { Memory, MemoryFrontMatter } from '../../src/contracts/types.js';
15
+
16
+ describe('parseFrontMatter', () => {
17
+ it('should parse valid front matter and content', () => {
18
+ const markdown = `---
19
+ id: "550e8400-e29b-41d4-a716-446655440000"
20
+ created_at: "2024-03-15T10:30:00Z"
21
+ updated_at: "2024-03-15T14:20:00Z"
22
+ tags:
23
+ - project
24
+ - meeting
25
+ category: "work"
26
+ importance: 4
27
+ ---
28
+
29
+ # Project Meeting
30
+
31
+ This is the meeting content.
32
+
33
+ ## Action Items
34
+
35
+ - Item 1
36
+ - Item 2
37
+ `;
38
+
39
+ const result = parseFrontMatter(markdown);
40
+ expect(result.frontMatter.id).toBe('550e8400-e29b-41d4-a716-446655440000');
41
+ expect(result.frontMatter.category).toBe('work');
42
+ expect(result.frontMatter.importance).toBe(4);
43
+ expect(result.title).toBe('Project Meeting');
44
+ expect(result.content).toContain('Action Items');
45
+ });
46
+
47
+ it('should parse front matter with empty tags', () => {
48
+ const markdown = `---
49
+ id: "550e8400-e29b-41d4-a716-446655440000"
50
+ created_at: "2024-03-15T10:30:00Z"
51
+ updated_at: "2024-03-15T10:30:00Z"
52
+ tags: []
53
+ category: "general"
54
+ importance: 3
55
+ ---
56
+
57
+ # Empty Tags Test
58
+
59
+ Content here.
60
+ `;
61
+
62
+ const result = parseFrontMatter(markdown);
63
+ expect(result.frontMatter.tags).toEqual([]);
64
+ });
65
+
66
+ it('should throw error for missing front matter', () => {
67
+ const markdown = `# No Front Matter
68
+
69
+ This markdown has no front matter.
70
+ `;
71
+
72
+ expect(() => parseFrontMatter(markdown)).toThrow(FrontMatterError);
73
+ expect(() => parseFrontMatter(markdown)).toThrow('Missing front matter delimiter');
74
+ });
75
+
76
+ it('should throw error for invalid YAML', () => {
77
+ const markdown = `---
78
+ id: "550e8400-e29b-41d4-a716-446655440000"
79
+ created_at: [invalid yaml
80
+ ---
81
+
82
+ # Title
83
+
84
+ Content.
85
+ `;
86
+
87
+ expect(() => parseFrontMatter(markdown)).toThrow(FrontMatterError);
88
+ });
89
+
90
+ it('should throw error for missing required fields', () => {
91
+ const markdown = `---
92
+ id: "550e8400-e29b-41d4-a716-446655440000"
93
+ ---
94
+
95
+ # Title
96
+
97
+ Content.
98
+ `;
99
+
100
+ expect(() => parseFrontMatter(markdown)).toThrow(FrontMatterError);
101
+ expect(() => parseFrontMatter(markdown)).toThrow('Missing required fields');
102
+ });
103
+
104
+ it('should handle multiline content correctly', () => {
105
+ const markdown = `---
106
+ id: "550e8400-e29b-41d4-a716-446655440000"
107
+ created_at: "2024-03-15T10:30:00Z"
108
+ updated_at: "2024-03-15T10:30:00Z"
109
+ tags: []
110
+ category: "general"
111
+ importance: 3
112
+ ---
113
+
114
+ # Title
115
+
116
+ Line 1
117
+ Line 2
118
+
119
+ Line 3 after blank
120
+ `;
121
+
122
+ const result = parseFrontMatter(markdown);
123
+ expect(result.content).toContain('Line 1');
124
+ expect(result.content).toContain('Line 3 after blank');
125
+ });
126
+ });
127
+
128
+ describe('stringifyFrontMatter', () => {
129
+ const frontMatter: MemoryFrontMatter = {
130
+ id: '550e8400-e29b-41d4-a716-446655440000',
131
+ created_at: '2024-03-15T10:30:00Z',
132
+ updated_at: '2024-03-15T14:20:00Z',
133
+ tags: ['project', 'meeting'],
134
+ category: 'work',
135
+ importance: 4,
136
+ };
137
+
138
+ it('should stringify front matter and content', () => {
139
+ const result = stringifyFrontMatter(frontMatter, 'Title', 'Content here');
140
+ expect(result).toContain('---');
141
+ expect(result).toContain('id: "550e8400-e29b-41d4-a716-446655440000"');
142
+ expect(result).toContain('# Title');
143
+ expect(result).toContain('Content here');
144
+ });
145
+
146
+ it('should format tags as YAML array', () => {
147
+ const result = stringifyFrontMatter(frontMatter, 'Title', 'Content');
148
+ expect(result).toContain('tags:');
149
+ expect(result).toContain('project');
150
+ expect(result).toContain('meeting');
151
+ });
152
+
153
+ it('should use LF line endings', () => {
154
+ const result = stringifyFrontMatter(frontMatter, 'Title', 'Content');
155
+ expect(result).not.toContain('\r\n');
156
+ expect(result).toContain('\n');
157
+ });
158
+
159
+ it('should add blank line between front matter and content', () => {
160
+ const result = stringifyFrontMatter(frontMatter, 'Title', 'Content');
161
+ expect(result).toMatch(/---\n\n# Title/);
162
+ });
163
+
164
+ it('should handle empty tags', () => {
165
+ const fmWithEmptyTags: MemoryFrontMatter = { ...frontMatter, tags: [] };
166
+ const result = stringifyFrontMatter(fmWithEmptyTags, 'Title', 'Content');
167
+ expect(result).toContain('tags: []');
168
+ });
169
+
170
+ it('should handle multiline content', () => {
171
+ const content = 'Line 1\n\nLine 2\n\nLine 3';
172
+ const result = stringifyFrontMatter(frontMatter, 'Title', content);
173
+ expect(result).toContain('Line 1');
174
+ expect(result).toContain('Line 2');
175
+ expect(result).toContain('Line 3');
176
+ });
177
+ });
178
+
179
+ describe('memoryToFrontMatter', () => {
180
+ it('should convert Memory to MemoryFrontMatter', () => {
181
+ const memory: Memory = {
182
+ id: '550e8400-e29b-41d4-a716-446655440000',
183
+ createdAt: '2024-03-15T10:30:00Z',
184
+ updatedAt: '2024-03-15T14:20:00Z',
185
+ tags: ['test'],
186
+ category: 'work',
187
+ importance: 3,
188
+ title: 'Test',
189
+ content: 'Content',
190
+ };
191
+
192
+ const result = memoryToFrontMatter(memory);
193
+ expect(result.id).toBe(memory.id);
194
+ expect(result.created_at).toBe(memory.createdAt);
195
+ expect(result.updated_at).toBe(memory.updatedAt);
196
+ expect(result.tags).toEqual(memory.tags);
197
+ expect(result.category).toBe(memory.category);
198
+ expect(result.importance).toBe(memory.importance);
199
+ });
200
+ });
201
+
202
+ describe('frontMatterToMemory', () => {
203
+ it('should convert MemoryFrontMatter to Memory', () => {
204
+ const fm: MemoryFrontMatter = {
205
+ id: '550e8400-e29b-41d4-a716-446655440000',
206
+ created_at: '2024-03-15T10:30:00Z',
207
+ updated_at: '2024-03-15T14:20:00Z',
208
+ tags: ['test'],
209
+ category: 'work',
210
+ importance: 3,
211
+ };
212
+
213
+ const result = frontMatterToMemory(fm, 'Title', 'Content');
214
+ expect(result.id).toBe(fm.id);
215
+ expect(result.createdAt).toBe(fm.created_at);
216
+ expect(result.updatedAt).toBe(fm.updated_at);
217
+ expect(result.tags).toEqual(fm.tags);
218
+ expect(result.category).toBe(fm.category);
219
+ expect(result.importance).toBe(fm.importance);
220
+ expect(result.title).toBe('Title');
221
+ expect(result.content).toBe('Content');
222
+ });
223
+ });