claude-conversation-memory-mcp 0.1.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/LICENSE +21 -0
- package/README.md +223 -0
- package/dist/ConversationMemory.d.ts +80 -0
- package/dist/ConversationMemory.d.ts.map +1 -0
- package/dist/ConversationMemory.js +203 -0
- package/dist/ConversationMemory.js.map +1 -0
- package/dist/documentation/CodeAnalyzer.d.ts +29 -0
- package/dist/documentation/CodeAnalyzer.d.ts.map +1 -0
- package/dist/documentation/CodeAnalyzer.js +122 -0
- package/dist/documentation/CodeAnalyzer.js.map +1 -0
- package/dist/documentation/ConversationAnalyzer.d.ts +19 -0
- package/dist/documentation/ConversationAnalyzer.d.ts.map +1 -0
- package/dist/documentation/ConversationAnalyzer.js +156 -0
- package/dist/documentation/ConversationAnalyzer.js.map +1 -0
- package/dist/documentation/CrossReferencer.d.ts +67 -0
- package/dist/documentation/CrossReferencer.d.ts.map +1 -0
- package/dist/documentation/CrossReferencer.js +247 -0
- package/dist/documentation/CrossReferencer.js.map +1 -0
- package/dist/documentation/DocumentationGenerator.d.ts +22 -0
- package/dist/documentation/DocumentationGenerator.d.ts.map +1 -0
- package/dist/documentation/DocumentationGenerator.js +57 -0
- package/dist/documentation/DocumentationGenerator.js.map +1 -0
- package/dist/documentation/MarkdownFormatter.d.ts +26 -0
- package/dist/documentation/MarkdownFormatter.d.ts.map +1 -0
- package/dist/documentation/MarkdownFormatter.js +301 -0
- package/dist/documentation/MarkdownFormatter.js.map +1 -0
- package/dist/documentation/types.d.ts +176 -0
- package/dist/documentation/types.d.ts.map +1 -0
- package/dist/documentation/types.js +5 -0
- package/dist/documentation/types.js.map +1 -0
- package/dist/embeddings/EmbeddingConfig.d.ts +39 -0
- package/dist/embeddings/EmbeddingConfig.d.ts.map +1 -0
- package/dist/embeddings/EmbeddingConfig.js +132 -0
- package/dist/embeddings/EmbeddingConfig.js.map +1 -0
- package/dist/embeddings/EmbeddingGenerator.d.ts +45 -0
- package/dist/embeddings/EmbeddingGenerator.d.ts.map +1 -0
- package/dist/embeddings/EmbeddingGenerator.js +129 -0
- package/dist/embeddings/EmbeddingGenerator.js.map +1 -0
- package/dist/embeddings/EmbeddingProvider.d.ts +34 -0
- package/dist/embeddings/EmbeddingProvider.d.ts.map +1 -0
- package/dist/embeddings/EmbeddingProvider.js +6 -0
- package/dist/embeddings/EmbeddingProvider.js.map +1 -0
- package/dist/embeddings/VectorStore.d.ts +75 -0
- package/dist/embeddings/VectorStore.d.ts.map +1 -0
- package/dist/embeddings/VectorStore.js +220 -0
- package/dist/embeddings/VectorStore.js.map +1 -0
- package/dist/embeddings/providers/OllamaEmbeddings.d.ts +38 -0
- package/dist/embeddings/providers/OllamaEmbeddings.d.ts.map +1 -0
- package/dist/embeddings/providers/OllamaEmbeddings.js +132 -0
- package/dist/embeddings/providers/OllamaEmbeddings.js.map +1 -0
- package/dist/embeddings/providers/OpenAIEmbeddings.d.ts +40 -0
- package/dist/embeddings/providers/OpenAIEmbeddings.d.ts.map +1 -0
- package/dist/embeddings/providers/OpenAIEmbeddings.js +128 -0
- package/dist/embeddings/providers/OpenAIEmbeddings.js.map +1 -0
- package/dist/embeddings/providers/TransformersEmbeddings.d.ts +38 -0
- package/dist/embeddings/providers/TransformersEmbeddings.d.ts.map +1 -0
- package/dist/embeddings/providers/TransformersEmbeddings.js +114 -0
- package/dist/embeddings/providers/TransformersEmbeddings.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +127 -0
- package/dist/index.js.map +1 -0
- package/dist/parsers/ConversationParser.d.ts +138 -0
- package/dist/parsers/ConversationParser.d.ts.map +1 -0
- package/dist/parsers/ConversationParser.js +325 -0
- package/dist/parsers/ConversationParser.js.map +1 -0
- package/dist/parsers/DecisionExtractor.d.ts +76 -0
- package/dist/parsers/DecisionExtractor.d.ts.map +1 -0
- package/dist/parsers/DecisionExtractor.js +305 -0
- package/dist/parsers/DecisionExtractor.js.map +1 -0
- package/dist/parsers/GitIntegrator.d.ts +71 -0
- package/dist/parsers/GitIntegrator.d.ts.map +1 -0
- package/dist/parsers/GitIntegrator.js +283 -0
- package/dist/parsers/GitIntegrator.js.map +1 -0
- package/dist/parsers/MistakeExtractor.d.ts +86 -0
- package/dist/parsers/MistakeExtractor.d.ts.map +1 -0
- package/dist/parsers/MistakeExtractor.js +341 -0
- package/dist/parsers/MistakeExtractor.js.map +1 -0
- package/dist/parsers/RequirementsExtractor.d.ts +70 -0
- package/dist/parsers/RequirementsExtractor.d.ts.map +1 -0
- package/dist/parsers/RequirementsExtractor.js +252 -0
- package/dist/parsers/RequirementsExtractor.js.map +1 -0
- package/dist/search/SemanticSearch.d.ts +90 -0
- package/dist/search/SemanticSearch.d.ts.map +1 -0
- package/dist/search/SemanticSearch.js +352 -0
- package/dist/search/SemanticSearch.js.map +1 -0
- package/dist/storage/ConversationStorage.d.ts +53 -0
- package/dist/storage/ConversationStorage.d.ts.map +1 -0
- package/dist/storage/ConversationStorage.js +249 -0
- package/dist/storage/ConversationStorage.js.map +1 -0
- package/dist/storage/SQLiteManager.d.ts +88 -0
- package/dist/storage/SQLiteManager.d.ts.map +1 -0
- package/dist/storage/SQLiteManager.js +281 -0
- package/dist/storage/SQLiteManager.js.map +1 -0
- package/dist/storage/migrations.d.ts +54 -0
- package/dist/storage/migrations.d.ts.map +1 -0
- package/dist/storage/migrations.js +153 -0
- package/dist/storage/migrations.js.map +1 -0
- package/dist/storage/schema.sql +321 -0
- package/dist/tools/ToolDefinitions.d.ts +265 -0
- package/dist/tools/ToolDefinitions.d.ts.map +1 -0
- package/dist/tools/ToolDefinitions.js +261 -0
- package/dist/tools/ToolDefinitions.js.map +1 -0
- package/dist/tools/ToolHandlers.d.ts +56 -0
- package/dist/tools/ToolHandlers.d.ts.map +1 -0
- package/dist/tools/ToolHandlers.js +431 -0
- package/dist/tools/ToolHandlers.js.map +1 -0
- package/dist/types/ToolTypes.d.ts +333 -0
- package/dist/types/ToolTypes.d.ts.map +1 -0
- package/dist/types/ToolTypes.js +6 -0
- package/dist/types/ToolTypes.js.map +1 -0
- package/dist/utils/sanitization.d.ts +35 -0
- package/dist/utils/sanitization.d.ts.map +1 -0
- package/dist/utils/sanitization.js +97 -0
- package/dist/utils/sanitization.js.map +1 -0
- package/package.json +87 -0
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mistake Extractor
|
|
3
|
+
* Identifies errors and how they were corrected to prevent repetition
|
|
4
|
+
*/
|
|
5
|
+
import { nanoid } from "nanoid";
|
|
6
|
+
export class MistakeExtractor {
|
|
7
|
+
// User correction indicators
|
|
8
|
+
CORRECTION_INDICATORS = [
|
|
9
|
+
/^no[,\s]/i,
|
|
10
|
+
/that'?s?\s+(?:wrong|incorrect|not right|a mistake)/i,
|
|
11
|
+
/(?:you|that)\s+(?:made|caused|introduced)\s+(?:a|an)\s+(?:error|bug|mistake)/i,
|
|
12
|
+
/don't\s+do\s+(?:that|this)/i,
|
|
13
|
+
/(?:should not|shouldn't|must not|mustn't)\s+(?:have\s+)?(?:done|used)/i,
|
|
14
|
+
/(?:fix|correct|change)\s+(?:that|this)/i,
|
|
15
|
+
];
|
|
16
|
+
// Error indicators in assistant messages
|
|
17
|
+
ERROR_INDICATORS = [
|
|
18
|
+
/error:/i,
|
|
19
|
+
/failed:/i,
|
|
20
|
+
/exception:/i,
|
|
21
|
+
/(?:this|that)\s+(?:didn't|doesn't|won't)\s+work/i,
|
|
22
|
+
/(?:broke|breaking|broken)/i,
|
|
23
|
+
/(?:issue|problem|bug)/i,
|
|
24
|
+
];
|
|
25
|
+
// Mistake type patterns
|
|
26
|
+
MISTAKE_PATTERNS = {
|
|
27
|
+
logic_error: [/logic\s+error/i, /incorrect\s+logic/i, /wrong\s+condition/i],
|
|
28
|
+
wrong_approach: [
|
|
29
|
+
/wrong\s+approach/i,
|
|
30
|
+
/better\s+way/i,
|
|
31
|
+
/should\s+(?:have\s+)?use(?:d)?/i,
|
|
32
|
+
],
|
|
33
|
+
misunderstanding: [
|
|
34
|
+
/misunderstood/i,
|
|
35
|
+
/(?:didn't|don't)\s+understand/i,
|
|
36
|
+
/confused\s+about/i,
|
|
37
|
+
],
|
|
38
|
+
syntax_error: [/syntax\s+error/i, /parse\s+error/i, /invalid\s+syntax/i],
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Extract mistakes from messages and tool results
|
|
42
|
+
*/
|
|
43
|
+
extractMistakes(messages, toolResults) {
|
|
44
|
+
const mistakes = [];
|
|
45
|
+
// Extract from tool errors
|
|
46
|
+
const toolErrors = this.extractToolErrors(toolResults, messages);
|
|
47
|
+
mistakes.push(...toolErrors);
|
|
48
|
+
// Extract from user corrections
|
|
49
|
+
const userCorrections = this.extractUserCorrections(messages);
|
|
50
|
+
mistakes.push(...userCorrections);
|
|
51
|
+
// Extract from error discussions
|
|
52
|
+
const errorDiscussions = this.extractErrorDiscussions(messages);
|
|
53
|
+
mistakes.push(...errorDiscussions);
|
|
54
|
+
return this.deduplicateMistakes(mistakes);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Extract mistakes from tool execution errors
|
|
58
|
+
*/
|
|
59
|
+
extractToolErrors(toolResults, messages) {
|
|
60
|
+
const mistakes = [];
|
|
61
|
+
for (const result of toolResults) {
|
|
62
|
+
if (!result.is_error) {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
const message = messages.find((m) => m.id === result.message_id);
|
|
66
|
+
if (!message) {
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
// Extract error details
|
|
70
|
+
const errorContent = result.stderr || result.content || "";
|
|
71
|
+
const mistakeType = this.classifyMistakeType(errorContent);
|
|
72
|
+
mistakes.push({
|
|
73
|
+
id: nanoid(),
|
|
74
|
+
conversation_id: message.conversation_id,
|
|
75
|
+
message_id: message.id,
|
|
76
|
+
mistake_type: mistakeType || "tool_error",
|
|
77
|
+
what_went_wrong: this.summarizeError(errorContent),
|
|
78
|
+
correction: this.findCorrection(message, messages),
|
|
79
|
+
files_affected: this.extractFilesFromError(errorContent),
|
|
80
|
+
timestamp: result.timestamp,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
return mistakes;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Extract mistakes from user corrections
|
|
87
|
+
*/
|
|
88
|
+
extractUserCorrections(messages) {
|
|
89
|
+
const mistakes = [];
|
|
90
|
+
for (let i = 0; i < messages.length; i++) {
|
|
91
|
+
const message = messages[i];
|
|
92
|
+
if (message.role !== "user" || !message.content) {
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
const content = message.content;
|
|
96
|
+
// Check if this is a correction
|
|
97
|
+
const isCorrection = this.CORRECTION_INDICATORS.some((pattern) => pattern.test(content));
|
|
98
|
+
if (!isCorrection) {
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
// Find the previous assistant message
|
|
102
|
+
const previousAssistant = this.findPreviousAssistantMessage(messages, i);
|
|
103
|
+
if (!previousAssistant) {
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
const mistakeType = this.classifyMistakeType(message.content);
|
|
107
|
+
mistakes.push({
|
|
108
|
+
id: nanoid(),
|
|
109
|
+
conversation_id: message.conversation_id,
|
|
110
|
+
message_id: previousAssistant.id,
|
|
111
|
+
mistake_type: mistakeType || "misunderstanding",
|
|
112
|
+
what_went_wrong: this.extractWhatWentWrong(message.content),
|
|
113
|
+
correction: this.extractCorrection(message.content),
|
|
114
|
+
user_correction_message: message.content,
|
|
115
|
+
files_affected: this.extractFilesFromMessage(message),
|
|
116
|
+
timestamp: message.timestamp,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
return mistakes;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Extract mistakes from error discussions in messages
|
|
123
|
+
*/
|
|
124
|
+
extractErrorDiscussions(messages) {
|
|
125
|
+
const mistakes = [];
|
|
126
|
+
for (const message of messages) {
|
|
127
|
+
if (message.role !== "assistant" || !message.content) {
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
const content = message.content;
|
|
131
|
+
// Check if message discusses an error
|
|
132
|
+
const hasErrorDiscussion = this.ERROR_INDICATORS.some((pattern) => pattern.test(content));
|
|
133
|
+
if (!hasErrorDiscussion) {
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
// Extract error discussion
|
|
137
|
+
const errorText = this.extractErrorDiscussion(message.content);
|
|
138
|
+
if (!errorText) {
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
const mistakeType = this.classifyMistakeType(errorText);
|
|
142
|
+
mistakes.push({
|
|
143
|
+
id: nanoid(),
|
|
144
|
+
conversation_id: message.conversation_id,
|
|
145
|
+
message_id: message.id,
|
|
146
|
+
mistake_type: mistakeType || "logic_error",
|
|
147
|
+
what_went_wrong: errorText,
|
|
148
|
+
correction: this.extractSolutionFromSameMessage(message.content),
|
|
149
|
+
files_affected: this.extractFilesFromMessage(message),
|
|
150
|
+
timestamp: message.timestamp,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
return mistakes;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Classify the type of mistake
|
|
157
|
+
*/
|
|
158
|
+
classifyMistakeType(text) {
|
|
159
|
+
for (const [type, patterns] of Object.entries(this.MISTAKE_PATTERNS)) {
|
|
160
|
+
for (const pattern of patterns) {
|
|
161
|
+
if (pattern.test(text)) {
|
|
162
|
+
return type;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Summarize error message
|
|
170
|
+
*/
|
|
171
|
+
summarizeError(errorText) {
|
|
172
|
+
// Take first line or first 200 characters
|
|
173
|
+
const firstLine = errorText.split("\n")[0];
|
|
174
|
+
return firstLine.length > 200
|
|
175
|
+
? firstLine.substring(0, 200) + "..."
|
|
176
|
+
: firstLine;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Find correction in subsequent messages
|
|
180
|
+
*/
|
|
181
|
+
findCorrection(errorMessage, allMessages) {
|
|
182
|
+
const index = allMessages.findIndex((m) => m.id === errorMessage.id);
|
|
183
|
+
if (index === -1) {
|
|
184
|
+
return undefined;
|
|
185
|
+
}
|
|
186
|
+
// Look at next few messages for a fix
|
|
187
|
+
const nextMessages = allMessages.slice(index + 1, index + 5);
|
|
188
|
+
for (const msg of nextMessages) {
|
|
189
|
+
if (msg.role === "assistant" && msg.content) {
|
|
190
|
+
// Look for fix indicators
|
|
191
|
+
if (/(?:fixed|resolved|corrected|solved)/i.test(msg.content)) {
|
|
192
|
+
return msg.content.substring(0, 500);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return undefined;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Extract files mentioned in error
|
|
200
|
+
*/
|
|
201
|
+
extractFilesFromError(errorText) {
|
|
202
|
+
const files = [];
|
|
203
|
+
// Common file path patterns
|
|
204
|
+
const filePathPattern = /(?:\/|\.\/|\.\.\/)?(?:[\w-]+\/)*[\w-]+\.[\w]+/g;
|
|
205
|
+
const matches = errorText.match(filePathPattern);
|
|
206
|
+
if (matches) {
|
|
207
|
+
files.push(...matches);
|
|
208
|
+
}
|
|
209
|
+
return [...new Set(files)];
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Extract files from message metadata
|
|
213
|
+
*/
|
|
214
|
+
extractFilesFromMessage(message) {
|
|
215
|
+
const files = [];
|
|
216
|
+
if (message.metadata) {
|
|
217
|
+
const metadataStr = JSON.stringify(message.metadata);
|
|
218
|
+
const filePathPattern = /(?:\/[\w-]+)+\.[\w]+/g;
|
|
219
|
+
const matches = metadataStr.match(filePathPattern);
|
|
220
|
+
if (matches) {
|
|
221
|
+
files.push(...matches);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return [...new Set(files)];
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Find previous assistant message
|
|
228
|
+
*/
|
|
229
|
+
findPreviousAssistantMessage(messages, currentIndex) {
|
|
230
|
+
for (let i = currentIndex - 1; i >= 0; i--) {
|
|
231
|
+
if (messages[i].role === "assistant") {
|
|
232
|
+
return messages[i];
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return undefined;
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Extract what went wrong from correction message
|
|
239
|
+
*/
|
|
240
|
+
extractWhatWentWrong(correctionText) {
|
|
241
|
+
// Remove correction indicators
|
|
242
|
+
let cleaned = correctionText;
|
|
243
|
+
for (const pattern of this.CORRECTION_INDICATORS) {
|
|
244
|
+
cleaned = cleaned.replace(pattern, "");
|
|
245
|
+
}
|
|
246
|
+
// Take first sentence or up to 300 characters
|
|
247
|
+
const sentences = cleaned.split(/\.|!|\?/);
|
|
248
|
+
const firstSentence = sentences[0]?.trim();
|
|
249
|
+
return firstSentence && firstSentence.length > 0
|
|
250
|
+
? firstSentence.substring(0, 300)
|
|
251
|
+
: cleaned.substring(0, 300);
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Extract correction from user message
|
|
255
|
+
*/
|
|
256
|
+
extractCorrection(correctionText) {
|
|
257
|
+
// Look for "instead" or "should" patterns
|
|
258
|
+
const insteadMatch = correctionText.match(/instead[,\s]+(.+?)(?:\.|$)/i);
|
|
259
|
+
if (insteadMatch) {
|
|
260
|
+
return insteadMatch[1].trim();
|
|
261
|
+
}
|
|
262
|
+
const shouldMatch = correctionText.match(/should\s+(?:have\s+)?(.+?)(?:\.|$)/i);
|
|
263
|
+
if (shouldMatch) {
|
|
264
|
+
return shouldMatch[1].trim();
|
|
265
|
+
}
|
|
266
|
+
return undefined;
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Extract error discussion from message
|
|
270
|
+
*/
|
|
271
|
+
extractErrorDiscussion(content) {
|
|
272
|
+
// Find sentences containing error indicators
|
|
273
|
+
const sentences = content.split(/\.|!|\?/);
|
|
274
|
+
for (const sentence of sentences) {
|
|
275
|
+
if (this.ERROR_INDICATORS.some((pattern) => pattern.test(sentence))) {
|
|
276
|
+
return sentence.trim();
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return undefined;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Extract solution from same message that discusses error
|
|
283
|
+
*/
|
|
284
|
+
extractSolutionFromSameMessage(content) {
|
|
285
|
+
// Look for solution indicators
|
|
286
|
+
const solutionPattern = /(?:to fix|solution|resolved by|corrected by|fixed by)\s+(.+?)(?:\.|$)/i;
|
|
287
|
+
const match = content.match(solutionPattern);
|
|
288
|
+
return match?.[1]?.trim();
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Deduplicate similar mistakes
|
|
292
|
+
*/
|
|
293
|
+
deduplicateMistakes(mistakes) {
|
|
294
|
+
const unique = [];
|
|
295
|
+
const seen = new Set();
|
|
296
|
+
for (const mistake of mistakes) {
|
|
297
|
+
// Create signature
|
|
298
|
+
const signature = `${mistake.what_went_wrong.substring(0, 100)}_${mistake.timestamp}`;
|
|
299
|
+
if (!seen.has(signature)) {
|
|
300
|
+
seen.add(signature);
|
|
301
|
+
unique.push(mistake);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
return unique;
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Score mistake severity (for prioritization)
|
|
308
|
+
*/
|
|
309
|
+
scoreMistakeSeverity(mistake) {
|
|
310
|
+
let score = 0;
|
|
311
|
+
// Has correction
|
|
312
|
+
if (mistake.correction) {
|
|
313
|
+
score += 2;
|
|
314
|
+
}
|
|
315
|
+
// User explicitly corrected
|
|
316
|
+
if (mistake.user_correction_message) {
|
|
317
|
+
score += 3;
|
|
318
|
+
}
|
|
319
|
+
// Affects files
|
|
320
|
+
if (mistake.files_affected.length > 0) {
|
|
321
|
+
score += 2;
|
|
322
|
+
}
|
|
323
|
+
// Type-based severity
|
|
324
|
+
switch (mistake.mistake_type) {
|
|
325
|
+
case "logic_error":
|
|
326
|
+
score += 3;
|
|
327
|
+
break;
|
|
328
|
+
case "wrong_approach":
|
|
329
|
+
score += 2;
|
|
330
|
+
break;
|
|
331
|
+
case "syntax_error":
|
|
332
|
+
score += 1;
|
|
333
|
+
break;
|
|
334
|
+
case "tool_error":
|
|
335
|
+
score += 1;
|
|
336
|
+
break;
|
|
337
|
+
}
|
|
338
|
+
return score;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
//# sourceMappingURL=MistakeExtractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MistakeExtractor.js","sourceRoot":"","sources":["../../src/parsers/MistakeExtractor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Requirements and Validations Extractor
|
|
3
|
+
* Tracks constraints, dependencies, and testing context
|
|
4
|
+
*/
|
|
5
|
+
import type { Message, ToolUse, ToolResult } from "./ConversationParser.js";
|
|
6
|
+
export interface Requirement {
|
|
7
|
+
id: string;
|
|
8
|
+
type: "dependency" | "performance" | "compatibility" | "business";
|
|
9
|
+
description: string;
|
|
10
|
+
rationale?: string;
|
|
11
|
+
affects_components: string[];
|
|
12
|
+
conversation_id: string;
|
|
13
|
+
message_id: string;
|
|
14
|
+
timestamp: number;
|
|
15
|
+
}
|
|
16
|
+
export interface Validation {
|
|
17
|
+
id: string;
|
|
18
|
+
conversation_id: string;
|
|
19
|
+
what_was_tested: string;
|
|
20
|
+
test_command?: string;
|
|
21
|
+
result: "passed" | "failed" | "error";
|
|
22
|
+
performance_data?: Record<string, unknown>;
|
|
23
|
+
files_tested: string[];
|
|
24
|
+
timestamp: number;
|
|
25
|
+
}
|
|
26
|
+
export declare class RequirementsExtractor {
|
|
27
|
+
private readonly REQUIREMENT_PATTERNS;
|
|
28
|
+
private readonly TEST_PATTERNS;
|
|
29
|
+
/**
|
|
30
|
+
* Extract requirements from messages
|
|
31
|
+
*/
|
|
32
|
+
extractRequirements(messages: Message[]): Requirement[];
|
|
33
|
+
/**
|
|
34
|
+
* Extract validations from tool uses
|
|
35
|
+
*/
|
|
36
|
+
extractValidations(toolUses: ToolUse[], toolResults: ToolResult[], messages: Message[]): Validation[];
|
|
37
|
+
/**
|
|
38
|
+
* Parse a requirement from pattern match
|
|
39
|
+
*/
|
|
40
|
+
private parseRequirement;
|
|
41
|
+
/**
|
|
42
|
+
* Extract rationale from requirement text
|
|
43
|
+
*/
|
|
44
|
+
private extractRationale;
|
|
45
|
+
/**
|
|
46
|
+
* Extract affected components from message metadata
|
|
47
|
+
*/
|
|
48
|
+
private extractAffectedComponents;
|
|
49
|
+
/**
|
|
50
|
+
* Extract what was tested from command and result
|
|
51
|
+
*/
|
|
52
|
+
private extractWhatWasTested;
|
|
53
|
+
/**
|
|
54
|
+
* Determine test result from tool result
|
|
55
|
+
*/
|
|
56
|
+
private determineTestResult;
|
|
57
|
+
/**
|
|
58
|
+
* Extract performance data from test results
|
|
59
|
+
*/
|
|
60
|
+
private extractPerformanceData;
|
|
61
|
+
/**
|
|
62
|
+
* Extract files that were tested
|
|
63
|
+
*/
|
|
64
|
+
private extractTestedFiles;
|
|
65
|
+
/**
|
|
66
|
+
* Deduplicate similar requirements
|
|
67
|
+
*/
|
|
68
|
+
private deduplicateRequirements;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=RequirementsExtractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RequirementsExtractor.d.ts","sourceRoot":"","sources":["../../src/parsers/RequirementsExtractor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAE5E,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,YAAY,GAAG,aAAa,GAAG,eAAe,GAAG,UAAU,CAAC;IAClE,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;IACtC,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC3C,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,qBAAqB;IAEhC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAmBnC;IAGF,OAAO,CAAC,QAAQ,CAAC,aAAa,CAQ5B;IAEF;;OAEG;IACH,mBAAmB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,WAAW,EAAE;IA8BvD;;OAEG;IACH,kBAAkB,CAChB,QAAQ,EAAE,OAAO,EAAE,EACnB,WAAW,EAAE,UAAU,EAAE,EACzB,QAAQ,EAAE,OAAO,EAAE,GAClB,UAAU,EAAE;IAuCf;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAgCxB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAuBxB;;OAEG;IACH,OAAO,CAAC,yBAAyB;IA0BjC;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAqB5B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IA6B3B;;OAEG;IACH,OAAO,CAAC,sBAAsB;IA6B9B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAe1B;;OAEG;IACH,OAAO,CAAC,uBAAuB;CAchC"}
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Requirements and Validations Extractor
|
|
3
|
+
* Tracks constraints, dependencies, and testing context
|
|
4
|
+
*/
|
|
5
|
+
import { nanoid } from "nanoid";
|
|
6
|
+
export class RequirementsExtractor {
|
|
7
|
+
// Requirement indicators
|
|
8
|
+
REQUIREMENT_PATTERNS = {
|
|
9
|
+
dependency: [
|
|
10
|
+
/(?:need|require|must use|depends on)\s+(.+?)\s+(?:library|package|module|dependency)/gi,
|
|
11
|
+
/(?:install|add)\s+(.+?)\s+(?:for|to)/gi,
|
|
12
|
+
],
|
|
13
|
+
performance: [
|
|
14
|
+
/(?:must|should|need to)\s+(?:be|run)\s+(?:faster|slower|within|under)\s+(.+)/gi,
|
|
15
|
+
/response time\s+(?:must|should)\s+(?:be\s+)?(?:under|less than|within)\s+(.+)/gi,
|
|
16
|
+
/(?:latency|throughput|performance)\s+requirement:\s*(.+)/gi,
|
|
17
|
+
],
|
|
18
|
+
compatibility: [
|
|
19
|
+
/(?:must|should|need to)\s+(?:support|work with|be compatible with)\s+(.+)/gi,
|
|
20
|
+
/(?:requires?|needs?)\s+(.+?)\s+(?:version|or higher|or later)/gi,
|
|
21
|
+
],
|
|
22
|
+
business: [
|
|
23
|
+
/business requirement:\s*(.+)/gi,
|
|
24
|
+
/(?:must|cannot|can't)\s+(?:exceed|violate|break)\s+(.+)/gi,
|
|
25
|
+
/(?:constraint|limitation):\s*(.+)/gi,
|
|
26
|
+
],
|
|
27
|
+
};
|
|
28
|
+
// Test/validation indicators
|
|
29
|
+
TEST_PATTERNS = [
|
|
30
|
+
/(?:npm|yarn|pnpm)\s+test/,
|
|
31
|
+
/(?:npm|yarn|pnpm)\s+run\s+test/,
|
|
32
|
+
/pytest/,
|
|
33
|
+
/jest/,
|
|
34
|
+
/mocha/,
|
|
35
|
+
/cargo\s+test/,
|
|
36
|
+
/go\s+test/,
|
|
37
|
+
];
|
|
38
|
+
/**
|
|
39
|
+
* Extract requirements from messages
|
|
40
|
+
*/
|
|
41
|
+
extractRequirements(messages) {
|
|
42
|
+
const requirements = [];
|
|
43
|
+
for (const message of messages) {
|
|
44
|
+
if (!message.content) {
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
// Check each requirement type
|
|
48
|
+
for (const [type, patterns] of Object.entries(this.REQUIREMENT_PATTERNS)) {
|
|
49
|
+
for (const pattern of patterns) {
|
|
50
|
+
const matches = Array.from(message.content.matchAll(pattern));
|
|
51
|
+
for (const match of matches) {
|
|
52
|
+
const requirement = this.parseRequirement(type, match, message);
|
|
53
|
+
if (requirement) {
|
|
54
|
+
requirements.push(requirement);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return this.deduplicateRequirements(requirements);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Extract validations from tool uses
|
|
64
|
+
*/
|
|
65
|
+
extractValidations(toolUses, toolResults, messages) {
|
|
66
|
+
const validations = [];
|
|
67
|
+
for (const toolUse of toolUses) {
|
|
68
|
+
// Check if this is a test command
|
|
69
|
+
if (toolUse.tool_name === "Bash") {
|
|
70
|
+
const command = toolUse.tool_input.command;
|
|
71
|
+
if (!command || typeof command !== "string") {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
const isTest = this.TEST_PATTERNS.some((pattern) => pattern.test(command));
|
|
75
|
+
if (isTest) {
|
|
76
|
+
// Find corresponding result
|
|
77
|
+
const result = toolResults.find((r) => r.tool_use_id === toolUse.id);
|
|
78
|
+
const message = messages.find((m) => m.id === toolUse.message_id);
|
|
79
|
+
if (result && message) {
|
|
80
|
+
validations.push({
|
|
81
|
+
id: nanoid(),
|
|
82
|
+
conversation_id: message.conversation_id,
|
|
83
|
+
what_was_tested: this.extractWhatWasTested(command, result),
|
|
84
|
+
test_command: command,
|
|
85
|
+
result: this.determineTestResult(result),
|
|
86
|
+
performance_data: this.extractPerformanceData(result),
|
|
87
|
+
files_tested: this.extractTestedFiles(result),
|
|
88
|
+
timestamp: toolUse.timestamp,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return validations;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Parse a requirement from pattern match
|
|
98
|
+
*/
|
|
99
|
+
parseRequirement(type, match, message) {
|
|
100
|
+
const description = match[1]?.trim();
|
|
101
|
+
if (!description) {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
if (!message.content) {
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
// Extract rationale from message context
|
|
108
|
+
const rationale = this.extractRationale(match[0], message.content);
|
|
109
|
+
// Extract affected components
|
|
110
|
+
const components = this.extractAffectedComponents(message);
|
|
111
|
+
return {
|
|
112
|
+
id: nanoid(),
|
|
113
|
+
type,
|
|
114
|
+
description,
|
|
115
|
+
rationale,
|
|
116
|
+
affects_components: components,
|
|
117
|
+
conversation_id: message.conversation_id,
|
|
118
|
+
message_id: message.id,
|
|
119
|
+
timestamp: message.timestamp,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Extract rationale from requirement text
|
|
124
|
+
*/
|
|
125
|
+
extractRationale(requirementText, fullContent) {
|
|
126
|
+
// Look for "because", "since", "for" explanations
|
|
127
|
+
const rationaleMatch = requirementText.match(/(?:because|since|for|due to)\s+(.+?)(?:\.|$)/i);
|
|
128
|
+
if (rationaleMatch) {
|
|
129
|
+
return rationaleMatch[1].trim();
|
|
130
|
+
}
|
|
131
|
+
// Look in surrounding context
|
|
132
|
+
const contextMatch = fullContent.match(new RegExp(`${requirementText.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}[^.]*?(?:because|since|for|due to)\\s+(.+?)(?:\\.|$)`, "i"));
|
|
133
|
+
return contextMatch?.[1]?.trim();
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Extract affected components from message metadata
|
|
137
|
+
*/
|
|
138
|
+
extractAffectedComponents(message) {
|
|
139
|
+
const components = [];
|
|
140
|
+
// Common component keywords
|
|
141
|
+
const componentKeywords = [
|
|
142
|
+
"frontend",
|
|
143
|
+
"backend",
|
|
144
|
+
"api",
|
|
145
|
+
"database",
|
|
146
|
+
"auth",
|
|
147
|
+
"ui",
|
|
148
|
+
"server",
|
|
149
|
+
"client",
|
|
150
|
+
];
|
|
151
|
+
const content = message.content?.toLowerCase() || "";
|
|
152
|
+
for (const keyword of componentKeywords) {
|
|
153
|
+
if (content.includes(keyword)) {
|
|
154
|
+
components.push(keyword);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return [...new Set(components)];
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Extract what was tested from command and result
|
|
161
|
+
*/
|
|
162
|
+
extractWhatWasTested(command, result) {
|
|
163
|
+
// Try to extract test file/suite name
|
|
164
|
+
const fileMatch = command.match(/test[/\\](.+?)(?:\s|$)/);
|
|
165
|
+
if (fileMatch) {
|
|
166
|
+
return fileMatch[1];
|
|
167
|
+
}
|
|
168
|
+
// Try to extract from result
|
|
169
|
+
const resultContent = result.stdout || result.content || "";
|
|
170
|
+
const suiteMatch = resultContent.match(/(?:Test Suite|Describe):\s*(.+)/i);
|
|
171
|
+
if (suiteMatch) {
|
|
172
|
+
return suiteMatch[1].trim();
|
|
173
|
+
}
|
|
174
|
+
// Fallback to command
|
|
175
|
+
return command;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Determine test result from tool result
|
|
179
|
+
*/
|
|
180
|
+
determineTestResult(result) {
|
|
181
|
+
if (result.is_error) {
|
|
182
|
+
return "error";
|
|
183
|
+
}
|
|
184
|
+
const output = (result.stdout || result.content || "").toLowerCase();
|
|
185
|
+
// Check for pass indicators
|
|
186
|
+
if (/(?:all tests? passed|✓|✔|success)/i.test(output) ||
|
|
187
|
+
/(?:\d+\s+passed,\s+0\s+failed)/i.test(output)) {
|
|
188
|
+
return "passed";
|
|
189
|
+
}
|
|
190
|
+
// Check for fail indicators
|
|
191
|
+
if (/(?:test failed|✗|✘|failure|failed)/i.test(output) ||
|
|
192
|
+
/(?:\d+\s+failed)/i.test(output)) {
|
|
193
|
+
return "failed";
|
|
194
|
+
}
|
|
195
|
+
// Default to passed if no errors
|
|
196
|
+
return result.is_error ? "error" : "passed";
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Extract performance data from test results
|
|
200
|
+
*/
|
|
201
|
+
extractPerformanceData(result) {
|
|
202
|
+
const output = result.stdout || result.content || "";
|
|
203
|
+
const data = {};
|
|
204
|
+
// Extract timing information
|
|
205
|
+
const timeMatch = output.match(/(\d+(?:\.\d+)?)\s*(ms|s|seconds?|milliseconds?)/i);
|
|
206
|
+
if (timeMatch) {
|
|
207
|
+
const value = parseFloat(timeMatch[1]);
|
|
208
|
+
const unit = timeMatch[2].toLowerCase();
|
|
209
|
+
data.duration_ms = unit.startsWith("s") ? value * 1000 : value;
|
|
210
|
+
}
|
|
211
|
+
// Extract test counts
|
|
212
|
+
const passedMatch = output.match(/(\d+)\s+passed/i);
|
|
213
|
+
if (passedMatch) {
|
|
214
|
+
data.tests_passed = parseInt(passedMatch[1]);
|
|
215
|
+
}
|
|
216
|
+
const failedMatch = output.match(/(\d+)\s+failed/i);
|
|
217
|
+
if (failedMatch) {
|
|
218
|
+
data.tests_failed = parseInt(failedMatch[1]);
|
|
219
|
+
}
|
|
220
|
+
return Object.keys(data).length > 0 ? data : undefined;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Extract files that were tested
|
|
224
|
+
*/
|
|
225
|
+
extractTestedFiles(result) {
|
|
226
|
+
const output = result.stdout || result.content || "";
|
|
227
|
+
const files = [];
|
|
228
|
+
// Look for file paths
|
|
229
|
+
const filePattern = /(?:PASS|FAIL|ERROR)\s+([\w/.-]+\.(?:test|spec)\.[\w]+)/gi;
|
|
230
|
+
const matches = Array.from(output.matchAll(filePattern));
|
|
231
|
+
for (const match of matches) {
|
|
232
|
+
files.push(match[1]);
|
|
233
|
+
}
|
|
234
|
+
return [...new Set(files)];
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Deduplicate similar requirements
|
|
238
|
+
*/
|
|
239
|
+
deduplicateRequirements(requirements) {
|
|
240
|
+
const unique = [];
|
|
241
|
+
const seen = new Set();
|
|
242
|
+
for (const req of requirements) {
|
|
243
|
+
const signature = `${req.type}_${req.description.substring(0, 50)}`;
|
|
244
|
+
if (!seen.has(signature)) {
|
|
245
|
+
seen.add(signature);
|
|
246
|
+
unique.push(req);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return unique;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
//# sourceMappingURL=RequirementsExtractor.js.map
|