@smallironman/mcp-memory-keeper 0.12.2-fork1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +542 -0
- package/LICENSE +21 -0
- package/README.md +1281 -0
- package/bin/mcp-memory-keeper +54 -0
- package/dist/__tests__/e2e/issue33-reproduce.test.js +234 -0
- package/dist/__tests__/e2e/server-e2e.test.js +341 -0
- package/dist/__tests__/helpers/database-test-helper.js +160 -0
- package/dist/__tests__/helpers/test-server.js +92 -0
- package/dist/__tests__/integration/advanced-features.test.js +614 -0
- package/dist/__tests__/integration/backward-compatibility.test.js +245 -0
- package/dist/__tests__/integration/batchOperationsE2E.test.js +396 -0
- package/dist/__tests__/integration/batchOperationsHandler.test.js +1230 -0
- package/dist/__tests__/integration/channelManagementHandler.test.js +1291 -0
- package/dist/__tests__/integration/channels.test.js +376 -0
- package/dist/__tests__/integration/checkpoint.test.js +251 -0
- package/dist/__tests__/integration/concurrent-access.test.js +190 -0
- package/dist/__tests__/integration/context-operations.test.js +243 -0
- package/dist/__tests__/integration/contextDiff.test.js +852 -0
- package/dist/__tests__/integration/contextDiffHandler.test.js +976 -0
- package/dist/__tests__/integration/contextExportHandler.test.js +510 -0
- package/dist/__tests__/integration/contextGetPaginationDefaults.test.js +298 -0
- package/dist/__tests__/integration/contextReassignChannelHandler.test.js +908 -0
- package/dist/__tests__/integration/contextRelationshipsHandler.test.js +1151 -0
- package/dist/__tests__/integration/contextSearch.test.js +1054 -0
- package/dist/__tests__/integration/contextSearchHandler.test.js +552 -0
- package/dist/__tests__/integration/contextWatchActual.test.js +165 -0
- package/dist/__tests__/integration/contextWatchHandler.test.js +1500 -0
- package/dist/__tests__/integration/database-initialization.test.js +134 -0
- package/dist/__tests__/integration/enhanced-context-operations.test.js +1082 -0
- package/dist/__tests__/integration/enhancedContextGetHandler.test.js +915 -0
- package/dist/__tests__/integration/enhancedContextTimelineHandler.test.js +716 -0
- package/dist/__tests__/integration/error-cases.test.js +411 -0
- package/dist/__tests__/integration/export-import.test.js +367 -0
- package/dist/__tests__/integration/feature-flags.test.js +542 -0
- package/dist/__tests__/integration/file-operations.test.js +264 -0
- package/dist/__tests__/integration/filterBySessionId.test.js +251 -0
- package/dist/__tests__/integration/git-integration.test.js +241 -0
- package/dist/__tests__/integration/index-tools.test.js +496 -0
- package/dist/__tests__/integration/issue11-actual-bug-demo.test.js +304 -0
- package/dist/__tests__/integration/issue11-search-filters-bug.test.js +561 -0
- package/dist/__tests__/integration/issue12-checkpoint-restore-behavior.test.js +621 -0
- package/dist/__tests__/integration/issue13-key-validation.test.js +433 -0
- package/dist/__tests__/integration/issue24-final-fix.test.js +241 -0
- package/dist/__tests__/integration/issue24-fix-validation.test.js +158 -0
- package/dist/__tests__/integration/issue24-reproduce.test.js +225 -0
- package/dist/__tests__/integration/issue24-token-limit.test.js +199 -0
- package/dist/__tests__/integration/issue33-array-items-schema.test.js +165 -0
- package/dist/__tests__/integration/knowledge-graph.test.js +338 -0
- package/dist/__tests__/integration/migrations.test.js +528 -0
- package/dist/__tests__/integration/multi-agent.test.js +546 -0
- package/dist/__tests__/integration/pagination-critical-fix.test.js +296 -0
- package/dist/__tests__/integration/paginationDefaultsHandler.test.js +600 -0
- package/dist/__tests__/integration/project-directory.test.js +291 -0
- package/dist/__tests__/integration/resource-cleanup.test.js +149 -0
- package/dist/__tests__/integration/retention.test.js +513 -0
- package/dist/__tests__/integration/search.test.js +333 -0
- package/dist/__tests__/integration/semantic-search.test.js +266 -0
- package/dist/__tests__/integration/server-initialization.test.js +305 -0
- package/dist/__tests__/integration/session-management.test.js +219 -0
- package/dist/__tests__/integration/simplified-sharing.test.js +346 -0
- package/dist/__tests__/integration/smart-compaction.test.js +230 -0
- package/dist/__tests__/integration/summarization.test.js +308 -0
- package/dist/__tests__/integration/tokenLimitEnforcement.test.js +134 -0
- package/dist/__tests__/integration/tool-profiles-integration.test.js +150 -0
- package/dist/__tests__/integration/watcher-migration-validation.test.js +544 -0
- package/dist/__tests__/security/input-validation.test.js +115 -0
- package/dist/__tests__/utils/agents.test.js +473 -0
- package/dist/__tests__/utils/database.test.js +177 -0
- package/dist/__tests__/utils/git.test.js +122 -0
- package/dist/__tests__/utils/knowledge-graph.test.js +297 -0
- package/dist/__tests__/utils/migrationHealthCheck.test.js +302 -0
- package/dist/__tests__/utils/project-directory-messages.test.js +192 -0
- package/dist/__tests__/utils/timezone-safe-dates.js +119 -0
- package/dist/__tests__/utils/token-limits.test.js +225 -0
- package/dist/__tests__/utils/tool-profiles.test.js +374 -0
- package/dist/__tests__/utils/validation.test.js +200 -0
- package/dist/__tests__/utils/vector-store.test.js +231 -0
- package/dist/handlers/contextWatchHandlers.js +206 -0
- package/dist/index.js +4425 -0
- package/dist/migrations/003_add_channels.js +174 -0
- package/dist/migrations/004_add_context_watch.js +151 -0
- package/dist/migrations/005_add_context_watch.js +98 -0
- package/dist/migrations/simplify-sharing.js +117 -0
- package/dist/repositories/BaseRepository.js +30 -0
- package/dist/repositories/CheckpointRepository.js +140 -0
- package/dist/repositories/ContextRepository.js +2017 -0
- package/dist/repositories/FileRepository.js +104 -0
- package/dist/repositories/RepositoryManager.js +62 -0
- package/dist/repositories/SessionRepository.js +66 -0
- package/dist/repositories/WatcherRepository.js +252 -0
- package/dist/repositories/index.js +15 -0
- package/dist/test-helpers/database-helper.js +128 -0
- package/dist/types/entities.js +3 -0
- package/dist/utils/agents.js +791 -0
- package/dist/utils/channels.js +150 -0
- package/dist/utils/database.js +780 -0
- package/dist/utils/feature-flags.js +476 -0
- package/dist/utils/git.js +145 -0
- package/dist/utils/knowledge-graph.js +264 -0
- package/dist/utils/migrationHealthCheck.js +373 -0
- package/dist/utils/migrations.js +452 -0
- package/dist/utils/retention.js +460 -0
- package/dist/utils/timestamps.js +112 -0
- package/dist/utils/token-limits.js +350 -0
- package/dist/utils/tool-profiles.js +242 -0
- package/dist/utils/validation.js +296 -0
- package/dist/utils/vector-store.js +247 -0
- package/examples/config.json +31 -0
- package/examples/project-directory-setup.md +114 -0
- package/package.json +85 -0
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const git_1 = require("../../utils/git");
|
|
37
|
+
const os = __importStar(require("os"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const fs = __importStar(require("fs"));
|
|
40
|
+
const uuid_1 = require("uuid");
|
|
41
|
+
const simple_git_1 = require("simple-git");
|
|
42
|
+
const database_helper_js_1 = require("../../test-helpers/database-helper.js");
|
|
43
|
+
describe('Git Integration Tests', () => {
|
|
44
|
+
let dbManager;
|
|
45
|
+
let gitOps;
|
|
46
|
+
let tempDbPath;
|
|
47
|
+
let tempRepoPath;
|
|
48
|
+
let db;
|
|
49
|
+
let git; // Track git instance for cleanup
|
|
50
|
+
beforeEach(async () => {
|
|
51
|
+
tempDbPath = path.join(os.tmpdir(), `test-git-${Date.now()}.db`);
|
|
52
|
+
tempRepoPath = path.join(os.tmpdir(), `test-repo-${Date.now()}`);
|
|
53
|
+
dbManager = database_helper_js_1.TestDatabaseHelper.createTestDatabase();
|
|
54
|
+
db = dbManager.getDatabase();
|
|
55
|
+
// Create and initialize a real git repo for testing
|
|
56
|
+
fs.mkdirSync(tempRepoPath, { recursive: true });
|
|
57
|
+
git = (0, simple_git_1.simpleGit)(tempRepoPath);
|
|
58
|
+
await git.init(['--initial-branch=master']);
|
|
59
|
+
await git.addConfig('user.name', 'Test User');
|
|
60
|
+
await git.addConfig('user.email', 'test@example.com');
|
|
61
|
+
// Use repo-local hooks directory to prevent global hooks from interfering
|
|
62
|
+
const localHooksDir = path.join(tempRepoPath, '.git', 'hooks');
|
|
63
|
+
await git.addConfig('core.hooksPath', localHooksDir);
|
|
64
|
+
await git.addConfig('commit.gpgsign', 'false');
|
|
65
|
+
// Create initial commit
|
|
66
|
+
fs.writeFileSync(path.join(tempRepoPath, 'README.md'), '# Test Repo');
|
|
67
|
+
await git.add('.');
|
|
68
|
+
await git.commit('Initial commit');
|
|
69
|
+
gitOps = new git_1.GitOperations(tempRepoPath);
|
|
70
|
+
});
|
|
71
|
+
afterEach(async () => {
|
|
72
|
+
// Clean up git processes first
|
|
73
|
+
if (git) {
|
|
74
|
+
try {
|
|
75
|
+
// Clear any pending git operations
|
|
76
|
+
git.removeAllListeners?.();
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
console.warn('Error cleaning up git:', error);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// Clean up databases
|
|
83
|
+
await database_helper_js_1.TestDatabaseHelper.cleanupAll();
|
|
84
|
+
// Clean up temp directories and files
|
|
85
|
+
try {
|
|
86
|
+
database_helper_js_1.TestDatabaseHelper.cleanupDbFiles(tempDbPath);
|
|
87
|
+
fs.rmSync(tempRepoPath, { recursive: true, force: true });
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
console.warn('Error cleaning up temp files:', error);
|
|
91
|
+
}
|
|
92
|
+
git = null;
|
|
93
|
+
});
|
|
94
|
+
describe('context_git_commit', () => {
|
|
95
|
+
it('should automatically save context on commit', async () => {
|
|
96
|
+
const sessionId = (0, uuid_1.v4)();
|
|
97
|
+
db.prepare('INSERT INTO sessions (id, name) VALUES (?, ?)').run(sessionId, 'Git Test Session');
|
|
98
|
+
// Add context items
|
|
99
|
+
const items = [
|
|
100
|
+
{ key: 'current_task', value: 'Implementing git integration', priority: 'high' },
|
|
101
|
+
{ key: 'decision', value: 'Use simple-git library', priority: 'normal' },
|
|
102
|
+
];
|
|
103
|
+
items.forEach(item => {
|
|
104
|
+
db.prepare('INSERT INTO context_items (id, session_id, key, value, priority) VALUES (?, ?, ?, ?, ?)').run((0, uuid_1.v4)(), sessionId, item.key, item.value, item.priority);
|
|
105
|
+
});
|
|
106
|
+
// Make a change and commit
|
|
107
|
+
fs.writeFileSync(path.join(tempRepoPath, 'test.txt'), 'test content');
|
|
108
|
+
const git = (0, simple_git_1.simpleGit)(tempRepoPath);
|
|
109
|
+
await git.add('.');
|
|
110
|
+
const commitResult = await git.commit('Test commit');
|
|
111
|
+
// Simulate auto-save on commit
|
|
112
|
+
const checkpointId = (0, uuid_1.v4)();
|
|
113
|
+
const gitInfo = await gitOps.getGitInfo();
|
|
114
|
+
db.prepare('INSERT INTO checkpoints (id, session_id, name, description, git_status, git_branch) VALUES (?, ?, ?, ?, ?, ?)').run(checkpointId, sessionId, `Git commit: ${commitResult.commit}`, 'Auto-saved on git commit', gitInfo.status, gitInfo.branch);
|
|
115
|
+
// Link context items
|
|
116
|
+
const contextItems = db
|
|
117
|
+
.prepare('SELECT id FROM context_items WHERE session_id = ?')
|
|
118
|
+
.all(sessionId);
|
|
119
|
+
contextItems.forEach((item) => {
|
|
120
|
+
db.prepare('INSERT INTO checkpoint_items (id, checkpoint_id, context_item_id) VALUES (?, ?, ?)').run((0, uuid_1.v4)(), checkpointId, item.id);
|
|
121
|
+
});
|
|
122
|
+
// Verify checkpoint was created
|
|
123
|
+
const checkpoint = db
|
|
124
|
+
.prepare('SELECT * FROM checkpoints WHERE id = ?')
|
|
125
|
+
.get(checkpointId);
|
|
126
|
+
expect(checkpoint).toBeDefined();
|
|
127
|
+
expect(checkpoint.name).toContain('Git commit:');
|
|
128
|
+
expect(checkpoint.git_branch).toBeTruthy();
|
|
129
|
+
});
|
|
130
|
+
it('should capture git status in checkpoint', async () => {
|
|
131
|
+
const sessionId = (0, uuid_1.v4)();
|
|
132
|
+
db.prepare('INSERT INTO sessions (id, name) VALUES (?, ?)').run(sessionId, 'Status Test');
|
|
133
|
+
// Create some changes
|
|
134
|
+
fs.writeFileSync(path.join(tempRepoPath, 'modified.txt'), 'original');
|
|
135
|
+
const git = (0, simple_git_1.simpleGit)(tempRepoPath);
|
|
136
|
+
await git.add('.');
|
|
137
|
+
await git.commit('Add file');
|
|
138
|
+
// Modify file
|
|
139
|
+
fs.writeFileSync(path.join(tempRepoPath, 'modified.txt'), 'changed');
|
|
140
|
+
// Create new file
|
|
141
|
+
fs.writeFileSync(path.join(tempRepoPath, 'new.txt'), 'new content');
|
|
142
|
+
// Stage one file
|
|
143
|
+
await git.add('modified.txt');
|
|
144
|
+
// Get git info
|
|
145
|
+
const gitInfo = await gitOps.getGitInfo();
|
|
146
|
+
// Create checkpoint with git status
|
|
147
|
+
const checkpointId = (0, uuid_1.v4)();
|
|
148
|
+
db.prepare('INSERT INTO checkpoints (id, session_id, name, git_status, git_branch) VALUES (?, ?, ?, ?, ?)').run(checkpointId, sessionId, 'Status Checkpoint', gitInfo.status, gitInfo.branch);
|
|
149
|
+
const checkpoint = db
|
|
150
|
+
.prepare('SELECT * FROM checkpoints WHERE id = ?')
|
|
151
|
+
.get(checkpointId);
|
|
152
|
+
expect(checkpoint.git_status).toContain('modified.txt');
|
|
153
|
+
// Parse the status to check properly
|
|
154
|
+
const status = JSON.parse(checkpoint.git_status);
|
|
155
|
+
expect(status.not_added).toContain('new.txt');
|
|
156
|
+
expect(checkpoint.git_branch).toBe('master'); // Default branch name
|
|
157
|
+
});
|
|
158
|
+
it('should handle commits with message containing context summary', async () => {
|
|
159
|
+
const sessionId = (0, uuid_1.v4)();
|
|
160
|
+
db.prepare('INSERT INTO sessions (id, name) VALUES (?, ?)').run(sessionId, 'Commit Message Test');
|
|
161
|
+
// Add context items that should be in commit message
|
|
162
|
+
const tasks = [
|
|
163
|
+
{ key: 'task1', value: 'Fixed authentication bug' },
|
|
164
|
+
{ key: 'task2', value: 'Added user validation' },
|
|
165
|
+
];
|
|
166
|
+
tasks.forEach(task => {
|
|
167
|
+
db.prepare('INSERT INTO context_items (id, session_id, key, value, category) VALUES (?, ?, ?, ?, ?)').run((0, uuid_1.v4)(), sessionId, task.key, task.value, 'task');
|
|
168
|
+
});
|
|
169
|
+
// Generate commit message with context
|
|
170
|
+
const completedTasks = db
|
|
171
|
+
.prepare('SELECT value FROM context_items WHERE session_id = ? AND category = ?')
|
|
172
|
+
.all(sessionId, 'task');
|
|
173
|
+
const commitMessage = [
|
|
174
|
+
'Feature: User authentication improvements',
|
|
175
|
+
'',
|
|
176
|
+
'Tasks completed:',
|
|
177
|
+
...completedTasks.map((t) => `- ${t.value}`),
|
|
178
|
+
'',
|
|
179
|
+
'[Context saved by MCP Memory Keeper]',
|
|
180
|
+
].join('\n');
|
|
181
|
+
// Make change and commit
|
|
182
|
+
fs.writeFileSync(path.join(tempRepoPath, 'auth.js'), 'auth code');
|
|
183
|
+
const git = (0, simple_git_1.simpleGit)(tempRepoPath);
|
|
184
|
+
await git.add('.');
|
|
185
|
+
const commitResult = await git.commit(commitMessage);
|
|
186
|
+
expect(commitResult.commit).toBeTruthy();
|
|
187
|
+
// Verify commit message
|
|
188
|
+
const log = await git.log(['-1']);
|
|
189
|
+
expect(log.latest).toBeDefined();
|
|
190
|
+
expect(log.latest?.message || log.latest?.hash).toBeDefined();
|
|
191
|
+
// The actual message should be in the latest entry
|
|
192
|
+
});
|
|
193
|
+
it('should link commits to sessions', async () => {
|
|
194
|
+
const sessionId = (0, uuid_1.v4)();
|
|
195
|
+
db.prepare('INSERT INTO sessions (id, name) VALUES (?, ?)').run(sessionId, 'Linked Commit Test');
|
|
196
|
+
// Make multiple commits
|
|
197
|
+
const git = (0, simple_git_1.simpleGit)(tempRepoPath);
|
|
198
|
+
const commits = [];
|
|
199
|
+
for (let i = 0; i < 3; i++) {
|
|
200
|
+
fs.writeFileSync(path.join(tempRepoPath, `file${i}.txt`), `content ${i}`);
|
|
201
|
+
await git.add('.');
|
|
202
|
+
const result = await git.commit(`Commit ${i}`);
|
|
203
|
+
commits.push(result.commit);
|
|
204
|
+
// Link commit to session - store commit hash in description
|
|
205
|
+
const checkpointId = (0, uuid_1.v4)();
|
|
206
|
+
db.prepare('INSERT INTO checkpoints (id, session_id, name, description) VALUES (?, ?, ?, ?)').run(checkpointId, sessionId, `Commit ${i}`, `Commit hash: ${result.commit}`);
|
|
207
|
+
}
|
|
208
|
+
// Query commits for session - using description field instead of metadata
|
|
209
|
+
const sessionCommits = db
|
|
210
|
+
.prepare(`SELECT * FROM checkpoints
|
|
211
|
+
WHERE session_id = ?
|
|
212
|
+
AND description LIKE 'Commit hash:%'
|
|
213
|
+
ORDER BY created_at`)
|
|
214
|
+
.all(sessionId);
|
|
215
|
+
expect(sessionCommits).toHaveLength(3);
|
|
216
|
+
sessionCommits.forEach((checkpoint, i) => {
|
|
217
|
+
// Extract commit hash from description
|
|
218
|
+
const match = checkpoint.description.match(/Commit hash: (.+)/);
|
|
219
|
+
expect(match).toBeTruthy();
|
|
220
|
+
expect(match[1]).toBe(commits[i]);
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
describe('Git error handling', () => {
|
|
225
|
+
it('should handle non-git directories gracefully', async () => {
|
|
226
|
+
const nonGitPath = path.join(os.tmpdir(), `non-git-${Date.now()}`);
|
|
227
|
+
fs.mkdirSync(nonGitPath, { recursive: true });
|
|
228
|
+
const nonGitOps = new git_1.GitOperations(nonGitPath);
|
|
229
|
+
const info = await nonGitOps.getGitInfo();
|
|
230
|
+
expect(info.isGitRepo).toBe(false);
|
|
231
|
+
expect(info.status.toLowerCase()).toContain('not a git repository');
|
|
232
|
+
fs.rmSync(nonGitPath, { recursive: true, force: true });
|
|
233
|
+
});
|
|
234
|
+
it('should handle git operation failures', async () => {
|
|
235
|
+
// Test with invalid commit (no changes)
|
|
236
|
+
const result = await gitOps.safeCommit('Empty commit');
|
|
237
|
+
expect(result.success).toBe(false);
|
|
238
|
+
expect(result.error).toContain('No changes to commit');
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
});
|