@gotza02/sequential-thinking 10000.1.6 → 10000.1.8
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/CLAUDE.md +31 -6
- package/README.md +20 -1
- package/dist/analyzers/ComplexityCalculator.d.ts +15 -0
- package/dist/analyzers/ComplexityCalculator.js +59 -0
- package/dist/analyzers/QualityAnalyzer.d.ts +25 -0
- package/dist/analyzers/QualityAnalyzer.js +89 -0
- package/dist/analyzers/RefactoringEngine.d.ts +20 -0
- package/dist/analyzers/RefactoringEngine.js +107 -0
- package/dist/analyzers/SymbolAnalyzer.d.ts +30 -0
- package/dist/analyzers/SymbolAnalyzer.js +123 -0
- package/dist/analyzers/index.d.ts +8 -0
- package/dist/analyzers/index.js +4 -0
- package/dist/coding.test.js +4 -0
- package/dist/dashboard/index.html +95 -0
- package/dist/dashboard/server.js +97 -0
- package/dist/graph.d.ts +0 -6
- package/dist/graph.js +9 -265
- package/dist/index.js +2 -0
- package/dist/intelligent-code.d.ts +91 -0
- package/dist/intelligent-code.js +425 -0
- package/dist/lib.d.ts +42 -0
- package/dist/lib.js +308 -237
- package/dist/parsers/GenericParser.d.ts +6 -0
- package/dist/parsers/GenericParser.js +52 -0
- package/dist/parsers/GoParser.d.ts +6 -0
- package/dist/parsers/GoParser.js +36 -0
- package/dist/parsers/JavaParser.d.ts +6 -0
- package/dist/parsers/JavaParser.js +32 -0
- package/dist/parsers/PythonParser.d.ts +6 -0
- package/dist/parsers/PythonParser.js +50 -0
- package/dist/parsers/RustParser.d.ts +6 -0
- package/dist/parsers/RustParser.js +33 -0
- package/dist/parsers/TypeScriptParser.d.ts +9 -0
- package/dist/parsers/TypeScriptParser.js +85 -0
- package/dist/parsers/index.d.ts +7 -0
- package/dist/parsers/index.js +6 -0
- package/dist/tools/intelligent-code.d.ts +7 -0
- package/dist/tools/intelligent-code.js +387 -0
- package/dist/tools/sports/tools/match.js +221 -166
- package/dist/tools/web.js +4 -1
- package/package.json +1 -1
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* INTELLIGENT CODE MODULE
|
|
3
|
+
* AI-powered code analysis, semantic search, and smart refactoring
|
|
4
|
+
*/
|
|
5
|
+
import * as fs from 'fs/promises';
|
|
6
|
+
import * as path from 'path';
|
|
7
|
+
import { exec } from 'child_process';
|
|
8
|
+
import { promisify } from 'util';
|
|
9
|
+
import ts from 'typescript';
|
|
10
|
+
import { validatePath } from './utils.js';
|
|
11
|
+
import { complexityCalculator, qualityAnalyzer, symbolAnalyzer, refactoringEngine } from './analyzers/index.js';
|
|
12
|
+
const execAsync = promisify(exec);
|
|
13
|
+
// ============= Intelligent Code Analyzer =============
|
|
14
|
+
export class IntelligentCodeAnalyzer {
|
|
15
|
+
graph;
|
|
16
|
+
program;
|
|
17
|
+
typeChecker;
|
|
18
|
+
constructor(graph) {
|
|
19
|
+
this.graph = graph;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Comprehensive code analysis with metrics and quality scoring
|
|
23
|
+
*/
|
|
24
|
+
async analyzeFile(filePath) {
|
|
25
|
+
const absolutePath = validatePath(filePath);
|
|
26
|
+
const content = await fs.readFile(absolutePath, 'utf-8');
|
|
27
|
+
// Parse AST
|
|
28
|
+
const sourceFile = ts.createSourceFile(absolutePath, content, ts.ScriptTarget.Latest, true);
|
|
29
|
+
// Calculate metrics using extracted analyzer
|
|
30
|
+
const metrics = complexityCalculator.calculate(sourceFile, content);
|
|
31
|
+
// Analyze quality using extracted analyzer
|
|
32
|
+
const quality = await qualityAnalyzer.analyze(sourceFile, content, metrics);
|
|
33
|
+
// Extract symbols with analysis using extracted analyzer
|
|
34
|
+
const symbols = symbolAnalyzer.analyze(sourceFile);
|
|
35
|
+
return { metrics, quality, ast: sourceFile, symbols };
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Smart impact analysis - predicts what will be affected by changes
|
|
39
|
+
*/
|
|
40
|
+
async analyzeImpact(filePath, changeDescription) {
|
|
41
|
+
const absolutePath = validatePath(filePath);
|
|
42
|
+
// Get graph relationships
|
|
43
|
+
const context = this.graph.getDeepContext(filePath);
|
|
44
|
+
if (!context) {
|
|
45
|
+
await this.graph.build(process.cwd());
|
|
46
|
+
}
|
|
47
|
+
const relationships = this.graph.getRelationships(filePath);
|
|
48
|
+
if (!relationships) {
|
|
49
|
+
return {
|
|
50
|
+
filePath,
|
|
51
|
+
directImpacts: [],
|
|
52
|
+
indirectImpacts: [],
|
|
53
|
+
testFiles: [],
|
|
54
|
+
riskScore: 0,
|
|
55
|
+
breakingChanges: false,
|
|
56
|
+
estimatedReviewTime: 0,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
// Direct impacts: files that import this file
|
|
60
|
+
const directImpacts = relationships.importedBy;
|
|
61
|
+
// Find indirect impacts (files that import the direct impacts)
|
|
62
|
+
const indirectImpacts = [];
|
|
63
|
+
for (const directFile of directImpacts) {
|
|
64
|
+
const directRel = this.graph.getRelationships(directFile);
|
|
65
|
+
if (directRel) {
|
|
66
|
+
for (const indirect of directRel.importedBy) {
|
|
67
|
+
if (indirect !== filePath && !directImpacts.includes(indirect)) {
|
|
68
|
+
indirectImpacts.push(indirect);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// Find related test files
|
|
74
|
+
const testFiles = await this.findRelatedTests(filePath);
|
|
75
|
+
// Calculate risk score
|
|
76
|
+
let riskScore = 0;
|
|
77
|
+
// Base risk from number of dependents
|
|
78
|
+
riskScore += directImpacts.length * 10;
|
|
79
|
+
riskScore += indirectImpacts.length * 5;
|
|
80
|
+
// Higher risk if changing public API
|
|
81
|
+
if (relationships.symbols.some(s => s.includes('export'))) {
|
|
82
|
+
riskScore += 20;
|
|
83
|
+
}
|
|
84
|
+
// Check change description for risky keywords
|
|
85
|
+
if (changeDescription) {
|
|
86
|
+
const riskyKeywords = ['delete', 'remove', 'rename', 'breaking', 'api'];
|
|
87
|
+
if (riskyKeywords.some(k => changeDescription.toLowerCase().includes(k))) {
|
|
88
|
+
riskScore += 15;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const breakingChanges = riskScore > 50;
|
|
92
|
+
const estimatedReviewTime = Math.min(120, 5 + directImpacts.length * 2 + indirectImpacts.length + testFiles.length * 3);
|
|
93
|
+
return {
|
|
94
|
+
filePath,
|
|
95
|
+
directImpacts,
|
|
96
|
+
indirectImpacts: [...new Set(indirectImpacts)],
|
|
97
|
+
testFiles,
|
|
98
|
+
riskScore: Math.min(100, riskScore),
|
|
99
|
+
breakingChanges,
|
|
100
|
+
estimatedReviewTime,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
async findRelatedTests(filePath) {
|
|
104
|
+
const testFiles = [];
|
|
105
|
+
const baseName = path.basename(filePath, path.extname(filePath));
|
|
106
|
+
const dir = path.dirname(filePath);
|
|
107
|
+
// Common test file patterns
|
|
108
|
+
const patterns = [
|
|
109
|
+
`${baseName}.test.ts`,
|
|
110
|
+
`${baseName}.spec.ts`,
|
|
111
|
+
`${baseName}.test.js`,
|
|
112
|
+
`${baseName}.spec.js`,
|
|
113
|
+
];
|
|
114
|
+
for (const pattern of patterns) {
|
|
115
|
+
const testPath = path.join(dir, pattern);
|
|
116
|
+
try {
|
|
117
|
+
await fs.access(testPath);
|
|
118
|
+
testFiles.push(testPath);
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
// File doesn't exist
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// Check for __tests__ directory
|
|
125
|
+
const testsDir = path.join(dir, '__tests__');
|
|
126
|
+
try {
|
|
127
|
+
const files = await fs.readdir(testsDir);
|
|
128
|
+
files.forEach(f => {
|
|
129
|
+
if (f.includes(baseName) && (f.endsWith('.test.ts') || f.endsWith('.spec.ts'))) {
|
|
130
|
+
testFiles.push(path.join(testsDir, f));
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
// Directory doesn't exist
|
|
136
|
+
}
|
|
137
|
+
return testFiles;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Generate intelligent refactoring suggestions
|
|
141
|
+
*/
|
|
142
|
+
async suggestRefactoring(filePath) {
|
|
143
|
+
const { ast, metrics } = await this.analyzeFile(filePath);
|
|
144
|
+
if (!ast)
|
|
145
|
+
return [];
|
|
146
|
+
// Use refactoring engine to generate suggestions
|
|
147
|
+
return refactoringEngine.suggest(ast, metrics);
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Semantic code search - find code by concept, not just text
|
|
151
|
+
*/
|
|
152
|
+
async semanticSearch(query, options = {}) {
|
|
153
|
+
const { filePattern = '*', maxResults = 10 } = options;
|
|
154
|
+
// Build query concepts
|
|
155
|
+
const concepts = this.extractConcepts(query);
|
|
156
|
+
// Search through codebase
|
|
157
|
+
const files = await this.getMatchingFiles(filePattern);
|
|
158
|
+
const results = [];
|
|
159
|
+
for (const filePath of files) {
|
|
160
|
+
try {
|
|
161
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
162
|
+
const relevance = this.calculateRelevance(content, concepts, query);
|
|
163
|
+
if (relevance > 0.3) {
|
|
164
|
+
const snippet = this.extractRelevantSnippet(content, concepts);
|
|
165
|
+
results.push({
|
|
166
|
+
filePath,
|
|
167
|
+
relevance,
|
|
168
|
+
context: this.extractContext(content, snippet),
|
|
169
|
+
matchedConcepts: concepts.filter(c => content.toLowerCase().includes(c.toLowerCase())),
|
|
170
|
+
codeSnippet: snippet,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
catch {
|
|
175
|
+
// Skip files that can't be read
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return results
|
|
179
|
+
.sort((a, b) => b.relevance - a.relevance)
|
|
180
|
+
.slice(0, maxResults);
|
|
181
|
+
}
|
|
182
|
+
extractConcepts(query) {
|
|
183
|
+
// Extract key concepts from query
|
|
184
|
+
const stopWords = new Set(['the', 'a', 'an', 'in', 'on', 'at', 'to', 'for', 'of', 'and', 'or']);
|
|
185
|
+
return query
|
|
186
|
+
.toLowerCase()
|
|
187
|
+
.split(/\s+/)
|
|
188
|
+
.filter(w => w.length > 2 && !stopWords.has(w))
|
|
189
|
+
.map(w => w.replace(/[^a-z0-9]/g, ''));
|
|
190
|
+
}
|
|
191
|
+
calculateRelevance(content, concepts, originalQuery) {
|
|
192
|
+
const lowerContent = content.toLowerCase();
|
|
193
|
+
let score = 0;
|
|
194
|
+
// Concept matching
|
|
195
|
+
for (const concept of concepts) {
|
|
196
|
+
const count = (lowerContent.match(new RegExp(concept, 'g')) || []).length;
|
|
197
|
+
score += Math.min(count * 0.1, 0.5);
|
|
198
|
+
}
|
|
199
|
+
// Check for function/variable names matching query
|
|
200
|
+
const camelCaseQuery = originalQuery.replace(/\s+(.)/g, (_, c) => c.toUpperCase());
|
|
201
|
+
const snakeCaseQuery = originalQuery.replace(/\s+/g, '_');
|
|
202
|
+
if (content.includes(camelCaseQuery) || content.includes(snakeCaseQuery)) {
|
|
203
|
+
score += 0.3;
|
|
204
|
+
}
|
|
205
|
+
// Boost for TypeScript/JavaScript files
|
|
206
|
+
if (content.includes('function') || content.includes('const') || content.includes('export')) {
|
|
207
|
+
score += 0.1;
|
|
208
|
+
}
|
|
209
|
+
return Math.min(1, score);
|
|
210
|
+
}
|
|
211
|
+
extractRelevantSnippet(content, concepts) {
|
|
212
|
+
const lines = content.split('\n');
|
|
213
|
+
let bestStart = 0;
|
|
214
|
+
let bestScore = 0;
|
|
215
|
+
// Find window with highest concept density
|
|
216
|
+
for (let i = 0; i < lines.length - 10; i++) {
|
|
217
|
+
const window = lines.slice(i, i + 10).join('\n').toLowerCase();
|
|
218
|
+
const score = concepts.filter(c => window.includes(c)).length;
|
|
219
|
+
if (score > bestScore) {
|
|
220
|
+
bestScore = score;
|
|
221
|
+
bestStart = i;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return lines.slice(bestStart, bestStart + 15).join('\n');
|
|
225
|
+
}
|
|
226
|
+
extractContext(content, snippet) {
|
|
227
|
+
const lines = content.split('\n');
|
|
228
|
+
const snippetLines = snippet.split('\n');
|
|
229
|
+
const firstLine = snippetLines[0];
|
|
230
|
+
// Try to find class/function name
|
|
231
|
+
for (let i = 0; i < lines.length; i++) {
|
|
232
|
+
if (lines[i] === firstLine) {
|
|
233
|
+
// Look backwards for function/class declaration
|
|
234
|
+
for (let j = Math.max(0, i - 5); j < i; j++) {
|
|
235
|
+
const match = lines[j].match(/(?:export\s+)?(?:class|function|interface)\s+(\w+)/);
|
|
236
|
+
if (match) {
|
|
237
|
+
return `${match[0]} (line ${j + 1})`;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return 'Global scope';
|
|
243
|
+
}
|
|
244
|
+
async getMatchingFiles(pattern) {
|
|
245
|
+
// Simple glob-like matching
|
|
246
|
+
const files = [];
|
|
247
|
+
try {
|
|
248
|
+
const { stdout } = await execAsync(`find . -type f -name "${pattern}" ! -path "*/node_modules/*" ! -path "*/.git/*" | head -100`, { cwd: process.cwd() });
|
|
249
|
+
return stdout.trim().split('\n').filter(Boolean);
|
|
250
|
+
}
|
|
251
|
+
catch {
|
|
252
|
+
return [];
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Auto-fix common code issues
|
|
257
|
+
*/
|
|
258
|
+
async autoFix(filePath, options = {}) {
|
|
259
|
+
const absolutePath = validatePath(filePath);
|
|
260
|
+
const content = await fs.readFile(absolutePath, 'utf-8');
|
|
261
|
+
const lines = content.split('\n');
|
|
262
|
+
const fixes = [];
|
|
263
|
+
let modifiedContent = content;
|
|
264
|
+
// Fix 1: Remove trailing whitespace
|
|
265
|
+
if (options.fixTrailingWhitespace !== false) {
|
|
266
|
+
for (let i = 0; i < lines.length; i++) {
|
|
267
|
+
const line = lines[i];
|
|
268
|
+
const trimmed = line.replace(/\s+$/, '');
|
|
269
|
+
if (line !== trimmed) {
|
|
270
|
+
fixes.push({
|
|
271
|
+
type: 'trailing-whitespace',
|
|
272
|
+
line: i + 1,
|
|
273
|
+
original: line,
|
|
274
|
+
fixed: trimmed,
|
|
275
|
+
});
|
|
276
|
+
lines[i] = trimmed;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
modifiedContent = lines.join('\n');
|
|
280
|
+
}
|
|
281
|
+
// Fix 2: Add missing semicolons (simple heuristic)
|
|
282
|
+
if (options.fixMissingSemicolons) {
|
|
283
|
+
const semicolonPattern = /^(\s*)(.+?)(?<!;)(\s*)$/;
|
|
284
|
+
for (let i = 0; i < lines.length; i++) {
|
|
285
|
+
const line = lines[i];
|
|
286
|
+
// Skip comments, strings, imports, exports, function declarations, etc.
|
|
287
|
+
if (line.trim().startsWith('//') ||
|
|
288
|
+
line.trim().startsWith('/*') ||
|
|
289
|
+
line.trim().startsWith('*') ||
|
|
290
|
+
line.trim().startsWith('import') ||
|
|
291
|
+
line.trim().startsWith('export') ||
|
|
292
|
+
line.trim().startsWith('function') ||
|
|
293
|
+
line.trim().startsWith('async function') ||
|
|
294
|
+
line.trim().startsWith('class') ||
|
|
295
|
+
line.trim().startsWith('interface') ||
|
|
296
|
+
line.trim().startsWith('type') ||
|
|
297
|
+
line.trim().startsWith('if') ||
|
|
298
|
+
line.trim().startsWith('for') ||
|
|
299
|
+
line.trim().startsWith('while') ||
|
|
300
|
+
line.trim().startsWith('switch') ||
|
|
301
|
+
line.trim().startsWith('try') ||
|
|
302
|
+
line.trim().startsWith('catch') ||
|
|
303
|
+
line.trim().startsWith('finally') ||
|
|
304
|
+
line.trim().startsWith('{') ||
|
|
305
|
+
line.trim().startsWith('}') ||
|
|
306
|
+
line.trim().endsWith('{') ||
|
|
307
|
+
line.trim().endsWith('}') ||
|
|
308
|
+
line.trim().endsWith(';') ||
|
|
309
|
+
line.trim() === '') {
|
|
310
|
+
continue;
|
|
311
|
+
}
|
|
312
|
+
// Add semicolon if line looks like a statement
|
|
313
|
+
if (/[a-zA-Z0-9_)\]]\s*$/.test(line) && !line.trim().endsWith(';')) {
|
|
314
|
+
fixes.push({
|
|
315
|
+
type: 'missing-semicolon',
|
|
316
|
+
line: i + 1,
|
|
317
|
+
original: line,
|
|
318
|
+
fixed: line + ';',
|
|
319
|
+
});
|
|
320
|
+
lines[i] = line + ';';
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
modifiedContent = lines.join('\n');
|
|
324
|
+
}
|
|
325
|
+
// Fix 3: Optimize imports
|
|
326
|
+
if (options.optimizeImports) {
|
|
327
|
+
const importRegex = /^(import\s+(?:{[^}]*}|\*\s+as\s+\w+|\w+)\s+from\s+['"][^'"]+['"];?)$/gm;
|
|
328
|
+
const imports = [];
|
|
329
|
+
let match;
|
|
330
|
+
while ((match = importRegex.exec(content)) !== null) {
|
|
331
|
+
imports.push(match[1]);
|
|
332
|
+
}
|
|
333
|
+
if (imports.length > 0) {
|
|
334
|
+
// Sort imports
|
|
335
|
+
imports.sort((a, b) => {
|
|
336
|
+
const aIsRelative = a.includes("from '.'") || a.includes("from '..");
|
|
337
|
+
const bIsRelative = b.includes("from '.'") || b.includes("from '..");
|
|
338
|
+
if (aIsRelative && !bIsRelative)
|
|
339
|
+
return 1;
|
|
340
|
+
if (!aIsRelative && bIsRelative)
|
|
341
|
+
return -1;
|
|
342
|
+
return a.localeCompare(b);
|
|
343
|
+
});
|
|
344
|
+
// Remove duplicates
|
|
345
|
+
const uniqueImports = [...new Set(imports)];
|
|
346
|
+
if (uniqueImports.length !== imports.length || imports.join('\n') !== uniqueImports.join('\n')) {
|
|
347
|
+
fixes.push({
|
|
348
|
+
type: 'optimize-imports',
|
|
349
|
+
line: 1,
|
|
350
|
+
original: `Found ${imports.length} imports`,
|
|
351
|
+
fixed: `Optimized to ${uniqueImports.length} imports`,
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
// Apply fixes if not dry run
|
|
357
|
+
const applied = !options.dryRun && fixes.length > 0;
|
|
358
|
+
if (applied) {
|
|
359
|
+
await fs.writeFile(absolutePath, modifiedContent, 'utf-8');
|
|
360
|
+
}
|
|
361
|
+
return { fixes, applied };
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Detect code patterns and anti-patterns
|
|
365
|
+
*/
|
|
366
|
+
detectPatterns(filePath, sourceFile) {
|
|
367
|
+
const patterns = [];
|
|
368
|
+
const content = sourceFile.getFullText();
|
|
369
|
+
// Pattern: Singleton
|
|
370
|
+
const singletonPattern = /class\s+(\w+).*?private\s+static\s+instance|getInstance/s;
|
|
371
|
+
if (singletonPattern.test(content)) {
|
|
372
|
+
patterns.push({
|
|
373
|
+
name: 'Singleton Pattern',
|
|
374
|
+
description: 'Ensures a class has only one instance',
|
|
375
|
+
examples: ['Database connection', 'Logger', 'Configuration'],
|
|
376
|
+
antiPattern: 'Can make testing difficult, consider dependency injection',
|
|
377
|
+
solution: 'Use factory functions or dependency injection instead',
|
|
378
|
+
confidence: 85,
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
// Pattern: Factory
|
|
382
|
+
const factoryPattern = /create[A-Z]\w+\s*\(|make[A-Z]\w+\s*\(/;
|
|
383
|
+
if (factoryPattern.test(content)) {
|
|
384
|
+
patterns.push({
|
|
385
|
+
name: 'Factory Pattern',
|
|
386
|
+
description: 'Creates objects without specifying exact class',
|
|
387
|
+
examples: ['createUser()', 'makeRequest()'],
|
|
388
|
+
solution: 'Use dependency injection container or factory pattern',
|
|
389
|
+
confidence: 70,
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
// Anti-pattern: Callback hell
|
|
393
|
+
const callbackHell = /\)\s*\{[\s\S]*?\)\s*\{[\s\S]*?\)\s*\{/;
|
|
394
|
+
if (callbackHell.test(content)) {
|
|
395
|
+
patterns.push({
|
|
396
|
+
name: 'Callback Hell (Anti-pattern)',
|
|
397
|
+
description: 'Deeply nested callbacks',
|
|
398
|
+
examples: [],
|
|
399
|
+
antiPattern: 'Makes code hard to read and maintain',
|
|
400
|
+
solution: 'Use async/await or Promise chains',
|
|
401
|
+
confidence: 90,
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
// Pattern: Dependency Injection
|
|
405
|
+
const diPattern = /constructor\s*\([^)]*(?:private|public|protected)[^)]*\)/;
|
|
406
|
+
if (diPattern.test(content)) {
|
|
407
|
+
patterns.push({
|
|
408
|
+
name: 'Dependency Injection',
|
|
409
|
+
description: 'Dependencies provided through constructor',
|
|
410
|
+
examples: ['constructor(private db: Database)'],
|
|
411
|
+
solution: 'Good practice for testability and modularity',
|
|
412
|
+
confidence: 80,
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
return patterns;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
// ============= Export singleton =============
|
|
419
|
+
let analyzerInstance = null;
|
|
420
|
+
export function getIntelligentAnalyzer(graph) {
|
|
421
|
+
if (!analyzerInstance) {
|
|
422
|
+
analyzerInstance = new IntelligentCodeAnalyzer(graph);
|
|
423
|
+
}
|
|
424
|
+
return analyzerInstance;
|
|
425
|
+
}
|
package/dist/lib.d.ts
CHANGED
|
@@ -41,6 +41,12 @@ export declare class SequentialThinkingServer {
|
|
|
41
41
|
private contextManager;
|
|
42
42
|
private ruleManager;
|
|
43
43
|
private maxHistorySize;
|
|
44
|
+
private static readonly MAX_HISTORY_SIZE;
|
|
45
|
+
private static readonly AUTO_PRUNE_THRESHOLD;
|
|
46
|
+
private static readonly CONFIDENCE_CRITICAL_THRESHOLD;
|
|
47
|
+
private static readonly MAX_NESTING_DEPTH;
|
|
48
|
+
private static readonly STALLING_THRESHOLD;
|
|
49
|
+
private static readonly EXECUTION_STRUGGLE_THRESHOLD;
|
|
44
50
|
constructor(storagePath?: string, delayMs?: number, maxHistorySize?: number);
|
|
45
51
|
private loadHistory;
|
|
46
52
|
private attemptRecovery;
|
|
@@ -58,6 +64,42 @@ export declare class SequentialThinkingServer {
|
|
|
58
64
|
searchHistory(query: string): Promise<ThoughtData[]>;
|
|
59
65
|
private addToMemory;
|
|
60
66
|
private formatThought;
|
|
67
|
+
/**
|
|
68
|
+
* Handle block management - create new blocks or switch context
|
|
69
|
+
*/
|
|
70
|
+
private handleBlockManagement;
|
|
71
|
+
/**
|
|
72
|
+
* Detect loops, stalling, and other thinking pattern issues
|
|
73
|
+
*/
|
|
74
|
+
private detectLoopsAndStalling;
|
|
75
|
+
/**
|
|
76
|
+
* Validate solution before accepting
|
|
77
|
+
*/
|
|
78
|
+
private validateSolution;
|
|
79
|
+
/**
|
|
80
|
+
* Update confidence score based on thought type and warnings
|
|
81
|
+
*/
|
|
82
|
+
private updateConfidenceScore;
|
|
83
|
+
/**
|
|
84
|
+
* Get block history for current input
|
|
85
|
+
*/
|
|
86
|
+
private getBlockHistory;
|
|
87
|
+
/**
|
|
88
|
+
* Check for smart branching - reset confidence on pivot
|
|
89
|
+
*/
|
|
90
|
+
private checkSmartBranching;
|
|
91
|
+
/**
|
|
92
|
+
* Check semantic thought recall for analysis type
|
|
93
|
+
*/
|
|
94
|
+
private checkSemanticRecall;
|
|
95
|
+
/**
|
|
96
|
+
* Check anti-insanity - prevent repeating failed executions
|
|
97
|
+
*/
|
|
98
|
+
private checkAntiInsanity;
|
|
99
|
+
/**
|
|
100
|
+
* Check if confidence is critical and return critical stop response if needed
|
|
101
|
+
*/
|
|
102
|
+
private checkConfidenceCritical;
|
|
61
103
|
processThought(input: ThoughtData): Promise<{
|
|
62
104
|
content: any[];
|
|
63
105
|
isError?: boolean;
|