kemdicode-mcp 1.18.0 → 1.19.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.
- package/README.md +16 -3
- package/dist/ai/execute.d.ts.map +1 -1
- package/dist/ai/execute.js +11 -1
- package/dist/ai/execute.js.map +1 -1
- package/dist/context/agent-monitor.d.ts +3 -3
- package/dist/context/agent-monitor.d.ts.map +1 -1
- package/dist/context/agent-monitor.js +15 -9
- package/dist/context/agent-monitor.js.map +1 -1
- package/dist/context/storage.d.ts.map +1 -1
- package/dist/context/storage.js +18 -2
- package/dist/context/storage.js.map +1 -1
- package/dist/kanban/kanban-store.d.ts +0 -18
- package/dist/kanban/kanban-store.d.ts.map +1 -1
- package/dist/kanban/kanban-store.js +97 -80
- package/dist/kanban/kanban-store.js.map +1 -1
- package/dist/recursive/tool-invoker.d.ts.map +1 -1
- package/dist/recursive/tool-invoker.js +5 -8
- package/dist/recursive/tool-invoker.js.map +1 -1
- package/dist/session/manager.d.ts.map +1 -1
- package/dist/session/manager.js +10 -3
- package/dist/session/manager.js.map +1 -1
- package/dist/tools/agents/agent-alert.tool.d.ts.map +1 -1
- package/dist/tools/agents/agent-alert.tool.js +7 -21
- package/dist/tools/agents/agent-alert.tool.js.map +1 -1
- package/dist/tools/agents/agent-inject.tool.d.ts.map +1 -1
- package/dist/tools/agents/agent-inject.tool.js +11 -23
- package/dist/tools/agents/agent-inject.tool.js.map +1 -1
- package/dist/tools/agents/agent-register.tool.d.ts.map +1 -1
- package/dist/tools/agents/agent-register.tool.js +1 -1
- package/dist/tools/agents/agent-register.tool.js.map +1 -1
- package/dist/tools/agents/queue-message.tool.js +2 -2
- package/dist/tools/agents/queue-message.tool.js.map +1 -1
- package/dist/tools/file/file-diff.tool.d.ts.map +1 -1
- package/dist/tools/file/file-diff.tool.js +86 -72
- package/dist/tools/file/file-diff.tool.js.map +1 -1
- package/dist/tools/file/file-read.tool.d.ts.map +1 -1
- package/dist/tools/file/file-read.tool.js +100 -123
- package/dist/tools/file/file-read.tool.js.map +1 -1
- package/dist/tools/file/file-write.tool.d.ts.map +1 -1
- package/dist/tools/file/file-write.tool.js +96 -102
- package/dist/tools/file/file-write.tool.js.map +1 -1
- package/dist/tools/git/git-log.tool.d.ts.map +1 -1
- package/dist/tools/git/git-log.tool.js +4 -1
- package/dist/tools/git/git-log.tool.js.map +1 -1
- package/dist/tools/kanban/board-create.tool.d.ts.map +1 -1
- package/dist/tools/kanban/board-create.tool.js +44 -35
- package/dist/tools/kanban/board-create.tool.js.map +1 -1
- package/dist/tools/kanban/board-invite.tool.d.ts.map +1 -1
- package/dist/tools/kanban/board-invite.tool.js +52 -42
- package/dist/tools/kanban/board-invite.tool.js.map +1 -1
- package/dist/tools/kanban/board-members.tool.d.ts.map +1 -1
- package/dist/tools/kanban/board-members.tool.js +123 -97
- package/dist/tools/kanban/board-members.tool.js.map +1 -1
- package/dist/tools/kanban/board-share.tool.d.ts.map +1 -1
- package/dist/tools/kanban/board-share.tool.js +48 -38
- package/dist/tools/kanban/board-share.tool.js.map +1 -1
- package/dist/tools/kanban/workspace-create.tool.d.ts.map +1 -1
- package/dist/tools/kanban/workspace-create.tool.js +41 -30
- package/dist/tools/kanban/workspace-create.tool.js.map +1 -1
- package/dist/tools/memory/checkpoint-restore.tool.d.ts.map +1 -1
- package/dist/tools/memory/checkpoint-restore.tool.js +1 -9
- package/dist/tools/memory/checkpoint-restore.tool.js.map +1 -1
- package/dist/tools/memory/checkpoint-save.tool.d.ts.map +1 -1
- package/dist/tools/memory/checkpoint-save.tool.js +2 -28
- package/dist/tools/memory/checkpoint-save.tool.js.map +1 -1
- package/dist/tools/memory/delete-memory.tool.d.ts.map +1 -1
- package/dist/tools/memory/delete-memory.tool.js +34 -35
- package/dist/tools/memory/delete-memory.tool.js.map +1 -1
- package/dist/tools/memory/edit-memory.tool.d.ts.map +1 -1
- package/dist/tools/memory/edit-memory.tool.js +89 -117
- package/dist/tools/memory/edit-memory.tool.js.map +1 -1
- package/dist/tools/memory/list-memories.tool.d.ts.map +1 -1
- package/dist/tools/memory/list-memories.tool.js +53 -46
- package/dist/tools/memory/list-memories.tool.js.map +1 -1
- package/dist/tools/memory/read-memory.tool.d.ts.map +1 -1
- package/dist/tools/memory/read-memory.tool.js +45 -39
- package/dist/tools/memory/read-memory.tool.js.map +1 -1
- package/dist/tools/memory/shared.d.ts +61 -0
- package/dist/tools/memory/shared.d.ts.map +1 -0
- package/dist/tools/memory/shared.js +63 -0
- package/dist/tools/memory/shared.js.map +1 -0
- package/dist/tools/memory/write-memory.tool.d.ts.map +1 -1
- package/dist/tools/memory/write-memory.tool.js +68 -107
- package/dist/tools/memory/write-memory.tool.js.map +1 -1
- package/dist/tools/multi-llm/consensus-prompt.tool.d.ts.map +1 -1
- package/dist/tools/multi-llm/consensus-prompt.tool.js +7 -3
- package/dist/tools/multi-llm/consensus-prompt.tool.js.map +1 -1
- package/dist/tools/registry.d.ts +13 -0
- package/dist/tools/registry.d.ts.map +1 -1
- package/dist/tools/registry.js +25 -0
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/session/session-create.tool.d.ts +8 -6
- package/dist/tools/session/session-create.tool.d.ts.map +1 -1
- package/dist/tools/session/session-create.tool.js +44 -34
- package/dist/tools/session/session-create.tool.js.map +1 -1
- package/dist/tools/session/session-delete.tool.d.ts +4 -2
- package/dist/tools/session/session-delete.tool.d.ts.map +1 -1
- package/dist/tools/session/session-delete.tool.js +51 -53
- package/dist/tools/session/session-delete.tool.js.map +1 -1
- package/dist/tools/specialized/code-review.tool.d.ts.map +1 -1
- package/dist/tools/specialized/code-review.tool.js +1 -0
- package/dist/tools/specialized/code-review.tool.js.map +1 -1
- package/dist/utils/format-helpers.d.ts +41 -0
- package/dist/utils/format-helpers.d.ts.map +1 -0
- package/dist/utils/format-helpers.js +76 -0
- package/dist/utils/format-helpers.js.map +1 -0
- package/dist/utils/projectContext.enhanced.d.ts.map +1 -1
- package/dist/utils/projectContext.enhanced.js +19 -4
- package/dist/utils/projectContext.enhanced.js.map +1 -1
- package/dist/utils/security.d.ts.map +1 -1
- package/dist/utils/security.js +11 -2
- package/dist/utils/security.js.map +1 -1
- package/dist/utils/validation.d.ts.map +1 -1
- package/dist/utils/validation.js +2 -4
- package/dist/utils/validation.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -24,23 +24,10 @@
|
|
|
24
24
|
* @module tools/memory/edit-memory
|
|
25
25
|
*/
|
|
26
26
|
import { z } from 'zod';
|
|
27
|
-
import { getSharedRedis } from '../../infrastructure/redis/connection.js';
|
|
28
|
-
import { createHash } from 'crypto';
|
|
29
27
|
import { Logger } from '../../utils/logger.js';
|
|
30
28
|
import { checkRateLimit } from '../../utils/validation.js';
|
|
31
|
-
|
|
32
|
-
const
|
|
33
|
-
/** Maximum memory content size: 1MB */
|
|
34
|
-
const MAX_CONTENT_SIZE = 1024 * 1024;
|
|
35
|
-
const getRedis = getSharedRedis;
|
|
36
|
-
/**
|
|
37
|
-
* Generate project ID from current working directory
|
|
38
|
-
*/
|
|
39
|
-
function getProjectId() {
|
|
40
|
-
const cwd = process.cwd();
|
|
41
|
-
return createHash('sha256').update(cwd).digest('hex').slice(0, 16);
|
|
42
|
-
}
|
|
43
|
-
const schema = z.object({
|
|
29
|
+
import { MEMORY_PREFIX, MAX_CONTENT_SIZE, getRedis, getProjectId, } from './shared.js';
|
|
30
|
+
const editItemSchema = z.object({
|
|
44
31
|
name: z.string().min(1).describe('Memory name'),
|
|
45
32
|
content: z.string().optional().describe('Replacement content'),
|
|
46
33
|
appendContent: z.string().optional().describe('Content to append'),
|
|
@@ -49,13 +36,15 @@ const schema = z.object({
|
|
|
49
36
|
addTags: z.array(z.string()).optional().describe('Tags to add'),
|
|
50
37
|
removeTags: z.array(z.string()).optional().describe('Tags to remove'),
|
|
51
38
|
});
|
|
39
|
+
const schema = z.object({
|
|
40
|
+
edits: z.array(editItemSchema).min(1).max(10).describe('Memory edits to apply (1-10)'),
|
|
41
|
+
});
|
|
52
42
|
export const editMemoryTool = {
|
|
53
43
|
name: 'edit-memory',
|
|
54
|
-
description: 'Edit existing
|
|
44
|
+
description: 'Edit 1-10 existing memories (content/tags). Returns results.',
|
|
55
45
|
zodSchema: schema,
|
|
56
46
|
execute: async (args) => {
|
|
57
|
-
const {
|
|
58
|
-
// Rate limit check
|
|
47
|
+
const { edits } = args;
|
|
59
48
|
if (!checkRateLimit('memory-operations', { maxRequests: 50, windowMs: 60000 })) {
|
|
60
49
|
return JSON.stringify({
|
|
61
50
|
success: false,
|
|
@@ -63,110 +52,93 @@ export const editMemoryTool = {
|
|
|
63
52
|
code: 'RATE_LIMIT_EXCEEDED',
|
|
64
53
|
});
|
|
65
54
|
}
|
|
66
|
-
// Check if any edit is requested
|
|
67
|
-
if (!content && !appendContent && !prependContent && !tags && !addTags && !removeTags) {
|
|
68
|
-
return JSON.stringify({
|
|
69
|
-
success: false,
|
|
70
|
-
error: 'No edit operations specified',
|
|
71
|
-
code: 'NO_EDITS',
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
55
|
const projectId = getProjectId();
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
if (!data) {
|
|
81
|
-
return JSON.stringify({
|
|
82
|
-
success: false,
|
|
83
|
-
error: `Memory '${name}' not found`,
|
|
84
|
-
code: 'MEMORY_NOT_FOUND',
|
|
85
|
-
name,
|
|
86
|
-
projectId,
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
const memory = JSON.parse(data);
|
|
90
|
-
const ttl = await client.ttl(memoryKey);
|
|
91
|
-
// Track changes
|
|
92
|
-
const changes = [];
|
|
93
|
-
// Update content
|
|
94
|
-
let newContent = memory.content;
|
|
95
|
-
if (content !== undefined) {
|
|
96
|
-
newContent = content;
|
|
97
|
-
changes.push('content replaced');
|
|
98
|
-
}
|
|
99
|
-
if (prependContent) {
|
|
100
|
-
newContent = prependContent + newContent;
|
|
101
|
-
changes.push(`prepended ${prependContent.length} chars`);
|
|
102
|
-
}
|
|
103
|
-
if (appendContent) {
|
|
104
|
-
newContent = newContent + appendContent;
|
|
105
|
-
changes.push(`appended ${appendContent.length} chars`);
|
|
106
|
-
}
|
|
107
|
-
// Check content size
|
|
108
|
-
if (newContent.length > MAX_CONTENT_SIZE) {
|
|
109
|
-
return JSON.stringify({
|
|
110
|
-
success: false,
|
|
111
|
-
error: `Content too large: ${newContent.length} bytes (max: ${MAX_CONTENT_SIZE} bytes)`,
|
|
112
|
-
code: 'CONTENT_TOO_LARGE',
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
// Update tags
|
|
116
|
-
let newTags = memory.tags;
|
|
117
|
-
if (tags !== undefined) {
|
|
118
|
-
newTags = tags;
|
|
119
|
-
changes.push('tags replaced');
|
|
120
|
-
}
|
|
121
|
-
if (addTags && addTags.length > 0) {
|
|
122
|
-
const added = addTags.filter((t) => !newTags.includes(t));
|
|
123
|
-
newTags = [...newTags, ...added];
|
|
124
|
-
if (added.length > 0) {
|
|
125
|
-
changes.push(`added tags: ${added.join(', ')}`);
|
|
56
|
+
const results = await Promise.all(edits.map(async (item) => {
|
|
57
|
+
try {
|
|
58
|
+
const { name, content, appendContent, prependContent, tags, addTags, removeTags } = item;
|
|
59
|
+
if (!content && !appendContent && !prependContent && !tags && !addTags && !removeTags) {
|
|
60
|
+
return { name, success: false, error: 'No edit operations specified', code: 'NO_EDITS' };
|
|
126
61
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
changes.push(`removed tags: ${removed.join(', ')}`);
|
|
62
|
+
const memoryKey = `${MEMORY_PREFIX}${projectId}:${name}`;
|
|
63
|
+
const client = await getRedis();
|
|
64
|
+
const data = await client.get(memoryKey);
|
|
65
|
+
if (!data) {
|
|
66
|
+
return { name, success: false, error: `Memory '${name}' not found`, code: 'MEMORY_NOT_FOUND' };
|
|
133
67
|
}
|
|
68
|
+
const memory = JSON.parse(data);
|
|
69
|
+
const ttl = await client.ttl(memoryKey);
|
|
70
|
+
const changes = [];
|
|
71
|
+
let newContent = memory.content;
|
|
72
|
+
if (content !== undefined) {
|
|
73
|
+
newContent = content;
|
|
74
|
+
changes.push('content replaced');
|
|
75
|
+
}
|
|
76
|
+
if (prependContent) {
|
|
77
|
+
newContent = prependContent + newContent;
|
|
78
|
+
changes.push(`prepended ${prependContent.length} chars`);
|
|
79
|
+
}
|
|
80
|
+
if (appendContent) {
|
|
81
|
+
newContent = newContent + appendContent;
|
|
82
|
+
changes.push(`appended ${appendContent.length} chars`);
|
|
83
|
+
}
|
|
84
|
+
if (newContent.length > MAX_CONTENT_SIZE) {
|
|
85
|
+
return { name, success: false, error: 'Content too large', code: 'CONTENT_TOO_LARGE' };
|
|
86
|
+
}
|
|
87
|
+
let newTags = memory.tags;
|
|
88
|
+
if (tags !== undefined) {
|
|
89
|
+
newTags = tags;
|
|
90
|
+
changes.push('tags replaced');
|
|
91
|
+
}
|
|
92
|
+
if (addTags && addTags.length > 0) {
|
|
93
|
+
const added = addTags.filter((t) => !newTags.includes(t));
|
|
94
|
+
newTags = [...newTags, ...added];
|
|
95
|
+
if (added.length > 0)
|
|
96
|
+
changes.push(`added tags: ${added.join(', ')}`);
|
|
97
|
+
}
|
|
98
|
+
if (removeTags && removeTags.length > 0) {
|
|
99
|
+
const removed = removeTags.filter((t) => newTags.includes(t));
|
|
100
|
+
newTags = newTags.filter((t) => !removeTags.includes(t));
|
|
101
|
+
if (removed.length > 0)
|
|
102
|
+
changes.push(`removed tags: ${removed.join(', ')}`);
|
|
103
|
+
}
|
|
104
|
+
const updatedMemory = {
|
|
105
|
+
...memory,
|
|
106
|
+
content: newContent,
|
|
107
|
+
tags: newTags,
|
|
108
|
+
updatedAt: Date.now(),
|
|
109
|
+
};
|
|
110
|
+
if (ttl > 0) {
|
|
111
|
+
await client.setex(memoryKey, ttl, JSON.stringify(updatedMemory));
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
await client.set(memoryKey, JSON.stringify(updatedMemory));
|
|
115
|
+
}
|
|
116
|
+
Logger.debug(`edit-memory: updated '${name}': ${changes.join(', ')}`);
|
|
117
|
+
return {
|
|
118
|
+
name,
|
|
119
|
+
success: true,
|
|
120
|
+
changes,
|
|
121
|
+
contentLength: newContent.length,
|
|
122
|
+
tags: newTags,
|
|
123
|
+
};
|
|
134
124
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
};
|
|
142
|
-
// Save with preserved TTL
|
|
143
|
-
if (ttl > 0) {
|
|
144
|
-
await client.setex(memoryKey, ttl, JSON.stringify(updatedMemory));
|
|
145
|
-
}
|
|
146
|
-
else {
|
|
147
|
-
await client.set(memoryKey, JSON.stringify(updatedMemory));
|
|
125
|
+
catch (error) {
|
|
126
|
+
return {
|
|
127
|
+
name: item.name,
|
|
128
|
+
success: false,
|
|
129
|
+
error: error instanceof Error ? error.message : String(error),
|
|
130
|
+
};
|
|
148
131
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
catch (error) {
|
|
162
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
163
|
-
Logger.error(`edit-memory error: ${errorMessage}`);
|
|
164
|
-
return JSON.stringify({
|
|
165
|
-
success: false,
|
|
166
|
-
error: errorMessage,
|
|
167
|
-
code: 'STORAGE_ERROR',
|
|
168
|
-
});
|
|
169
|
-
}
|
|
132
|
+
}));
|
|
133
|
+
const successful = results.filter((r) => r.success);
|
|
134
|
+
const failed = results.filter((r) => !r.success);
|
|
135
|
+
return JSON.stringify({
|
|
136
|
+
success: failed.length === 0,
|
|
137
|
+
projectId,
|
|
138
|
+
edited: successful.length,
|
|
139
|
+
failed: failed.length,
|
|
140
|
+
results,
|
|
141
|
+
});
|
|
170
142
|
},
|
|
171
143
|
};
|
|
172
144
|
//# sourceMappingURL=edit-memory.tool.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"edit-memory.tool.js","sourceRoot":"","sources":["../../../src/tools/memory/edit-memory.tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH;;;;;;;GAOG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"edit-memory.tool.js","sourceRoot":"","sources":["../../../src/tools/memory/edit-memory.tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list-memories.tool.d.ts","sourceRoot":"","sources":["../../../src/tools/memory/list-memories.tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;
|
|
1
|
+
{"version":3,"file":"list-memories.tool.d.ts","sourceRoot":"","sources":["../../../src/tools/memory/list-memories.tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAWH,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AA6B7C,eAAO,MAAM,gBAAgB,EAAE,WAsI9B,CAAC"}
|
|
@@ -23,21 +23,9 @@
|
|
|
23
23
|
* @module tools/memory/list-memories
|
|
24
24
|
*/
|
|
25
25
|
import { z } from 'zod';
|
|
26
|
-
import { getSharedRedis } from '../../infrastructure/redis/connection.js';
|
|
27
|
-
import { createHash } from 'crypto';
|
|
28
26
|
import { Logger } from '../../utils/logger.js';
|
|
29
27
|
import { checkRateLimit } from '../../utils/validation.js';
|
|
30
|
-
|
|
31
|
-
const MEMORY_PREFIX = 'mcp:memory:';
|
|
32
|
-
const MEMORY_INDEX_PREFIX = 'mcp:memory:index:';
|
|
33
|
-
const getRedis = getSharedRedis;
|
|
34
|
-
/**
|
|
35
|
-
* Generate project ID from current working directory
|
|
36
|
-
*/
|
|
37
|
-
function getProjectId() {
|
|
38
|
-
const cwd = process.cwd();
|
|
39
|
-
return createHash('sha256').update(cwd).digest('hex').slice(0, 16);
|
|
40
|
-
}
|
|
28
|
+
import { MEMORY_PREFIX, MEMORY_INDEX_PREFIX, getRedis, getProjectId, } from './shared.js';
|
|
41
29
|
const schema = z.object({
|
|
42
30
|
tag: z.string().optional().describe('Filter by tag'),
|
|
43
31
|
limit: z.number().min(1).max(100).default(50).describe('Max memories to list'),
|
|
@@ -72,47 +60,66 @@ export const listMemoriesTool = {
|
|
|
72
60
|
message: 'No memories found for this project',
|
|
73
61
|
});
|
|
74
62
|
}
|
|
75
|
-
// Fetch memory
|
|
63
|
+
// Fetch all memory data + TTLs in two pipeline batches (avoid N+1)
|
|
64
|
+
const memoryKeys = names.map((name) => `${MEMORY_PREFIX}${projectId}:${name}`);
|
|
65
|
+
const getPipeline = client.pipeline();
|
|
66
|
+
for (const key of memoryKeys) {
|
|
67
|
+
getPipeline.get(key);
|
|
68
|
+
}
|
|
69
|
+
const getResults = await getPipeline.exec();
|
|
70
|
+
const ttlPipeline = client.pipeline();
|
|
71
|
+
for (const key of memoryKeys) {
|
|
72
|
+
ttlPipeline.ttl(key);
|
|
73
|
+
}
|
|
74
|
+
const ttlResults = await ttlPipeline.exec();
|
|
76
75
|
const memories = [];
|
|
77
76
|
const memoriesWithContent = [];
|
|
78
|
-
|
|
77
|
+
const staleNames = [];
|
|
78
|
+
for (let i = 0; i < names.length; i++) {
|
|
79
79
|
if (memories.length >= limit)
|
|
80
80
|
break;
|
|
81
|
-
const
|
|
82
|
-
const
|
|
83
|
-
if (data) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
contentLength: memory.content.length,
|
|
94
|
-
tags: memory.tags,
|
|
95
|
-
createdAt: memory.createdAt,
|
|
96
|
-
updatedAt: memory.updatedAt,
|
|
97
|
-
ttlDays: ttl > 0 ? Math.round(ttl / 86400) : null,
|
|
98
|
-
};
|
|
99
|
-
memories.push(summary);
|
|
100
|
-
if (includeContent) {
|
|
101
|
-
memoriesWithContent.push({
|
|
102
|
-
...summary,
|
|
103
|
-
content: memory.content,
|
|
104
|
-
});
|
|
105
|
-
}
|
|
81
|
+
const [getErr, data] = (getResults?.[i] ?? [null, null]);
|
|
82
|
+
const [ttlErr, ttl] = (ttlResults?.[i] ?? [null, -1]);
|
|
83
|
+
if (getErr || !data) {
|
|
84
|
+
// Memory expired or deleted, mark for index cleanup
|
|
85
|
+
staleNames.push(names[i]);
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
const memory = JSON.parse(data);
|
|
90
|
+
// Filter by tag if specified
|
|
91
|
+
if (tag && !memory.tags.includes(tag)) {
|
|
92
|
+
continue;
|
|
106
93
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
94
|
+
const ttlValue = ttlErr ? null : ttl;
|
|
95
|
+
const summary = {
|
|
96
|
+
name: memory.name,
|
|
97
|
+
contentLength: memory.content.length,
|
|
98
|
+
tags: memory.tags,
|
|
99
|
+
createdAt: memory.createdAt,
|
|
100
|
+
updatedAt: memory.updatedAt,
|
|
101
|
+
ttlDays: ttlValue && ttlValue > 0 ? Math.round(ttlValue / 86400) : null,
|
|
102
|
+
};
|
|
103
|
+
memories.push(summary);
|
|
104
|
+
if (includeContent) {
|
|
105
|
+
memoriesWithContent.push({
|
|
106
|
+
...summary,
|
|
107
|
+
content: memory.content,
|
|
108
|
+
});
|
|
110
109
|
}
|
|
111
110
|
}
|
|
112
|
-
|
|
113
|
-
//
|
|
114
|
-
|
|
111
|
+
catch {
|
|
112
|
+
// Skip corrupted entries
|
|
113
|
+
Logger.warn(`list-memories: skipping corrupted entry '${names[i]}'`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// Cleanup stale index entries
|
|
117
|
+
if (staleNames.length > 0) {
|
|
118
|
+
const cleanupPipeline = client.pipeline();
|
|
119
|
+
for (const name of staleNames) {
|
|
120
|
+
cleanupPipeline.srem(indexKey, name);
|
|
115
121
|
}
|
|
122
|
+
await cleanupPipeline.exec();
|
|
116
123
|
}
|
|
117
124
|
// Sort by updatedAt descending
|
|
118
125
|
memories.sort((a, b) => b.updatedAt - a.updatedAt);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list-memories.tool.js","sourceRoot":"","sources":["../../../src/tools/memory/list-memories.tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH;;;;;;GAMG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"list-memories.tool.js","sourceRoot":"","sources":["../../../src/tools/memory/list-memories.tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH;;;;;;GAMG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAEL,aAAa,EACb,mBAAmB,EACnB,QAAQ,EACR,YAAY,GACb,MAAM,aAAa,CAAC;AAYrB,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;IACtB,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC;IACpD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,sBAAsB,CAAC;IAC9E,cAAc,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,gCAAgC,CAAC;CACtF,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,gBAAgB,GAAgB;IAC3C,IAAI,EAAE,eAAe;IACrB,WAAW,EAAE,uCAAuC;IACpD,SAAS,EAAE,MAAM;IAEjB,OAAO,EAAE,KAAK,EAAE,IAAI,EAAmB,EAAE;QACvC,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,cAAc,EAAE,GAAG,IAAwB,CAAC;QAEhE,mBAAmB;QACnB,IAAI,CAAC,cAAc,CAAC,mBAAmB,EAAE,EAAE,WAAW,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;YAChF,OAAO,IAAI,CAAC,SAAS,CAAC;gBACpB,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,2CAA2C;gBAClD,IAAI,EAAE,qBAAqB;aAC5B,CAAC,CAAC;QACL,CAAC;QAED,MAAM,SAAS,GAAG,YAAY,EAAE,CAAC;QACjC,MAAM,QAAQ,GAAG,GAAG,mBAAmB,GAAG,SAAS,EAAE,CAAC;QAEtD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,QAAQ,EAAE,CAAC;YAEhC,kCAAkC;YAClC,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAE9C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACvB,OAAO,IAAI,CAAC,SAAS,CAAC;oBACpB,OAAO,EAAE,IAAI;oBACb,SAAS;oBACT,KAAK,EAAE,CAAC;oBACR,QAAQ,EAAE,EAAE;oBACZ,OAAO,EAAE,oCAAoC;iBAC9C,CAAC,CAAC;YACL,CAAC;YAED,mEAAmE;YACnE,MAAM,UAAU,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,aAAa,GAAG,SAAS,IAAI,IAAI,EAAE,CAAC,CAAC;YAE/E,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;YACtC,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;gBAC7B,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACvB,CAAC;YACD,MAAM,UAAU,GAAG,MAAM,WAAW,CAAC,IAAI,EAAE,CAAC;YAE5C,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;YACtC,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;gBAC7B,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACvB,CAAC;YACD,MAAM,UAAU,GAAG,MAAM,WAAW,CAAC,IAAI,EAAE,CAAC;YAE5C,MAAM,QAAQ,GAAoB,EAAE,CAAC;YACrC,MAAM,mBAAmB,GAA6C,EAAE,CAAC;YACzE,MAAM,UAAU,GAAa,EAAE,CAAC;YAEhC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACtC,IAAI,QAAQ,CAAC,MAAM,IAAI,KAAK;oBAAE,MAAM;gBAEpC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAkC,CAAC;gBAC1F,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAA2B,CAAC;gBAEhF,IAAI,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;oBACpB,oDAAoD;oBACpD,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;oBAC1B,SAAS;gBACX,CAAC;gBAED,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAkB,CAAC;oBAEjD,6BAA6B;oBAC7B,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;wBACtC,SAAS;oBACX,CAAC;oBAED,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC;oBACrC,MAAM,OAAO,GAAkB;wBAC7B,IAAI,EAAE,MAAM,CAAC,IAAI;wBACjB,aAAa,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM;wBACpC,IAAI,EAAE,MAAM,CAAC,IAAI;wBACjB,SAAS,EAAE,MAAM,CAAC,SAAS;wBAC3B,SAAS,EAAE,MAAM,CAAC,SAAS;wBAC3B,OAAO,EAAE,QAAQ,IAAI,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI;qBACxE,CAAC;oBAEF,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;oBAEvB,IAAI,cAAc,EAAE,CAAC;wBACnB,mBAAmB,CAAC,IAAI,CAAC;4BACvB,GAAG,OAAO;4BACV,OAAO,EAAE,MAAM,CAAC,OAAO;yBACxB,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,yBAAyB;oBACzB,MAAM,CAAC,IAAI,CAAC,4CAA4C,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;gBACvE,CAAC;YACH,CAAC;YAED,8BAA8B;YAC9B,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC1B,MAAM,eAAe,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;gBAC1C,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;oBAC9B,eAAe,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;gBACvC,CAAC;gBACD,MAAM,eAAe,CAAC,IAAI,EAAE,CAAC;YAC/B,CAAC;YAED,+BAA+B;YAC/B,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC;YACnD,IAAI,cAAc,EAAE,CAAC;gBACnB,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC;YAChE,CAAC;YAED,MAAM,CAAC,KAAK,CAAC,wBAAwB,QAAQ,CAAC,MAAM,yBAAyB,SAAS,EAAE,CAAC,CAAC;YAE1F,OAAO,IAAI,CAAC,SAAS,CAAC;gBACpB,OAAO,EAAE,IAAI;gBACb,SAAS;gBACT,KAAK,EAAE,QAAQ,CAAC,MAAM;gBACtB,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI;gBAC5B,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,QAAQ;aAC1D,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC5E,MAAM,CAAC,KAAK,CAAC,wBAAwB,YAAY,EAAE,CAAC,CAAC;YAErD,OAAO,IAAI,CAAC,SAAS,CAAC;gBACpB,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,YAAY;gBACnB,IAAI,EAAE,eAAe;aACtB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;CACF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read-memory.tool.d.ts","sourceRoot":"","sources":["../../../src/tools/memory/read-memory.tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;
|
|
1
|
+
{"version":3,"file":"read-memory.tool.d.ts","sourceRoot":"","sources":["../../../src/tools/memory/read-memory.tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAWH,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAW7C,eAAO,MAAM,cAAc,EAAE,WAmF5B,CAAC"}
|
|
@@ -23,30 +23,18 @@
|
|
|
23
23
|
* @module tools/memory/read-memory
|
|
24
24
|
*/
|
|
25
25
|
import { z } from 'zod';
|
|
26
|
-
import { getSharedRedis } from '../../infrastructure/redis/connection.js';
|
|
27
|
-
import { createHash } from 'crypto';
|
|
28
26
|
import { Logger } from '../../utils/logger.js';
|
|
29
27
|
import { checkRateLimit } from '../../utils/validation.js';
|
|
30
|
-
|
|
31
|
-
const MEMORY_PREFIX = 'mcp:memory:';
|
|
32
|
-
const getRedis = getSharedRedis;
|
|
33
|
-
/**
|
|
34
|
-
* Generate project ID from current working directory
|
|
35
|
-
*/
|
|
36
|
-
function getProjectId() {
|
|
37
|
-
const cwd = process.cwd();
|
|
38
|
-
return createHash('sha256').update(cwd).digest('hex').slice(0, 16);
|
|
39
|
-
}
|
|
28
|
+
import { MEMORY_PREFIX, getRedis, getProjectId } from './shared.js';
|
|
40
29
|
const schema = z.object({
|
|
41
|
-
|
|
30
|
+
names: z.array(z.string().min(1)).min(1).max(20).describe('Memory names to retrieve (1-20)'),
|
|
42
31
|
});
|
|
43
32
|
export const readMemoryTool = {
|
|
44
33
|
name: 'read-memory',
|
|
45
|
-
description: 'Retrieve named
|
|
34
|
+
description: 'Retrieve 1-20 named memories from current project.',
|
|
46
35
|
zodSchema: schema,
|
|
47
36
|
execute: async (args) => {
|
|
48
|
-
const {
|
|
49
|
-
// Rate limit check
|
|
37
|
+
const { names } = args;
|
|
50
38
|
if (!checkRateLimit('memory-operations', { maxRequests: 200, windowMs: 60000 })) {
|
|
51
39
|
return JSON.stringify({
|
|
52
40
|
success: false,
|
|
@@ -55,33 +43,51 @@ export const readMemoryTool = {
|
|
|
55
43
|
});
|
|
56
44
|
}
|
|
57
45
|
const projectId = getProjectId();
|
|
58
|
-
const memoryKey = `${MEMORY_PREFIX}${projectId}:${name}`;
|
|
59
46
|
try {
|
|
60
47
|
const client = await getRedis();
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
projectId,
|
|
69
|
-
});
|
|
48
|
+
// Pipeline: fetch all memories at once
|
|
49
|
+
const getPipeline = client.pipeline();
|
|
50
|
+
const ttlPipeline = client.pipeline();
|
|
51
|
+
for (const name of names) {
|
|
52
|
+
const memoryKey = `${MEMORY_PREFIX}${projectId}:${name}`;
|
|
53
|
+
getPipeline.get(memoryKey);
|
|
54
|
+
ttlPipeline.ttl(memoryKey);
|
|
70
55
|
}
|
|
71
|
-
const
|
|
72
|
-
const
|
|
73
|
-
|
|
56
|
+
const getResults = await getPipeline.exec();
|
|
57
|
+
const ttlResults = await ttlPipeline.exec();
|
|
58
|
+
const results = names.map((name, i) => {
|
|
59
|
+
const data = getResults?.[i]?.[1];
|
|
60
|
+
const ttl = ttlResults?.[i]?.[1] ?? -1;
|
|
61
|
+
if (!data) {
|
|
62
|
+
return {
|
|
63
|
+
name,
|
|
64
|
+
success: false,
|
|
65
|
+
error: `Memory '${name}' not found`,
|
|
66
|
+
code: 'MEMORY_NOT_FOUND',
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
const memory = JSON.parse(data);
|
|
70
|
+
Logger.debug(`read-memory: retrieved '${name}' for project ${projectId}`);
|
|
71
|
+
return {
|
|
72
|
+
name: memory.name,
|
|
73
|
+
success: true,
|
|
74
|
+
content: memory.content,
|
|
75
|
+
contentLength: memory.content.length,
|
|
76
|
+
tags: memory.tags,
|
|
77
|
+
createdAt: memory.createdAt,
|
|
78
|
+
updatedAt: memory.updatedAt,
|
|
79
|
+
ttlSeconds: ttl > 0 ? ttl : null,
|
|
80
|
+
ttlDays: ttl > 0 ? Math.round(ttl / 86400) : null,
|
|
81
|
+
};
|
|
82
|
+
});
|
|
83
|
+
const successful = results.filter((r) => r.success);
|
|
84
|
+
const failed = results.filter((r) => !r.success);
|
|
74
85
|
return JSON.stringify({
|
|
75
|
-
success:
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
tags: memory.tags,
|
|
81
|
-
createdAt: memory.createdAt,
|
|
82
|
-
updatedAt: memory.updatedAt,
|
|
83
|
-
ttlSeconds: ttl > 0 ? ttl : null,
|
|
84
|
-
ttlDays: ttl > 0 ? Math.round(ttl / 86400) : null,
|
|
86
|
+
success: failed.length === 0,
|
|
87
|
+
projectId,
|
|
88
|
+
found: successful.length,
|
|
89
|
+
notFound: failed.length,
|
|
90
|
+
results,
|
|
85
91
|
});
|
|
86
92
|
}
|
|
87
93
|
catch (error) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read-memory.tool.js","sourceRoot":"","sources":["../../../src/tools/memory/read-memory.tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH;;;;;;GAMG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"read-memory.tool.js","sourceRoot":"","sources":["../../../src/tools/memory/read-memory.tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH;;;;;;GAMG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAsB,aAAa,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAExF,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;IACtB,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,iCAAiC,CAAC;CAC7F,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,cAAc,GAAgB;IACzC,IAAI,EAAE,aAAa;IACnB,WAAW,EAAE,oDAAoD;IACjE,SAAS,EAAE,MAAM;IAEjB,OAAO,EAAE,KAAK,EAAE,IAAI,EAAmB,EAAE;QACvC,MAAM,EAAE,KAAK,EAAE,GAAG,IAAsB,CAAC;QAEzC,IAAI,CAAC,cAAc,CAAC,mBAAmB,EAAE,EAAE,WAAW,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;YAChF,OAAO,IAAI,CAAC,SAAS,CAAC;gBACpB,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,2CAA2C;gBAClD,IAAI,EAAE,qBAAqB;aAC5B,CAAC,CAAC;QACL,CAAC;QAED,MAAM,SAAS,GAAG,YAAY,EAAE,CAAC;QAEjC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,QAAQ,EAAE,CAAC;YAEhC,uCAAuC;YACvC,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;YACtC,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;YACtC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,MAAM,SAAS,GAAG,GAAG,aAAa,GAAG,SAAS,IAAI,IAAI,EAAE,CAAC;gBACzD,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;gBAC3B,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAC7B,CAAC;YAED,MAAM,UAAU,GAAG,MAAM,WAAW,CAAC,IAAI,EAAE,CAAC;YAC5C,MAAM,UAAU,GAAG,MAAM,WAAW,CAAC,IAAI,EAAE,CAAC;YAE5C,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;gBACpC,MAAM,IAAI,GAAG,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAkB,CAAC;gBACnD,MAAM,GAAG,GAAI,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAY,IAAI,CAAC,CAAC,CAAC;gBAEnD,IAAI,CAAC,IAAI,EAAE,CAAC;oBACV,OAAO;wBACL,IAAI;wBACJ,OAAO,EAAE,KAAK;wBACd,KAAK,EAAE,WAAW,IAAI,aAAa;wBACnC,IAAI,EAAE,kBAAkB;qBACzB,CAAC;gBACJ,CAAC;gBAED,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAkB,CAAC;gBACjD,MAAM,CAAC,KAAK,CAAC,2BAA2B,IAAI,iBAAiB,SAAS,EAAE,CAAC,CAAC;gBAE1E,OAAO;oBACL,IAAI,EAAE,MAAM,CAAC,IAAI;oBACjB,OAAO,EAAE,IAAI;oBACb,OAAO,EAAE,MAAM,CAAC,OAAO;oBACvB,aAAa,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM;oBACpC,IAAI,EAAE,MAAM,CAAC,IAAI;oBACjB,SAAS,EAAE,MAAM,CAAC,SAAS;oBAC3B,SAAS,EAAE,MAAM,CAAC,SAAS;oBAC3B,UAAU,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI;oBAChC,OAAO,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI;iBAClD,CAAC;YACJ,CAAC,CAAC,CAAC;YAEH,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;YACpD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;YAEjD,OAAO,IAAI,CAAC,SAAS,CAAC;gBACpB,OAAO,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;gBAC5B,SAAS;gBACT,KAAK,EAAE,UAAU,CAAC,MAAM;gBACxB,QAAQ,EAAE,MAAM,CAAC,MAAM;gBACvB,OAAO;aACR,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC5E,MAAM,CAAC,KAAK,CAAC,sBAAsB,YAAY,EAAE,CAAC,CAAC;YAEnD,OAAO,IAAI,CAAC,SAAS,CAAC;gBACpB,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,YAAY;gBACnB,IAAI,EAAE,eAAe;aACtB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KemdiCode MCP Server
|
|
3
|
+
* Copyright (C) 2025-2026 Kemdi Sp. z o.o.
|
|
4
|
+
*
|
|
5
|
+
* This program is free software: you can redistribute it and/or modify
|
|
6
|
+
* it under the terms of the GNU General Public License as published by
|
|
7
|
+
* the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
* (at your option) any later version.
|
|
9
|
+
*
|
|
10
|
+
* This program is distributed in the hope that it will be useful,
|
|
11
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
* GNU General Public License for more details.
|
|
14
|
+
*
|
|
15
|
+
* You should have received a copy of the GNU General Public License
|
|
16
|
+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
+
*/
|
|
18
|
+
import { getSharedRedis } from '../../infrastructure/redis/connection.js';
|
|
19
|
+
import type { Redis } from 'ioredis';
|
|
20
|
+
/** Memory entry structure */
|
|
21
|
+
export interface ProjectMemory {
|
|
22
|
+
name: string;
|
|
23
|
+
projectId: string;
|
|
24
|
+
content: string;
|
|
25
|
+
createdAt: number;
|
|
26
|
+
updatedAt: number;
|
|
27
|
+
tags: string[];
|
|
28
|
+
}
|
|
29
|
+
/** Checkpoint entry structure */
|
|
30
|
+
export interface Checkpoint {
|
|
31
|
+
name: string;
|
|
32
|
+
projectId: string;
|
|
33
|
+
content: string;
|
|
34
|
+
createdAt: number;
|
|
35
|
+
updatedAt: number;
|
|
36
|
+
tags: string[];
|
|
37
|
+
}
|
|
38
|
+
/** Redis key prefixes */
|
|
39
|
+
export declare const MEMORY_PREFIX = "mcp:memory:";
|
|
40
|
+
export declare const MEMORY_INDEX_PREFIX = "mcp:memory:index:";
|
|
41
|
+
export declare const CHECKPOINT_PREFIX = "mcp:checkpoint:";
|
|
42
|
+
export declare const CHECKPOINT_INDEX_PREFIX = "mcp:checkpoint:index:";
|
|
43
|
+
/** Maximum content size: 1MB */
|
|
44
|
+
export declare const MAX_CONTENT_SIZE: number;
|
|
45
|
+
/** Default TTL: 30 days in seconds */
|
|
46
|
+
export declare const DEFAULT_MEMORY_TTL: number;
|
|
47
|
+
/** Default checkpoint TTL: 7 days in seconds */
|
|
48
|
+
export declare const DEFAULT_CHECKPOINT_TTL: number;
|
|
49
|
+
/** Shared Redis getter */
|
|
50
|
+
export declare const getRedis: typeof getSharedRedis;
|
|
51
|
+
/**
|
|
52
|
+
* Generate a unique project identifier from current working directory.
|
|
53
|
+
* Creates a SHA-256 hash of the CWD, truncated to 16 characters.
|
|
54
|
+
*/
|
|
55
|
+
export declare function getProjectId(): string;
|
|
56
|
+
/**
|
|
57
|
+
* Retrieve the original creation timestamp of an existing entry.
|
|
58
|
+
* Used when overwriting to preserve the original createdAt.
|
|
59
|
+
*/
|
|
60
|
+
export declare function getExistingCreatedAt(client: Redis, key: string): Promise<number | null>;
|
|
61
|
+
//# sourceMappingURL=shared.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../../src/tools/memory/shared.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AASH,OAAO,EAAE,cAAc,EAAE,MAAM,0CAA0C,CAAC;AAC1E,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAErC,6BAA6B;AAC7B,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,iCAAiC;AACjC,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,yBAAyB;AACzB,eAAO,MAAM,aAAa,gBAAgB,CAAC;AAC3C,eAAO,MAAM,mBAAmB,sBAAsB,CAAC;AACvD,eAAO,MAAM,iBAAiB,oBAAoB,CAAC;AACnD,eAAO,MAAM,uBAAuB,0BAA0B,CAAC;AAE/D,gCAAgC;AAChC,eAAO,MAAM,gBAAgB,QAAc,CAAC;AAE5C,sCAAsC;AACtC,eAAO,MAAM,kBAAkB,QAAoB,CAAC;AAEpD,gDAAgD;AAChD,eAAO,MAAM,sBAAsB,QAAmB,CAAC;AAEvD,0BAA0B;AAC1B,eAAO,MAAM,QAAQ,uBAAiB,CAAC;AAEvC;;;GAGG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAGrC;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAW7F"}
|