minovative-mind-cli 2.5.2 → 2.6.1
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 +29 -26
- package/dist/commands/chat.js +2 -2
- package/dist/services/agent/inputHandler.d.ts +9 -0
- package/dist/services/agent/inputHandler.js +34 -0
- package/dist/services/agent/slashCommands.js +105 -29
- package/dist/services/agent/syntaxAgent.d.ts +40 -0
- package/dist/services/agent/syntaxAgent.js +237 -23
- package/dist/services/agent/toolLoop.js +10 -1
- package/dist/services/agent/types.d.ts +1 -0
- package/dist/services/agent-tools.d.ts +156 -1
- package/dist/services/agent-tools.js +259 -67
- package/dist/services/agent.d.ts +74 -0
- package/dist/services/agent.js +193 -31
- package/dist/services/ai.d.ts +5 -0
- package/dist/services/ai.js +80 -87
- package/dist/services/chatHistoryService.d.ts +11 -0
- package/dist/services/chatHistoryService.js +20 -1
- package/dist/services/contextAgent.d.ts +1 -1
- package/dist/services/contextAgent.js +9 -29
- package/dist/services/orchestration/investigationAgent.d.ts +2 -1
- package/dist/services/orchestration/investigationAgent.js +7 -2
- package/dist/services/orchestration/investigationOrchestrator.d.ts +1 -1
- package/dist/services/orchestration/investigationOrchestrator.js +13 -2
- package/dist/services/orchestration/orchestrator.js +21 -4
- package/dist/services/orchestration/subAgent.d.ts +2 -1
- package/dist/services/orchestration/subAgent.js +12 -6
- package/dist/utils/analysisRunner.d.ts +27 -4
- package/dist/utils/analysisRunner.js +100 -20
- package/dist/utils/config.d.ts +2 -0
- package/dist/utils/config.js +2 -0
- package/dist/utils/fuzzyMatch.d.ts +32 -0
- package/dist/utils/fuzzyMatch.js +215 -27
- package/dist/utils/localSyntaxValidator.d.ts +2 -2
- package/dist/utils/localSyntaxValidator.js +280 -81
- package/dist/utils/performanceAuditor.d.ts +2 -7
- package/dist/utils/performanceAuditor.js +541 -89
- package/dist/utils/projectStorage.js +9 -0
- package/dist/utils/systemPrompts.d.ts +3 -2
- package/dist/utils/systemPrompts.js +29 -5
- package/oclif.manifest.json +2 -2
- package/package.json +1 -1
|
@@ -1,103 +1,302 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
|
+
/**
|
|
3
|
+
* Checks if file content contains placeholder comments indicating AI code truncation.
|
|
4
|
+
*/
|
|
5
|
+
function isTruncated(content) {
|
|
6
|
+
const lines = content.split('\n');
|
|
7
|
+
const truncPattern = '^(/\\/|/\\*)\\s*(\\.\\.\\.\\s*$|\\.\\.\\.\\s*\\*\\/$|\\[?\\s*\\.\\.\\.\\s*(existing\\s*code|rest\\s*of\\s*(the\\s*)?(file|code|content|implementation)|remaining|omitted|unchanged))';
|
|
8
|
+
const truncRegex = new RegExp(truncPattern, 'i');
|
|
9
|
+
for (const line of lines) {
|
|
10
|
+
const trimmed = line.trim();
|
|
11
|
+
if (!trimmed)
|
|
12
|
+
continue;
|
|
13
|
+
if (truncRegex.test(trimmed)) {
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
2
19
|
export function localValidate(filePath, content) {
|
|
3
20
|
const ext = path.extname(filePath).toLowerCase();
|
|
4
|
-
// Check
|
|
5
|
-
if (
|
|
21
|
+
// 1. Check JSON files using native JSON parser
|
|
22
|
+
if (ext === '.json') {
|
|
23
|
+
try {
|
|
24
|
+
JSON.parse(content);
|
|
25
|
+
return { isValid: true };
|
|
26
|
+
}
|
|
27
|
+
catch (err) {
|
|
28
|
+
return {
|
|
29
|
+
isValid: false,
|
|
30
|
+
error: 'Invalid JSON syntax: ' + err.message,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
// 2. Check for truncation markers
|
|
35
|
+
if (isTruncated(content)) {
|
|
6
36
|
return {
|
|
7
37
|
isValid: false,
|
|
8
38
|
error: 'File appears to be truncated (contains placeholder comments)',
|
|
9
39
|
};
|
|
10
40
|
}
|
|
11
|
-
// C-style languages
|
|
12
41
|
const C_STYLE_EXTS = [
|
|
13
|
-
'.ts',
|
|
14
|
-
'.
|
|
42
|
+
'.ts',
|
|
43
|
+
'.js',
|
|
44
|
+
'.tsx',
|
|
45
|
+
'.jsx',
|
|
46
|
+
'.css',
|
|
47
|
+
'.html',
|
|
48
|
+
'.rs',
|
|
49
|
+
'.go',
|
|
50
|
+
'.java',
|
|
51
|
+
'.cpp',
|
|
52
|
+
'.c',
|
|
53
|
+
'.h',
|
|
54
|
+
'.cs',
|
|
55
|
+
'.php',
|
|
56
|
+
'.swift',
|
|
15
57
|
];
|
|
16
|
-
// Hash-style languages (only validate [] and ())
|
|
17
58
|
const HASH_STYLE_EXTS = ['.py', '.rb', '.sh', '.yaml', '.yml'];
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
59
|
+
const isJsTs = ['.js', '.jsx', '.ts', '.tsx', '.mjs', '.cjs'].includes(ext);
|
|
60
|
+
const isCStyle = C_STYLE_EXTS.includes(ext);
|
|
61
|
+
const isHashStyle = HASH_STYLE_EXTS.includes(ext);
|
|
62
|
+
if (!isCStyle && !isHashStyle && !isJsTs) {
|
|
63
|
+
return { isValid: true };
|
|
64
|
+
}
|
|
65
|
+
const stack = [];
|
|
66
|
+
const pairs = {
|
|
67
|
+
'{': '}',
|
|
68
|
+
'[': ']',
|
|
69
|
+
'(': ')',
|
|
70
|
+
'${': '}',
|
|
71
|
+
};
|
|
72
|
+
let inSingleComment = false;
|
|
73
|
+
let inMultiComment = false;
|
|
74
|
+
let inString = false;
|
|
75
|
+
let stringChar = '';
|
|
76
|
+
let inTemplate = false;
|
|
77
|
+
let inRegex = false;
|
|
78
|
+
let inRegexCharClass = false;
|
|
79
|
+
// Track tokens to determine if '/' can start a regex literal
|
|
80
|
+
let lastToken = '';
|
|
81
|
+
let currentWord = '';
|
|
82
|
+
const EXPR_KEYWORDS = new Set([
|
|
83
|
+
'return',
|
|
84
|
+
'case',
|
|
85
|
+
'typeof',
|
|
86
|
+
'void',
|
|
87
|
+
'delete',
|
|
88
|
+
'yield',
|
|
89
|
+
'await',
|
|
90
|
+
'throw',
|
|
91
|
+
'instanceof',
|
|
92
|
+
'in',
|
|
93
|
+
'of',
|
|
94
|
+
'new',
|
|
95
|
+
'else',
|
|
96
|
+
'do',
|
|
97
|
+
'tok',
|
|
98
|
+
]);
|
|
99
|
+
const EXPR_PUNCT = new Set([
|
|
100
|
+
'(',
|
|
101
|
+
'[',
|
|
102
|
+
'{',
|
|
103
|
+
';',
|
|
104
|
+
',',
|
|
105
|
+
'=',
|
|
106
|
+
'+',
|
|
107
|
+
'-',
|
|
108
|
+
'*',
|
|
109
|
+
'%',
|
|
110
|
+
'&',
|
|
111
|
+
'|',
|
|
112
|
+
'^',
|
|
113
|
+
'!',
|
|
114
|
+
'~',
|
|
115
|
+
'?',
|
|
116
|
+
':',
|
|
117
|
+
'<',
|
|
118
|
+
'>',
|
|
119
|
+
'/',
|
|
120
|
+
'=>',
|
|
121
|
+
'${',
|
|
122
|
+
]);
|
|
123
|
+
const wordCharRegex = new RegExp('[a-zA-Z0-9_$]');
|
|
124
|
+
const alphaRegex = new RegExp('[a-zA-Z]');
|
|
125
|
+
for (let i = 0; i < content.length; i++) {
|
|
126
|
+
const char = content[i];
|
|
127
|
+
const nextChar = content[i + 1];
|
|
128
|
+
// --- 1. SINGLE LINE COMMENT ---
|
|
129
|
+
if (inSingleComment) {
|
|
130
|
+
if (char === '\n') {
|
|
131
|
+
inSingleComment = false;
|
|
52
132
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
inSingleComment = false;
|
|
61
|
-
continue;
|
|
62
|
-
}
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
// --- 2. MULTI LINE COMMENT ---
|
|
136
|
+
if (inMultiComment) {
|
|
137
|
+
if (char === '*' && nextChar === '/') {
|
|
138
|
+
inMultiComment = false;
|
|
139
|
+
i++; // skip '/'
|
|
63
140
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
// --- 3. STRING LITERAL ('...' or "...") ---
|
|
144
|
+
if (inString) {
|
|
145
|
+
if (char === '\\') {
|
|
146
|
+
i++; // skip escaped char
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
if (char === stringChar) {
|
|
150
|
+
inString = false;
|
|
151
|
+
stringChar = '';
|
|
75
152
|
}
|
|
76
|
-
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
// --- 4. TEMPLATE LITERAL (`...`) ---
|
|
156
|
+
if (inTemplate) {
|
|
157
|
+
if (char === '\\') {
|
|
158
|
+
i++; // skip escaped char
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
if (char === '$' && nextChar === '{') {
|
|
162
|
+
// Enter template expression ${...}
|
|
163
|
+
stack.push('${');
|
|
164
|
+
inTemplate = false;
|
|
165
|
+
i++; // skip '{'
|
|
166
|
+
lastToken = '${';
|
|
167
|
+
currentWord = '';
|
|
77
168
|
continue;
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
169
|
+
}
|
|
170
|
+
if (char === '`') {
|
|
171
|
+
inTemplate = false;
|
|
172
|
+
}
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
// --- 5. REGEX LITERAL (/.../) ---
|
|
176
|
+
if (inRegex) {
|
|
177
|
+
if (char === '\\') {
|
|
178
|
+
i++; // skip escaped char
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
if (char === '[') {
|
|
182
|
+
inRegexCharClass = true;
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
if (char === ']') {
|
|
186
|
+
inRegexCharClass = false;
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
if (char === '/' && !inRegexCharClass) {
|
|
190
|
+
inRegex = false;
|
|
191
|
+
// Skip regex flags (e.g. /foo/gim)
|
|
192
|
+
while (i + 1 < content.length && alphaRegex.test(content[i + 1])) {
|
|
193
|
+
i++;
|
|
92
194
|
}
|
|
93
195
|
}
|
|
196
|
+
continue;
|
|
94
197
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
198
|
+
// --- 6. NOT IN STRING / COMMENT / TEMPLATE / REGEX ---
|
|
199
|
+
// Check for comment starts
|
|
200
|
+
if (!isHashStyle) {
|
|
201
|
+
if (char === '/' && nextChar === '/') {
|
|
202
|
+
inSingleComment = true;
|
|
203
|
+
i++; // skip second '/'
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
if (char === '/' && nextChar === '*') {
|
|
207
|
+
inMultiComment = true;
|
|
208
|
+
i++; // skip '*'
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
if (char === '#') {
|
|
214
|
+
inSingleComment = true;
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
// Check for string starts (' or ")
|
|
219
|
+
if (char === '"' || char === "'") {
|
|
220
|
+
inString = true;
|
|
221
|
+
stringChar = char;
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
// Check for template literal start (`)
|
|
225
|
+
if (isJsTs && char === '`') {
|
|
226
|
+
inTemplate = true;
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
// Check for regex literal start
|
|
230
|
+
if (isJsTs && char === '/') {
|
|
231
|
+
// Determine if '/' starts a regex or is a division operator
|
|
232
|
+
const prevToken = currentWord || lastToken;
|
|
233
|
+
const isExpr = !prevToken || EXPR_KEYWORDS.has(prevToken) || EXPR_PUNCT.has(prevToken);
|
|
234
|
+
if (isExpr) {
|
|
235
|
+
inRegex = true;
|
|
236
|
+
inRegexCharClass = false;
|
|
237
|
+
currentWord = '';
|
|
238
|
+
lastToken = '/';
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
// Update lastToken / currentWord tracking
|
|
243
|
+
if (char === ' ' || char === '\t' || char === '\n' || char === '\r') {
|
|
244
|
+
if (currentWord) {
|
|
245
|
+
lastToken = currentWord;
|
|
246
|
+
currentWord = '';
|
|
247
|
+
}
|
|
100
248
|
}
|
|
249
|
+
else if (wordCharRegex.test(char)) {
|
|
250
|
+
currentWord += char;
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
if (currentWord) {
|
|
254
|
+
lastToken = currentWord;
|
|
255
|
+
currentWord = '';
|
|
256
|
+
}
|
|
257
|
+
lastToken = char;
|
|
258
|
+
}
|
|
259
|
+
// --- 7. BRACKET MATCHING ---
|
|
260
|
+
if (['{', '[', '('].includes(char)) {
|
|
261
|
+
if (isHashStyle && char === '{')
|
|
262
|
+
continue;
|
|
263
|
+
stack.push(char);
|
|
264
|
+
}
|
|
265
|
+
else if (['}', ']', ')'].includes(char)) {
|
|
266
|
+
if (isHashStyle && char === '}')
|
|
267
|
+
continue;
|
|
268
|
+
const last = stack.pop();
|
|
269
|
+
if (!last || pairs[last] !== char) {
|
|
270
|
+
return {
|
|
271
|
+
isValid: false,
|
|
272
|
+
error: "Unbalanced character '" + char + "' at position " + i,
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
// If we popped a '${' template expression delimiter, return to template literal mode
|
|
276
|
+
if (last === '${') {
|
|
277
|
+
inTemplate = true;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
// Final check for unclosed delimiters or unclosed comments/strings/regex
|
|
282
|
+
if (stack.length > 0) {
|
|
283
|
+
const unclosed = stack[stack.length - 1];
|
|
284
|
+
return {
|
|
285
|
+
isValid: false,
|
|
286
|
+
error: "Unclosed character '" + unclosed + "'",
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
if (inMultiComment) {
|
|
290
|
+
return { isValid: false, error: 'Unclosed multi-line comment' };
|
|
291
|
+
}
|
|
292
|
+
if (inString) {
|
|
293
|
+
return { isValid: false, error: 'Unclosed string literal' };
|
|
294
|
+
}
|
|
295
|
+
if (inTemplate) {
|
|
296
|
+
return { isValid: false, error: 'Unclosed template literal' };
|
|
297
|
+
}
|
|
298
|
+
if (inRegex) {
|
|
299
|
+
return { isValid: false, error: 'Unclosed regex literal' };
|
|
101
300
|
}
|
|
102
301
|
return { isValid: true };
|
|
103
302
|
}
|
|
@@ -20,10 +20,7 @@ export declare function isAuditableFile(filePath: string): boolean;
|
|
|
20
20
|
/**
|
|
21
21
|
* Scans source code for performance anti-patterns using language-aware
|
|
22
22
|
* regex-based heuristics. Returns structured findings grouped by severity.
|
|
23
|
-
*
|
|
24
|
-
* This function is designed to be called inline during the verification
|
|
25
|
-
* phase — it's synchronous, zero-dependency, and executes in <50ms on
|
|
26
|
-
* files up to 10,000 lines.
|
|
23
|
+
* Supports comment suppression directives (perf-ignore).
|
|
27
24
|
*
|
|
28
25
|
* @param content - The raw source code string to audit.
|
|
29
26
|
* @param filePath - The file path (used for language detection via extension).
|
|
@@ -31,12 +28,10 @@ export declare function isAuditableFile(filePath: string): boolean;
|
|
|
31
28
|
*/
|
|
32
29
|
export declare function auditFilePerformance(content: string, filePath: string): PerfAuditResult;
|
|
33
30
|
/**
|
|
34
|
-
* Formats audit findings for
|
|
35
|
-
* Used for non-blocking warnings shown to the user after verification.
|
|
31
|
+
* Formats audit findings for terminal display using picocolors.
|
|
36
32
|
*/
|
|
37
33
|
export declare function formatAuditForTerminal(results: PerfAuditResult[]): string;
|
|
38
34
|
/**
|
|
39
35
|
* Formats audit findings into a structured prompt for the AI auto-correction loop.
|
|
40
|
-
* Only includes ERROR-severity findings (warnings and info are non-blocking).
|
|
41
36
|
*/
|
|
42
37
|
export declare function formatAuditForModel(results: PerfAuditResult[]): string;
|