@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
package/CLAUDE.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# SmartAgent Elite Controller - System Instructions
|
|
2
2
|
|
|
3
|
-
You are an AI assistant powered by the Sequential Thinking MCP server (@gotza02/sequential-thinking@10000.1.
|
|
3
|
+
You are an AI assistant powered by the Sequential Thinking MCP server (@gotza02/sequential-thinking@10000.1.7).
|
|
4
4
|
|
|
5
5
|
## Critical Prime Directives
|
|
6
6
|
|
|
@@ -80,11 +80,31 @@ You are an AI assistant powered by the Sequential Thinking MCP server (@gotza02/
|
|
|
80
80
|
| `get_project_graph` | Codebase structure analysis | File dependencies |
|
|
81
81
|
| `get_file_relationships` | Find related files | Import/dependency graph |
|
|
82
82
|
|
|
83
|
+
### 🧠 Intelligent Code Analysis Tools (v10000.1.7+)
|
|
84
|
+
| Tool | Purpose | Features |
|
|
85
|
+
|------|---------|----------|
|
|
86
|
+
| `intelligent_code_analyze` | Deep code analysis | Quality scoring, metrics, issue detection |
|
|
87
|
+
| `intelligent_impact_analysis` | Change prediction | Risk score, affected files, test recommendations |
|
|
88
|
+
| `intelligent_semantic_search` | Concept-based search | Find code by meaning, not just text |
|
|
89
|
+
| `intelligent_refactor_suggest` | Refactoring ideas | AI suggestions with before/after code |
|
|
90
|
+
| `intelligent_code_compare` | Code comparison | Diff analysis with statistics |
|
|
91
|
+
| `intelligent_code_autofix` | Auto-fix code issues | Trailing whitespace, semicolons, imports |
|
|
92
|
+
|
|
93
|
+
**Intelligent Code Analysis Protocol:**
|
|
94
|
+
1. Before major changes → `intelligent_impact_analysis` (know the risk)
|
|
95
|
+
2. Understanding code → `intelligent_code_analyze` (quality + metrics)
|
|
96
|
+
3. Finding related code → `intelligent_semantic_search` (concept search)
|
|
97
|
+
4. Improving code → `intelligent_refactor_suggest` (actionable ideas)
|
|
98
|
+
5. Code reviews → `intelligent_code_compare` (detailed diffs)
|
|
99
|
+
6. Clean up issues → `intelligent_code_autofix` (dryRun first, then apply)
|
|
100
|
+
7. Monitor quality → Check `http://localhost:3001/api/code-quality` for project overview
|
|
101
|
+
|
|
83
102
|
**Code Edit Protocol:**
|
|
84
|
-
1.
|
|
85
|
-
2.
|
|
86
|
-
3.
|
|
87
|
-
4.
|
|
103
|
+
1. Before changes: Run `intelligent_impact_analysis` to assess risk
|
|
104
|
+
2. Always use `deep_code_edit` (not raw file writes)
|
|
105
|
+
3. Review backup location if rollback needed
|
|
106
|
+
4. Use `search_code` first to understand context
|
|
107
|
+
5. Validate changes with `get_project_graph`
|
|
88
108
|
|
|
89
109
|
### 📝 Knowledge & Notes Tools
|
|
90
110
|
| Tool | Purpose | Persistence |
|
|
@@ -124,6 +144,10 @@ Need information?
|
|
|
124
144
|
|
|
125
145
|
Need to take action?
|
|
126
146
|
├── Code changes → deep_code_edit
|
|
147
|
+
├── Code analysis → intelligent_code_analyze
|
|
148
|
+
├── Impact prediction → intelligent_impact_analysis
|
|
149
|
+
├── Refactoring ideas → intelligent_refactor_suggest
|
|
150
|
+
├── Auto-fix issues → intelligent_code_autofix
|
|
127
151
|
├── Store knowledge → add_note / create_knowledge_node
|
|
128
152
|
├── Track sports bet → track_prediction
|
|
129
153
|
└── Complex workflow → sequentialthinking → execution
|
|
@@ -180,7 +204,8 @@ For code changes:
|
|
|
180
204
|
📝 Files Modified: [list]
|
|
181
205
|
💾 Backup Location: [path]
|
|
182
206
|
✅ Validation: [tests/status]
|
|
183
|
-
🔍 Impact Analysis: [
|
|
207
|
+
🔍 Impact Analysis: [use intelligent_impact_analysis]
|
|
208
|
+
📊 Code Quality: [use intelligent_code_analyze for metrics]
|
|
184
209
|
```
|
|
185
210
|
|
|
186
211
|
## Error Recovery
|
package/README.md
CHANGED
|
@@ -115,6 +115,16 @@ Add to your `~/.claude/CLAUDE.md` or project-specific `.claude/CLAUDE.md`:
|
|
|
115
115
|
| `search_code` | Semantic code search |
|
|
116
116
|
| `get_project_graph` | Analyze codebase structure |
|
|
117
117
|
|
|
118
|
+
### 🧠 Intelligent Code Analysis (v10000.1.7+)
|
|
119
|
+
| Tool | Description |
|
|
120
|
+
|------|-------------|
|
|
121
|
+
| `intelligent_code_analyze` | AI-powered code analysis with quality scoring, metrics, and issue detection |
|
|
122
|
+
| `intelligent_impact_analysis` | Predict impact of code changes with risk scoring and affected files |
|
|
123
|
+
| `intelligent_semantic_search` | Search code by concept/meaning, not just text |
|
|
124
|
+
| `intelligent_refactor_suggest` | Get intelligent refactoring suggestions with code examples |
|
|
125
|
+
| `intelligent_code_compare` | Compare two code snippets or files with detailed diff analysis |
|
|
126
|
+
| `intelligent_code_autofix` | Auto-fix common issues (trailing whitespace, missing semicolons, optimize imports) |
|
|
127
|
+
|
|
118
128
|
### 📝 Knowledge & Notes Tools
|
|
119
129
|
| Tool | Description |
|
|
120
130
|
|------|-------------|
|
|
@@ -150,13 +160,22 @@ CRITICAL DIRECTIVES:
|
|
|
150
160
|
- Use analyze_football_match_structured for JSON/probability data
|
|
151
161
|
- Check value_bet_calculator for betting recommendations
|
|
152
162
|
4. Use deep_code_edit for structural code changes (creates backups)
|
|
153
|
-
5.
|
|
163
|
+
5. For intelligent code analysis:
|
|
164
|
+
- Use intelligent_code_analyze for quality scoring and metrics
|
|
165
|
+
- Use intelligent_impact_analysis before making changes
|
|
166
|
+
- Use intelligent_semantic_search to find related code
|
|
167
|
+
- Use intelligent_refactor_suggest for improvement ideas
|
|
168
|
+
- Use intelligent_code_autofix to clean up common issues (dryRun first!)
|
|
169
|
+
6. Track predictions with track_prediction for ROI analysis
|
|
170
|
+
7. Check code quality dashboard at http://localhost:3001/api/code-quality
|
|
154
171
|
|
|
155
172
|
TOOL PRIORITY:
|
|
156
173
|
- Information needed → web_search (Brave/Exa/DuckDuckGo)
|
|
157
174
|
- Problem solving → sequentialthinking
|
|
158
175
|
- Sports data → analyze_football_match_* tools
|
|
159
176
|
- Code editing → deep_code_edit
|
|
177
|
+
- Code analysis → intelligent_code_analyze
|
|
178
|
+
- Change impact → intelligent_impact_analysis
|
|
160
179
|
- Human input → ask_human
|
|
161
180
|
|
|
162
181
|
SAFETY PROTOCOLS:
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
export interface CodeMetrics {
|
|
3
|
+
complexity: number;
|
|
4
|
+
linesOfCode: number;
|
|
5
|
+
commentRatio: number;
|
|
6
|
+
functionCount: number;
|
|
7
|
+
maxNestingDepth: number;
|
|
8
|
+
duplicateCode: number;
|
|
9
|
+
testCoverage?: number;
|
|
10
|
+
}
|
|
11
|
+
export declare class ComplexityCalculator {
|
|
12
|
+
calculate(sourceFile: ts.SourceFile, content: string): CodeMetrics;
|
|
13
|
+
}
|
|
14
|
+
export declare const complexityCalculator: ComplexityCalculator;
|
|
15
|
+
export default complexityCalculator;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
export class ComplexityCalculator {
|
|
3
|
+
calculate(sourceFile, content) {
|
|
4
|
+
let complexity = 0;
|
|
5
|
+
let functionCount = 0;
|
|
6
|
+
let maxNestingDepth = 0;
|
|
7
|
+
let currentDepth = 0;
|
|
8
|
+
const visit = (node) => {
|
|
9
|
+
// Cyclomatic complexity
|
|
10
|
+
if (ts.isIfStatement(node) ||
|
|
11
|
+
ts.isConditionalExpression(node) ||
|
|
12
|
+
ts.isWhileStatement(node) ||
|
|
13
|
+
ts.isForStatement(node) ||
|
|
14
|
+
ts.isForInStatement(node) ||
|
|
15
|
+
ts.isForOfStatement(node) ||
|
|
16
|
+
ts.isCaseClause(node) ||
|
|
17
|
+
(ts.isBinaryExpression(node) &&
|
|
18
|
+
(node.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken ||
|
|
19
|
+
node.operatorToken.kind === ts.SyntaxKind.BarBarToken))) {
|
|
20
|
+
complexity++;
|
|
21
|
+
}
|
|
22
|
+
// Function count
|
|
23
|
+
if (ts.isFunctionDeclaration(node) ||
|
|
24
|
+
ts.isArrowFunction(node) ||
|
|
25
|
+
ts.isMethodDeclaration(node)) {
|
|
26
|
+
functionCount++;
|
|
27
|
+
}
|
|
28
|
+
// Nesting depth
|
|
29
|
+
if (ts.isBlock(node) ||
|
|
30
|
+
ts.isIfStatement(node) ||
|
|
31
|
+
ts.isForStatement(node) ||
|
|
32
|
+
ts.isWhileStatement(node)) {
|
|
33
|
+
currentDepth++;
|
|
34
|
+
maxNestingDepth = Math.max(maxNestingDepth, currentDepth);
|
|
35
|
+
}
|
|
36
|
+
ts.forEachChild(node, visit);
|
|
37
|
+
if (ts.isBlock(node) ||
|
|
38
|
+
ts.isIfStatement(node) ||
|
|
39
|
+
ts.isForStatement(node) ||
|
|
40
|
+
ts.isWhileStatement(node)) {
|
|
41
|
+
currentDepth--;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
visit(sourceFile);
|
|
45
|
+
const lines = content.split('\n');
|
|
46
|
+
const codeLines = lines.filter(l => l.trim().length > 0 && !l.trim().startsWith('//'));
|
|
47
|
+
const commentLines = lines.filter(l => l.trim().startsWith('//') || l.trim().startsWith('/*'));
|
|
48
|
+
return {
|
|
49
|
+
complexity: complexity + 1, // Base complexity is 1
|
|
50
|
+
linesOfCode: codeLines.length,
|
|
51
|
+
commentRatio: codeLines.length > 0 ? commentLines.length / codeLines.length : 0,
|
|
52
|
+
functionCount,
|
|
53
|
+
maxNestingDepth,
|
|
54
|
+
duplicateCode: 0, // Would need cross-file analysis
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
export const complexityCalculator = new ComplexityCalculator();
|
|
59
|
+
export default complexityCalculator;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
import { CodeMetrics } from './ComplexityCalculator.js';
|
|
3
|
+
export interface QualityIssue {
|
|
4
|
+
type: 'error' | 'warning' | 'info';
|
|
5
|
+
category: 'complexity' | 'style' | 'security' | 'performance' | 'maintainability';
|
|
6
|
+
message: string;
|
|
7
|
+
line?: number;
|
|
8
|
+
column?: number;
|
|
9
|
+
severity: number;
|
|
10
|
+
suggestion?: string;
|
|
11
|
+
autoFixable: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface CodeQualityScore {
|
|
14
|
+
overall: number;
|
|
15
|
+
maintainability: number;
|
|
16
|
+
reliability: number;
|
|
17
|
+
security: number;
|
|
18
|
+
performance: number;
|
|
19
|
+
issues: QualityIssue[];
|
|
20
|
+
}
|
|
21
|
+
export declare class QualityAnalyzer {
|
|
22
|
+
analyze(sourceFile: ts.SourceFile, content: string, metrics: CodeMetrics): Promise<CodeQualityScore>;
|
|
23
|
+
}
|
|
24
|
+
export declare const qualityAnalyzer: QualityAnalyzer;
|
|
25
|
+
export default qualityAnalyzer;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
export class QualityAnalyzer {
|
|
3
|
+
async analyze(sourceFile, content, metrics) {
|
|
4
|
+
const issues = [];
|
|
5
|
+
// Complexity checks
|
|
6
|
+
if (metrics.complexity > 20) {
|
|
7
|
+
issues.push({
|
|
8
|
+
type: 'warning',
|
|
9
|
+
category: 'complexity',
|
|
10
|
+
message: `High cyclomatic complexity (${metrics.complexity}). Consider refactoring.`,
|
|
11
|
+
severity: 7,
|
|
12
|
+
suggestion: 'Extract smaller functions or simplify conditional logic',
|
|
13
|
+
autoFixable: false,
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
if (metrics.maxNestingDepth > 4) {
|
|
17
|
+
issues.push({
|
|
18
|
+
type: 'warning',
|
|
19
|
+
category: 'maintainability',
|
|
20
|
+
message: `Deep nesting detected (${metrics.maxNestingDepth} levels)`,
|
|
21
|
+
severity: 6,
|
|
22
|
+
suggestion: 'Use early returns or extract nested logic into functions',
|
|
23
|
+
autoFixable: false,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
// Comment ratio
|
|
27
|
+
if (metrics.commentRatio < 0.05 && metrics.linesOfCode > 50) {
|
|
28
|
+
issues.push({
|
|
29
|
+
type: 'info',
|
|
30
|
+
category: 'maintainability',
|
|
31
|
+
message: 'Low comment ratio. Consider adding documentation.',
|
|
32
|
+
severity: 3,
|
|
33
|
+
suggestion: 'Add JSDoc comments for public APIs',
|
|
34
|
+
autoFixable: false,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
// Function length
|
|
38
|
+
const visit = (node) => {
|
|
39
|
+
if (ts.isFunctionDeclaration(node) || ts.isMethodDeclaration(node)) {
|
|
40
|
+
const start = node.getStart(sourceFile);
|
|
41
|
+
const end = node.getEnd();
|
|
42
|
+
const functionLines = content.substring(start, end).split('\n').length;
|
|
43
|
+
if (functionLines > 50) {
|
|
44
|
+
issues.push({
|
|
45
|
+
type: 'warning',
|
|
46
|
+
category: 'maintainability',
|
|
47
|
+
message: `Long function detected (${functionLines} lines)`,
|
|
48
|
+
line: ts.getLineAndCharacterOfPosition(sourceFile, node.getStart()).line + 1,
|
|
49
|
+
severity: 6,
|
|
50
|
+
suggestion: 'Extract helper functions to reduce function length',
|
|
51
|
+
autoFixable: false,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
ts.forEachChild(node, visit);
|
|
56
|
+
};
|
|
57
|
+
visit(sourceFile);
|
|
58
|
+
// Check for any types
|
|
59
|
+
const anyTypeRegex = /:\s*any\b/g;
|
|
60
|
+
const anyMatches = content.match(anyTypeRegex);
|
|
61
|
+
if (anyMatches && anyMatches.length > 5) {
|
|
62
|
+
issues.push({
|
|
63
|
+
type: 'warning',
|
|
64
|
+
category: 'maintainability',
|
|
65
|
+
message: `Excessive use of 'any' type (${anyMatches.length} occurrences)`,
|
|
66
|
+
severity: 5,
|
|
67
|
+
suggestion: 'Replace with proper types or use unknown with type guards',
|
|
68
|
+
autoFixable: false,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
// Calculate scores
|
|
72
|
+
const maintainability = Math.max(0, 100 - metrics.complexity * 2 - metrics.maxNestingDepth * 5);
|
|
73
|
+
const reliability = Math.max(0, 100 - (anyMatches?.length || 0) * 5);
|
|
74
|
+
const security = 100; // Would need security-specific checks
|
|
75
|
+
const performance = 100; // Would need performance analysis
|
|
76
|
+
const issuePenalty = issues.reduce((sum, i) => sum + i.severity * 2, 0);
|
|
77
|
+
const overall = Math.max(0, Math.min(100, (maintainability + reliability + security + performance) / 4 - issuePenalty));
|
|
78
|
+
return {
|
|
79
|
+
overall: Math.round(overall),
|
|
80
|
+
maintainability: Math.round(maintainability),
|
|
81
|
+
reliability: Math.round(reliability),
|
|
82
|
+
security,
|
|
83
|
+
performance,
|
|
84
|
+
issues: issues.sort((a, b) => b.severity - a.severity),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
export const qualityAnalyzer = new QualityAnalyzer();
|
|
89
|
+
export default qualityAnalyzer;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
import { CodeMetrics } from './ComplexityCalculator.js';
|
|
3
|
+
export interface RefactoringSuggestion {
|
|
4
|
+
type: 'extract-method' | 'rename' | 'reorder' | 'simplify' | 'optimize-imports' | 'add-types';
|
|
5
|
+
description: string;
|
|
6
|
+
currentCode: string;
|
|
7
|
+
suggestedCode: string;
|
|
8
|
+
confidence: number;
|
|
9
|
+
impact: 'low' | 'medium' | 'high';
|
|
10
|
+
effort: 'quick' | 'moderate' | 'extensive';
|
|
11
|
+
benefits: string[];
|
|
12
|
+
}
|
|
13
|
+
export declare class RefactoringEngine {
|
|
14
|
+
suggest(ast: ts.SourceFile, metrics: CodeMetrics): RefactoringSuggestion[];
|
|
15
|
+
private findLongFunctions;
|
|
16
|
+
private findNestedConditionals;
|
|
17
|
+
private findAnyUsages;
|
|
18
|
+
}
|
|
19
|
+
export declare const refactoringEngine: RefactoringEngine;
|
|
20
|
+
export default refactoringEngine;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
export class RefactoringEngine {
|
|
3
|
+
suggest(ast, metrics) {
|
|
4
|
+
const suggestions = [];
|
|
5
|
+
// Suggest extracting long functions
|
|
6
|
+
if (metrics.complexity > 10) {
|
|
7
|
+
const longFunctions = this.findLongFunctions(ast);
|
|
8
|
+
for (const func of longFunctions) {
|
|
9
|
+
suggestions.push({
|
|
10
|
+
type: 'extract-method',
|
|
11
|
+
description: `Extract ${func.name} into smaller functions`,
|
|
12
|
+
currentCode: func.code,
|
|
13
|
+
suggestedCode: `// Suggested: Split into ${Math.ceil(func.lines / 20)} helper functions`,
|
|
14
|
+
confidence: 85,
|
|
15
|
+
impact: 'medium',
|
|
16
|
+
effort: 'moderate',
|
|
17
|
+
benefits: ['Reduced complexity', 'Better testability', 'Easier maintenance'],
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
// Simplify nested conditionals
|
|
22
|
+
const nestedConditionals = this.findNestedConditionals(ast);
|
|
23
|
+
for (const nested of nestedConditionals) {
|
|
24
|
+
suggestions.push({
|
|
25
|
+
type: 'simplify',
|
|
26
|
+
description: 'Simplify deeply nested conditionals',
|
|
27
|
+
currentCode: nested.code,
|
|
28
|
+
suggestedCode: '// Use early returns or extract into guard clauses',
|
|
29
|
+
confidence: 90,
|
|
30
|
+
impact: 'low',
|
|
31
|
+
effort: 'quick',
|
|
32
|
+
benefits: ['Improved readability', 'Reduced cognitive load'],
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
// Add types for any
|
|
36
|
+
const anyUsages = this.findAnyUsages(ast);
|
|
37
|
+
if (anyUsages.length > 0) {
|
|
38
|
+
suggestions.push({
|
|
39
|
+
type: 'add-types',
|
|
40
|
+
description: `Replace ${anyUsages.length} 'any' types with proper types`,
|
|
41
|
+
currentCode: anyUsages.map(a => a.code).join('\n'),
|
|
42
|
+
suggestedCode: '// Define proper interfaces or use unknown with type guards',
|
|
43
|
+
confidence: 80,
|
|
44
|
+
impact: 'medium',
|
|
45
|
+
effort: 'moderate',
|
|
46
|
+
benefits: ['Type safety', 'Better IDE support', 'Fewer runtime errors'],
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
return suggestions.sort((a, b) => b.confidence - a.confidence);
|
|
50
|
+
}
|
|
51
|
+
findLongFunctions(sourceFile) {
|
|
52
|
+
const functions = [];
|
|
53
|
+
const content = sourceFile.getFullText();
|
|
54
|
+
const visit = (node) => {
|
|
55
|
+
if (ts.isFunctionDeclaration(node) && node.name) {
|
|
56
|
+
const start = node.getStart(sourceFile);
|
|
57
|
+
const end = node.getEnd();
|
|
58
|
+
const code = content.substring(start, end);
|
|
59
|
+
const lines = code.split('\n').length;
|
|
60
|
+
if (lines > 30) {
|
|
61
|
+
functions.push({
|
|
62
|
+
name: node.name.text,
|
|
63
|
+
lines,
|
|
64
|
+
code: code.substring(0, 200) + '...',
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
ts.forEachChild(node, visit);
|
|
69
|
+
};
|
|
70
|
+
visit(sourceFile);
|
|
71
|
+
return functions;
|
|
72
|
+
}
|
|
73
|
+
findNestedConditionals(sourceFile) {
|
|
74
|
+
const nested = [];
|
|
75
|
+
const content = sourceFile.getFullText();
|
|
76
|
+
const visit = (node, depth = 0) => {
|
|
77
|
+
if (ts.isIfStatement(node)) {
|
|
78
|
+
if (depth > 3) {
|
|
79
|
+
const code = content.substring(node.getStart(sourceFile), node.getEnd());
|
|
80
|
+
nested.push({ depth, code: code.substring(0, 150) + '...' });
|
|
81
|
+
}
|
|
82
|
+
ts.forEachChild(node, n => visit(n, depth + 1));
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
ts.forEachChild(node, n => visit(n, depth));
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
visit(sourceFile);
|
|
89
|
+
return nested;
|
|
90
|
+
}
|
|
91
|
+
findAnyUsages(sourceFile) {
|
|
92
|
+
const usages = [];
|
|
93
|
+
const content = sourceFile.getFullText();
|
|
94
|
+
const visit = (node) => {
|
|
95
|
+
if (ts.isTypeReferenceNode(node) && node.typeName.getText(sourceFile) === 'any') {
|
|
96
|
+
usages.push({
|
|
97
|
+
code: content.substring(node.getStart(sourceFile), node.getEnd()),
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
ts.forEachChild(node, visit);
|
|
101
|
+
};
|
|
102
|
+
visit(sourceFile);
|
|
103
|
+
return usages;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
export const refactoringEngine = new RefactoringEngine();
|
|
107
|
+
export default refactoringEngine;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
export interface SymbolAnalysis {
|
|
3
|
+
name: string;
|
|
4
|
+
kind: 'function' | 'class' | 'interface' | 'method' | 'type';
|
|
5
|
+
params?: {
|
|
6
|
+
name: string;
|
|
7
|
+
type: string;
|
|
8
|
+
optional?: boolean;
|
|
9
|
+
}[];
|
|
10
|
+
returnType?: string;
|
|
11
|
+
isAsync?: boolean;
|
|
12
|
+
complexity?: number;
|
|
13
|
+
isExported: boolean;
|
|
14
|
+
documentation?: string;
|
|
15
|
+
methods?: SymbolAnalysis[];
|
|
16
|
+
properties?: {
|
|
17
|
+
name: string;
|
|
18
|
+
type: string;
|
|
19
|
+
optional?: boolean;
|
|
20
|
+
}[];
|
|
21
|
+
}
|
|
22
|
+
export declare class SymbolAnalyzer {
|
|
23
|
+
analyze(sourceFile: ts.SourceFile): SymbolAnalysis[];
|
|
24
|
+
private analyzeFunction;
|
|
25
|
+
private analyzeClass;
|
|
26
|
+
private analyzeInterface;
|
|
27
|
+
private extractJSDoc;
|
|
28
|
+
}
|
|
29
|
+
export declare const symbolAnalyzer: SymbolAnalyzer;
|
|
30
|
+
export default symbolAnalyzer;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
export class SymbolAnalyzer {
|
|
3
|
+
analyze(sourceFile) {
|
|
4
|
+
const symbols = [];
|
|
5
|
+
const visit = (node) => {
|
|
6
|
+
if (ts.isFunctionDeclaration(node) && node.name) {
|
|
7
|
+
const symbol = this.analyzeFunction(node, sourceFile);
|
|
8
|
+
if (symbol)
|
|
9
|
+
symbols.push(symbol);
|
|
10
|
+
}
|
|
11
|
+
else if (ts.isClassDeclaration(node) && node.name) {
|
|
12
|
+
const symbol = this.analyzeClass(node, sourceFile);
|
|
13
|
+
if (symbol)
|
|
14
|
+
symbols.push(symbol);
|
|
15
|
+
}
|
|
16
|
+
else if (ts.isInterfaceDeclaration(node)) {
|
|
17
|
+
const symbol = this.analyzeInterface(node, sourceFile);
|
|
18
|
+
if (symbol)
|
|
19
|
+
symbols.push(symbol);
|
|
20
|
+
}
|
|
21
|
+
ts.forEachChild(node, visit);
|
|
22
|
+
};
|
|
23
|
+
visit(sourceFile);
|
|
24
|
+
return symbols;
|
|
25
|
+
}
|
|
26
|
+
analyzeFunction(node, sourceFile) {
|
|
27
|
+
if (!node.name)
|
|
28
|
+
return null;
|
|
29
|
+
const params = node.parameters.map(p => ({
|
|
30
|
+
name: p.name.getText(sourceFile),
|
|
31
|
+
type: p.type?.getText(sourceFile) || 'unknown',
|
|
32
|
+
optional: !!p.questionToken,
|
|
33
|
+
}));
|
|
34
|
+
const returnType = node.type?.getText(sourceFile) || 'inferred';
|
|
35
|
+
const isAsync = node.modifiers?.some(m => m.kind === ts.SyntaxKind.AsyncKeyword) || false;
|
|
36
|
+
// Calculate function complexity
|
|
37
|
+
let complexity = 1;
|
|
38
|
+
const countComplexity = (n) => {
|
|
39
|
+
if (ts.isIfStatement(n) ||
|
|
40
|
+
ts.isWhileStatement(n) ||
|
|
41
|
+
ts.isForStatement(n) ||
|
|
42
|
+
ts.isConditionalExpression(n)) {
|
|
43
|
+
complexity++;
|
|
44
|
+
}
|
|
45
|
+
ts.forEachChild(n, countComplexity);
|
|
46
|
+
};
|
|
47
|
+
countComplexity(node);
|
|
48
|
+
return {
|
|
49
|
+
name: node.name.text,
|
|
50
|
+
kind: 'function',
|
|
51
|
+
params,
|
|
52
|
+
returnType,
|
|
53
|
+
isAsync,
|
|
54
|
+
complexity,
|
|
55
|
+
isExported: node.modifiers?.some(m => m.kind === ts.SyntaxKind.ExportKeyword) || false,
|
|
56
|
+
documentation: this.extractJSDoc(node, sourceFile),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
analyzeClass(node, sourceFile) {
|
|
60
|
+
if (!node.name)
|
|
61
|
+
return null;
|
|
62
|
+
const methods = [];
|
|
63
|
+
const properties = [];
|
|
64
|
+
node.members.forEach(member => {
|
|
65
|
+
if (ts.isMethodDeclaration(member) && member.name) {
|
|
66
|
+
methods.push({
|
|
67
|
+
name: member.name.getText(sourceFile),
|
|
68
|
+
kind: 'method',
|
|
69
|
+
params: member.parameters.map(p => ({
|
|
70
|
+
name: p.name.getText(sourceFile),
|
|
71
|
+
type: p.type?.getText(sourceFile) || 'unknown',
|
|
72
|
+
})),
|
|
73
|
+
returnType: member.type?.getText(sourceFile) || 'void',
|
|
74
|
+
isAsync: member.modifiers?.some(m => m.kind === ts.SyntaxKind.AsyncKeyword) || false,
|
|
75
|
+
complexity: 1,
|
|
76
|
+
isExported: false,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
else if (ts.isPropertyDeclaration(member) && member.name) {
|
|
80
|
+
properties.push({
|
|
81
|
+
name: member.name.getText(sourceFile),
|
|
82
|
+
type: member.type?.getText(sourceFile) || 'unknown',
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
return {
|
|
87
|
+
name: node.name.text,
|
|
88
|
+
kind: 'class',
|
|
89
|
+
methods,
|
|
90
|
+
properties,
|
|
91
|
+
isExported: node.modifiers?.some(m => m.kind === ts.SyntaxKind.ExportKeyword) || false,
|
|
92
|
+
documentation: this.extractJSDoc(node, sourceFile),
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
analyzeInterface(node, sourceFile) {
|
|
96
|
+
const properties = node.members.map(member => {
|
|
97
|
+
if (ts.isPropertySignature(member) && member.name) {
|
|
98
|
+
return {
|
|
99
|
+
name: member.name.getText(sourceFile),
|
|
100
|
+
type: member.type?.getText(sourceFile) || 'unknown',
|
|
101
|
+
optional: !!member.questionToken,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
return null;
|
|
105
|
+
}).filter(p => p !== null);
|
|
106
|
+
return {
|
|
107
|
+
name: node.name.text,
|
|
108
|
+
kind: 'interface',
|
|
109
|
+
properties,
|
|
110
|
+
isExported: node.modifiers?.some(m => m.kind === ts.SyntaxKind.ExportKeyword) || false,
|
|
111
|
+
documentation: this.extractJSDoc(node, sourceFile),
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
extractJSDoc(node, sourceFile) {
|
|
115
|
+
const jsDoc = node.jsDoc;
|
|
116
|
+
if (jsDoc && jsDoc.length > 0) {
|
|
117
|
+
return jsDoc[0].comment?.toString();
|
|
118
|
+
}
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
export const symbolAnalyzer = new SymbolAnalyzer();
|
|
123
|
+
export default symbolAnalyzer;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { ComplexityCalculator, complexityCalculator } from './ComplexityCalculator.js';
|
|
2
|
+
export type { CodeMetrics } from './ComplexityCalculator.js';
|
|
3
|
+
export { QualityAnalyzer, qualityAnalyzer } from './QualityAnalyzer.js';
|
|
4
|
+
export type { QualityIssue, CodeQualityScore } from './QualityAnalyzer.js';
|
|
5
|
+
export { SymbolAnalyzer, symbolAnalyzer } from './SymbolAnalyzer.js';
|
|
6
|
+
export type { SymbolAnalysis } from './SymbolAnalyzer.js';
|
|
7
|
+
export { RefactoringEngine, refactoringEngine } from './RefactoringEngine.js';
|
|
8
|
+
export type { RefactoringSuggestion } from './RefactoringEngine.js';
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { ComplexityCalculator, complexityCalculator } from './ComplexityCalculator.js';
|
|
2
|
+
export { QualityAnalyzer, qualityAnalyzer } from './QualityAnalyzer.js';
|
|
3
|
+
export { SymbolAnalyzer, symbolAnalyzer } from './SymbolAnalyzer.js';
|
|
4
|
+
export { RefactoringEngine, refactoringEngine } from './RefactoringEngine.js';
|
package/dist/coding.test.js
CHANGED
|
@@ -96,6 +96,10 @@ describe('Deep Coding Tools', () => {
|
|
|
96
96
|
});
|
|
97
97
|
});
|
|
98
98
|
describe('deep_code_edit', () => {
|
|
99
|
+
beforeEach(() => {
|
|
100
|
+
// Mock fs.stat for file size checks
|
|
101
|
+
fs.stat.mockResolvedValue({ size: 100 });
|
|
102
|
+
});
|
|
99
103
|
it('should error if target text is not found', async () => {
|
|
100
104
|
registerCodingTools(mockServer, mockGraph);
|
|
101
105
|
const handler = registeredTools['deep_code_edit'];
|