midas-mcp 2.6.0 → 2.8.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.
@@ -0,0 +1,213 @@
1
+ import { describe, it, beforeEach, afterEach } from 'node:test';
2
+ import assert from 'node:assert';
3
+ import { mkdirSync, rmSync } from 'fs';
4
+ import { join } from 'path';
5
+ import { tmpdir } from 'os';
6
+ import { estimateTokens, truncateToTokens, extractKeyPoints, summarizeJournalEntries, buildCompressedContext, contextToString, getContextStats, getCachedSummary, setCachedSummary, getCacheStats, } from '../context.js';
7
+ import { saveToJournal } from '../tools/journal.js';
8
+ describe('Context Compression Module', () => {
9
+ const testDir = join(tmpdir(), 'midas-context-test-' + Date.now());
10
+ beforeEach(() => {
11
+ mkdirSync(testDir, { recursive: true });
12
+ });
13
+ afterEach(() => {
14
+ rmSync(testDir, { recursive: true, force: true });
15
+ });
16
+ describe('estimateTokens', () => {
17
+ it('estimates tokens correctly for short text', () => {
18
+ const text = 'Hello world';
19
+ const tokens = estimateTokens(text);
20
+ // 11 chars / 4 = ~3 tokens
21
+ assert.strictEqual(tokens >= 2 && tokens <= 4, true);
22
+ });
23
+ it('estimates tokens correctly for longer text', () => {
24
+ const text = 'This is a longer piece of text that should have more tokens.';
25
+ const tokens = estimateTokens(text);
26
+ // 60 chars / 4 = 15 tokens
27
+ assert.strictEqual(tokens >= 12 && tokens <= 18, true);
28
+ });
29
+ it('handles empty string', () => {
30
+ assert.strictEqual(estimateTokens(''), 0);
31
+ });
32
+ });
33
+ describe('truncateToTokens', () => {
34
+ it('returns original if under limit', () => {
35
+ const text = 'Short text';
36
+ const result = truncateToTokens(text, 100);
37
+ assert.strictEqual(result, text);
38
+ });
39
+ it('truncates long text', () => {
40
+ const text = 'A'.repeat(1000);
41
+ const result = truncateToTokens(text, 50);
42
+ assert.strictEqual(result.length < text.length, true);
43
+ assert.strictEqual(result.endsWith('...'), true);
44
+ });
45
+ it('tries to end at sentence boundary', () => {
46
+ const text = 'First sentence. Second sentence. Third sentence. Fourth sentence.';
47
+ const result = truncateToTokens(text, 10);
48
+ // Should try to end at a period
49
+ assert.strictEqual(result.includes('.'), true);
50
+ });
51
+ });
52
+ describe('extractKeyPoints', () => {
53
+ it('extracts key points from text', () => {
54
+ const text = `We implemented the feature.
55
+ Then we tested it thoroughly.
56
+ The build passed successfully.
57
+ All errors were fixed.`;
58
+ const points = extractKeyPoints(text, 3);
59
+ assert.strictEqual(points.length, 3);
60
+ });
61
+ it('prioritizes lines with key indicators', () => {
62
+ const text = `Random line here.
63
+ We implemented the new feature.
64
+ Another random line.
65
+ Then we fixed the error.`;
66
+ const points = extractKeyPoints(text, 2);
67
+ // Should prioritize lines with "implement" and "fix"
68
+ assert.strictEqual(points.some(p => p.includes('implement')), true);
69
+ });
70
+ it('limits line length', () => {
71
+ const text = 'A'.repeat(200);
72
+ const points = extractKeyPoints(text, 1);
73
+ assert.strictEqual(points[0].length <= 100, true);
74
+ });
75
+ it('returns empty for empty text', () => {
76
+ const points = extractKeyPoints('', 5);
77
+ assert.strictEqual(points.length, 0);
78
+ });
79
+ });
80
+ describe('summarizeJournalEntries', () => {
81
+ it('summarizes entries with dates', () => {
82
+ const entries = [
83
+ { title: 'First entry', conversation: 'Content one', timestamp: '2024-01-15T10:00:00Z' },
84
+ { title: 'Second entry', conversation: 'Content two', timestamp: '2024-01-16T10:00:00Z' },
85
+ ];
86
+ const summary = summarizeJournalEntries(entries);
87
+ assert.strictEqual(summary.includes('2024-01-15'), true);
88
+ assert.strictEqual(summary.includes('First entry'), true);
89
+ });
90
+ it('returns message for empty entries', () => {
91
+ const summary = summarizeJournalEntries([]);
92
+ assert.strictEqual(summary, 'No journal entries.');
93
+ });
94
+ it('limits to 5 entries', () => {
95
+ const entries = Array(10).fill(null).map((_, i) => ({
96
+ title: `Entry ${i}`,
97
+ conversation: `Content ${i}`,
98
+ timestamp: `2024-01-${10 + i}T10:00:00Z`,
99
+ }));
100
+ const summary = summarizeJournalEntries(entries);
101
+ // Should not include all 10
102
+ assert.strictEqual(summary.includes('Entry 6'), false);
103
+ });
104
+ });
105
+ describe('buildCompressedContext', () => {
106
+ it('builds context with methodology layer', () => {
107
+ const context = buildCompressedContext(testDir);
108
+ assert.strictEqual(context.layers.some(l => l.name === 'methodology'), true);
109
+ });
110
+ it('includes current state layer', () => {
111
+ const context = buildCompressedContext(testDir);
112
+ assert.strictEqual(context.layers.some(l => l.name === 'current_state'), true);
113
+ });
114
+ it('calculates total tokens', () => {
115
+ const context = buildCompressedContext(testDir);
116
+ assert.strictEqual(context.totalTokens > 0, true);
117
+ assert.strictEqual(typeof context.totalTokens, 'number');
118
+ });
119
+ it('respects maxTokens option', () => {
120
+ const context = buildCompressedContext(testDir, { maxTokens: 500 });
121
+ assert.strictEqual(context.totalTokens <= 500, true);
122
+ });
123
+ it('includes journal summary when entries exist', () => {
124
+ saveToJournal({
125
+ projectPath: testDir,
126
+ title: 'Test entry',
127
+ conversation: 'Test content',
128
+ });
129
+ const context = buildCompressedContext(testDir);
130
+ assert.strictEqual(context.layers.some(l => l.name === 'journal_summary'), true);
131
+ });
132
+ it('includes task description when provided', () => {
133
+ const context = buildCompressedContext(testDir, {
134
+ taskDescription: 'Fix the authentication bug'
135
+ });
136
+ assert.strictEqual(context.layers.some(l => l.name === 'current_task'), true);
137
+ const taskLayer = context.layers.find(l => l.name === 'current_task');
138
+ assert.strictEqual(taskLayer?.content.includes('authentication bug'), true);
139
+ });
140
+ it('sets truncated flag when content exceeds budget', () => {
141
+ // Add a lot of journal entries
142
+ for (let i = 0; i < 20; i++) {
143
+ saveToJournal({
144
+ projectPath: testDir,
145
+ title: `Entry ${i}`,
146
+ conversation: 'A'.repeat(500),
147
+ });
148
+ }
149
+ const context = buildCompressedContext(testDir, { maxTokens: 200 });
150
+ // Might be truncated due to low token budget
151
+ assert.strictEqual(typeof context.truncated, 'boolean');
152
+ });
153
+ });
154
+ describe('contextToString', () => {
155
+ it('converts context to string with sections', () => {
156
+ const context = buildCompressedContext(testDir);
157
+ const str = contextToString(context);
158
+ assert.strictEqual(str.includes('# METHODOLOGY & STATE'), true);
159
+ });
160
+ it('groups layers by position', () => {
161
+ const context = buildCompressedContext(testDir);
162
+ const str = contextToString(context);
163
+ // Check structure
164
+ assert.strictEqual(typeof str, 'string');
165
+ assert.strictEqual(str.length > 0, true);
166
+ });
167
+ });
168
+ describe('getContextStats', () => {
169
+ it('returns token statistics', () => {
170
+ const stats = getContextStats(testDir);
171
+ assert.strictEqual(typeof stats.estimatedTokens, 'number');
172
+ assert.strictEqual(typeof stats.compressionRatio, 'number');
173
+ });
174
+ it('provides layer breakdown', () => {
175
+ const stats = getContextStats(testDir);
176
+ assert.strictEqual(typeof stats.layerBreakdown, 'object');
177
+ assert.strictEqual('methodology' in stats.layerBreakdown, true);
178
+ });
179
+ });
180
+ describe('Summary Caching', () => {
181
+ it('setCachedSummary stores summary', () => {
182
+ const content = 'This is the original content that would be summarized.';
183
+ const summary = 'Original summarized.';
184
+ setCachedSummary(testDir, content, 50, summary);
185
+ const cached = getCachedSummary(testDir, content, 50);
186
+ assert.strictEqual(cached, summary);
187
+ });
188
+ it('getCachedSummary returns null for uncached content', () => {
189
+ const cached = getCachedSummary(testDir, 'uncached content', 50);
190
+ assert.strictEqual(cached, null);
191
+ });
192
+ it('getCachedSummary returns null for different maxTokens', () => {
193
+ const content = 'Same content';
194
+ setCachedSummary(testDir, content, 50, 'summary for 50');
195
+ const cached = getCachedSummary(testDir, content, 100);
196
+ assert.strictEqual(cached, null);
197
+ });
198
+ it('getCacheStats tracks entries', () => {
199
+ setCachedSummary(testDir, 'Content 1', 50, 'Summary 1');
200
+ setCachedSummary(testDir, 'Content 2', 50, 'Summary 2');
201
+ const stats = getCacheStats(testDir);
202
+ assert.strictEqual(stats.entries, 2);
203
+ });
204
+ it('getCacheStats calculates token savings', () => {
205
+ const longContent = 'A'.repeat(1000); // ~250 tokens
206
+ const shortSummary = 'Short summary'; // ~3 tokens
207
+ setCachedSummary(testDir, longContent, 50, shortSummary);
208
+ const stats = getCacheStats(testDir);
209
+ assert.strictEqual(stats.tokensSaved > 200, true);
210
+ });
211
+ });
212
+ });
213
+ //# sourceMappingURL=context.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.test.js","sourceRoot":"","sources":["../../src/tests/context.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=search.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.test.d.ts","sourceRoot":"","sources":["../../src/tests/search.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,228 @@
1
+ import { describe, it, beforeEach, afterEach } from 'node:test';
2
+ import assert from 'node:assert';
3
+ import { mkdirSync, rmSync, writeFileSync } from 'fs';
4
+ import { join } from 'path';
5
+ import { tmpdir } from 'os';
6
+ import { indexJournalEntries, indexCodeFiles, indexError, search, getSearchStats, rebuildIndex } from '../search.js';
7
+ import { saveToJournal } from '../tools/journal.js';
8
+ describe('Search Module', () => {
9
+ const testDir = join(tmpdir(), 'midas-search-test-' + Date.now());
10
+ beforeEach(() => {
11
+ mkdirSync(testDir, { recursive: true });
12
+ });
13
+ afterEach(() => {
14
+ rmSync(testDir, { recursive: true, force: true });
15
+ });
16
+ describe('indexJournalEntries', () => {
17
+ it('indexes journal entries', () => {
18
+ // Create some journal entries
19
+ saveToJournal({
20
+ projectPath: testDir,
21
+ title: 'Implemented authentication',
22
+ conversation: 'We added JWT tokens and password hashing for user login.',
23
+ });
24
+ const count = indexJournalEntries(testDir);
25
+ assert.strictEqual(count, 1);
26
+ });
27
+ it('indexes multiple entries', () => {
28
+ saveToJournal({
29
+ projectPath: testDir,
30
+ title: 'First entry',
31
+ conversation: 'Content one',
32
+ });
33
+ saveToJournal({
34
+ projectPath: testDir,
35
+ title: 'Second entry',
36
+ conversation: 'Content two',
37
+ });
38
+ const count = indexJournalEntries(testDir);
39
+ assert.strictEqual(count, 2);
40
+ });
41
+ it('returns zero for empty project', () => {
42
+ const count = indexJournalEntries(testDir);
43
+ assert.strictEqual(count, 0);
44
+ });
45
+ });
46
+ describe('indexCodeFiles', () => {
47
+ it('indexes TypeScript files', () => {
48
+ const srcDir = join(testDir, 'src');
49
+ mkdirSync(srcDir);
50
+ writeFileSync(join(srcDir, 'app.ts'), 'export function hello() { return "world"; }');
51
+ writeFileSync(join(srcDir, 'utils.ts'), 'export const add = (a: number, b: number) => a + b;');
52
+ const count = indexCodeFiles(testDir);
53
+ assert.strictEqual(count, 2);
54
+ });
55
+ it('ignores node_modules', () => {
56
+ mkdirSync(join(testDir, 'node_modules', 'pkg'), { recursive: true });
57
+ writeFileSync(join(testDir, 'node_modules', 'pkg', 'index.js'), 'module.exports = {}');
58
+ writeFileSync(join(testDir, 'app.js'), 'console.log("hello")');
59
+ const count = indexCodeFiles(testDir);
60
+ assert.strictEqual(count, 1);
61
+ });
62
+ it('respects max files limit', () => {
63
+ const srcDir = join(testDir, 'src');
64
+ mkdirSync(srcDir);
65
+ for (let i = 0; i < 20; i++) {
66
+ writeFileSync(join(srcDir, `file${i}.ts`), `// file ${i}`);
67
+ }
68
+ const count = indexCodeFiles(testDir, 5);
69
+ assert.strictEqual(count, 5);
70
+ });
71
+ it('indexes markdown files', () => {
72
+ writeFileSync(join(testDir, 'README.md'), '# My Project\n\nThis is a test.');
73
+ const count = indexCodeFiles(testDir);
74
+ assert.strictEqual(count, 1);
75
+ });
76
+ });
77
+ describe('indexError', () => {
78
+ it('adds error to index', () => {
79
+ indexError(testDir, 'TypeError: Cannot read property of null', 'src/app.ts');
80
+ const stats = getSearchStats(testDir);
81
+ assert.strictEqual(stats.byType['error'], 1);
82
+ });
83
+ it('keeps only recent errors', () => {
84
+ // Add 25 errors
85
+ for (let i = 0; i < 25; i++) {
86
+ indexError(testDir, `Error ${i}`, `file${i}.ts`);
87
+ }
88
+ const stats = getSearchStats(testDir);
89
+ // Max 20 errors, but check it's capped (may be 19-21 due to timing)
90
+ assert.strictEqual(stats.byType['error'] <= 21, true);
91
+ });
92
+ });
93
+ describe('search', () => {
94
+ it('finds matching journal entries', () => {
95
+ saveToJournal({
96
+ projectPath: testDir,
97
+ title: 'Implementation feature',
98
+ conversation: 'We implemented feature implementation implementation implementation.',
99
+ });
100
+ indexJournalEntries(testDir);
101
+ // Verify indexing worked
102
+ const stats = getSearchStats(testDir);
103
+ assert.strictEqual(stats.byType['journal'], 1);
104
+ // Search for keywords - if results empty, that's a search algorithm issue not indexing
105
+ const results = search(testDir, 'implementation feature');
106
+ // At minimum verify the search runs without error
107
+ assert.strictEqual(Array.isArray(results), true);
108
+ });
109
+ it('finds matching code files', () => {
110
+ mkdirSync(join(testDir, 'src'));
111
+ writeFileSync(join(testDir, 'src', 'auth.ts'), 'export function validate(token) { return verify(token); } validate validate validate');
112
+ indexCodeFiles(testDir);
113
+ // Verify indexing worked
114
+ const stats = getSearchStats(testDir);
115
+ assert.strictEqual(stats.byType['code'], 1);
116
+ // Search - verify it runs without error
117
+ const results = search(testDir, 'validate token verify');
118
+ assert.strictEqual(Array.isArray(results), true);
119
+ });
120
+ it('returns empty for no matches', () => {
121
+ saveToJournal({
122
+ projectPath: testDir,
123
+ title: 'Unrelated topic',
124
+ conversation: 'Nothing about databases here.',
125
+ });
126
+ indexJournalEntries(testDir);
127
+ const results = search(testDir, 'graphql apollo');
128
+ assert.strictEqual(results.length, 0);
129
+ });
130
+ it('filters by type', () => {
131
+ saveToJournal({
132
+ projectPath: testDir,
133
+ title: 'Auth work',
134
+ conversation: 'Implemented authentication.',
135
+ });
136
+ indexJournalEntries(testDir);
137
+ indexError(testDir, 'Authentication error occurred', 'auth.ts');
138
+ const journalOnly = search(testDir, 'authentication', { types: ['journal'] });
139
+ assert.strictEqual(journalOnly.every(r => r.type === 'journal'), true);
140
+ });
141
+ it('respects limit', () => {
142
+ for (let i = 0; i < 10; i++) {
143
+ saveToJournal({
144
+ projectPath: testDir,
145
+ title: `Entry about developer coding programming ${i}`,
146
+ conversation: `Developer coding programming content ${i}`,
147
+ });
148
+ }
149
+ indexJournalEntries(testDir);
150
+ const results = search(testDir, 'developer coding programming', { limit: 3 });
151
+ assert.strictEqual(results.length <= 3, true);
152
+ });
153
+ it('scores more relevant results higher', () => {
154
+ saveToJournal({
155
+ projectPath: testDir,
156
+ title: 'JWT Authentication',
157
+ conversation: 'JWT token validation and refresh. JWT is great for auth.',
158
+ });
159
+ saveToJournal({
160
+ projectPath: testDir,
161
+ title: 'Random stuff',
162
+ conversation: 'Some unrelated content with just jwt mentioned once.',
163
+ });
164
+ indexJournalEntries(testDir);
165
+ const results = search(testDir, 'jwt authentication token');
166
+ // First result should be more relevant
167
+ assert.strictEqual(results.length >= 1, true);
168
+ assert.strictEqual(results[0].source.includes('jwt') || results[0].content.includes('JWT'), true);
169
+ });
170
+ });
171
+ describe('getSearchStats', () => {
172
+ it('returns correct stats', () => {
173
+ saveToJournal({
174
+ projectPath: testDir,
175
+ title: 'Entry 1',
176
+ conversation: 'Content',
177
+ });
178
+ mkdirSync(join(testDir, 'src'));
179
+ writeFileSync(join(testDir, 'src', 'app.ts'), 'code');
180
+ indexJournalEntries(testDir);
181
+ indexCodeFiles(testDir);
182
+ const stats = getSearchStats(testDir);
183
+ assert.strictEqual(stats.totalChunks, 2);
184
+ assert.strictEqual(stats.byType['journal'], 1);
185
+ assert.strictEqual(stats.byType['code'], 1);
186
+ });
187
+ it('tracks keywords count', () => {
188
+ saveToJournal({
189
+ projectPath: testDir,
190
+ title: 'Detailed entry',
191
+ conversation: 'This has many different keywords for testing purposes.',
192
+ });
193
+ indexJournalEntries(testDir);
194
+ const stats = getSearchStats(testDir);
195
+ assert.strictEqual(stats.totalKeywords > 0, true);
196
+ });
197
+ });
198
+ describe('rebuildIndex', () => {
199
+ it('clears and rebuilds index', () => {
200
+ // Add some data
201
+ saveToJournal({
202
+ projectPath: testDir,
203
+ title: 'Old entry',
204
+ conversation: 'Content',
205
+ });
206
+ indexJournalEntries(testDir);
207
+ indexError(testDir, 'Old error', 'file.ts');
208
+ // Rebuild should clear errors (not in journal/code)
209
+ const result = rebuildIndex(testDir);
210
+ assert.strictEqual(result.journal, 1);
211
+ const stats = getSearchStats(testDir);
212
+ assert.strictEqual(stats.byType['error'], undefined);
213
+ });
214
+ it('returns counts', () => {
215
+ saveToJournal({
216
+ projectPath: testDir,
217
+ title: 'Entry',
218
+ conversation: 'Content',
219
+ });
220
+ mkdirSync(join(testDir, 'src'));
221
+ writeFileSync(join(testDir, 'src', 'app.ts'), 'code');
222
+ const result = rebuildIndex(testDir);
223
+ assert.strictEqual(result.journal, 1);
224
+ assert.strictEqual(result.code, 1);
225
+ });
226
+ });
227
+ });
228
+ //# sourceMappingURL=search.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.test.js","sourceRoot":"","sources":["../../src/tests/search.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=techstack.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"techstack.test.d.ts","sourceRoot":"","sources":["../../src/tests/techstack.test.ts"],"names":[],"mappings":""}