@gotza02/sequential-thinking 10000.1.6 → 10000.1.7

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.
@@ -0,0 +1,7 @@
1
+ /**
2
+ * INTELLIGENT CODE TOOLS
3
+ * AI-powered code analysis, semantic search, and smart refactoring for MCP
4
+ */
5
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
6
+ import { ProjectKnowledgeGraph } from '../graph.js';
7
+ export declare function registerIntelligentCodeTools(server: McpServer, graph: ProjectKnowledgeGraph): void;
@@ -0,0 +1,387 @@
1
+ /**
2
+ * INTELLIGENT CODE TOOLS
3
+ * AI-powered code analysis, semantic search, and smart refactoring for MCP
4
+ */
5
+ import { z } from "zod";
6
+ import { getIntelligentAnalyzer } from '../intelligent-code.js';
7
+ import { validatePath } from "../utils.js";
8
+ import * as fs from 'fs/promises';
9
+ export function registerIntelligentCodeTools(server, graph) {
10
+ const analyzer = getIntelligentAnalyzer(graph);
11
+ // 1. intelligent_code_analyze
12
+ server.tool("intelligent_code_analyze", "Deep AI-powered code analysis with metrics, quality scoring, and issue detection. Provides actionable recommendations.", {
13
+ filePath: z.string().describe("Path to the file to analyze"),
14
+ includeSuggestions: z.boolean().optional().default(true).describe("Include refactoring suggestions"),
15
+ detailLevel: z.enum(['basic', 'standard', 'comprehensive']).optional().default('standard').describe("Level of analysis detail")
16
+ }, async ({ filePath, includeSuggestions, detailLevel }) => {
17
+ try {
18
+ const absolutePath = validatePath(filePath);
19
+ const { metrics, quality, symbols } = await analyzer.analyzeFile(absolutePath);
20
+ let output = `šŸ” INTELLIGENT CODE ANALYSIS: ${filePath}\n`;
21
+ output += `═`.repeat(60) + '\n\n';
22
+ // Quality Score Dashboard
23
+ output += `šŸ“Š QUALITY SCORE\n`;
24
+ output += ` Overall: ${getScoreEmoji(quality.overall)} ${quality.overall}/100\n`;
25
+ output += ` Maintainability: ${getScoreEmoji(quality.maintainability)} ${quality.maintainability}/100\n`;
26
+ output += ` Reliability: ${getScoreEmoji(quality.reliability)} ${quality.reliability}/100\n`;
27
+ output += ` Security: ${getScoreEmoji(quality.security)} ${quality.security}/100\n`;
28
+ output += ` Performance: ${getScoreEmoji(quality.performance)} ${quality.performance}/100\n\n`;
29
+ // Metrics
30
+ if (detailLevel !== 'basic') {
31
+ output += `šŸ“ˆ CODE METRICS\n`;
32
+ output += ` Lines of Code: ${metrics.linesOfCode}\n`;
33
+ output += ` Functions: ${metrics.functionCount}\n`;
34
+ output += ` Cyclomatic Complexity: ${metrics.complexity}\n`;
35
+ output += ` Max Nesting Depth: ${metrics.maxNestingDepth}\n`;
36
+ output += ` Comment Ratio: ${(metrics.commentRatio * 100).toFixed(1)}%\n\n`;
37
+ }
38
+ // Issues
39
+ if (quality.issues.length > 0) {
40
+ output += `āš ļø ISSUES FOUND (${quality.issues.length})\n`;
41
+ const criticalIssues = quality.issues.filter(i => i.severity >= 7);
42
+ const warnings = quality.issues.filter(i => i.severity >= 4 && i.severity < 7);
43
+ const infos = quality.issues.filter(i => i.severity < 4);
44
+ if (criticalIssues.length > 0) {
45
+ output += `\n šŸ”“ Critical:\n`;
46
+ criticalIssues.forEach(i => {
47
+ output += ` • ${i.message}\n`;
48
+ if (i.suggestion)
49
+ output += ` šŸ’” ${i.suggestion}\n`;
50
+ if (i.line)
51
+ output += ` šŸ“ Line ${i.line}\n`;
52
+ });
53
+ }
54
+ if (warnings.length > 0) {
55
+ output += `\n 🟔 Warnings:\n`;
56
+ warnings.forEach(i => {
57
+ output += ` • ${i.message}\n`;
58
+ if (i.suggestion)
59
+ output += ` šŸ’” ${i.suggestion}\n`;
60
+ });
61
+ }
62
+ if (detailLevel === 'comprehensive' && infos.length > 0) {
63
+ output += `\n šŸ”µ Suggestions:\n`;
64
+ infos.forEach(i => {
65
+ output += ` • ${i.message}\n`;
66
+ });
67
+ }
68
+ output += '\n';
69
+ }
70
+ // Symbols overview
71
+ if (detailLevel === 'comprehensive' && symbols.length > 0) {
72
+ output += `šŸ”£ SYMBOLS (${symbols.length})\n`;
73
+ symbols.forEach(s => {
74
+ const icon = s.kind === 'function' ? 'āš™ļø' : s.kind === 'class' ? 'šŸ—ļø' : s.kind === 'interface' ? 'šŸ“‹' : 'šŸ”¹';
75
+ output += ` ${icon} ${s.name} (${s.kind})\n`;
76
+ if (s.documentation) {
77
+ output += ` "${s.documentation.substring(0, 100)}..."\n`;
78
+ }
79
+ });
80
+ output += '\n';
81
+ }
82
+ // Refactoring suggestions
83
+ if (includeSuggestions && detailLevel !== 'basic') {
84
+ const suggestions = await analyzer.suggestRefactoring(absolutePath);
85
+ if (suggestions.length > 0) {
86
+ output += `✨ REFACTORING SUGGESTIONS (${suggestions.length})\n`;
87
+ suggestions.slice(0, 5).forEach((s, idx) => {
88
+ output += `\n ${idx + 1}. ${s.type.toUpperCase()} (${s.confidence}% confidence)\n`;
89
+ output += ` ${s.description}\n`;
90
+ output += ` Impact: ${s.impact} | Effort: ${s.effort}\n`;
91
+ output += ` Benefits: ${s.benefits.join(', ')}\n`;
92
+ });
93
+ }
94
+ }
95
+ return { content: [{ type: "text", text: output }] };
96
+ }
97
+ catch (error) {
98
+ return {
99
+ content: [{ type: "text", text: `Analysis Error: ${error instanceof Error ? error.message : String(error)}` }],
100
+ isError: true
101
+ };
102
+ }
103
+ });
104
+ // 2. intelligent_impact_analysis
105
+ server.tool("intelligent_impact_analysis", "Predict the impact of code changes. Shows affected files, risk score, and test recommendations.", {
106
+ filePath: z.string().describe("Path to the file being modified"),
107
+ changeDescription: z.string().optional().describe("Description of the planned changes (helps risk assessment)")
108
+ }, async ({ filePath, changeDescription }) => {
109
+ try {
110
+ const absolutePath = validatePath(filePath);
111
+ const impact = await analyzer.analyzeImpact(absolutePath, changeDescription);
112
+ let output = `šŸŽÆ IMPACT ANALYSIS: ${filePath}\n`;
113
+ output += `═`.repeat(60) + '\n\n';
114
+ // Risk assessment
115
+ const riskEmoji = impact.riskScore > 70 ? 'šŸ”“' : impact.riskScore > 40 ? '🟔' : '🟢';
116
+ output += `${riskEmoji} RISK SCORE: ${impact.riskScore}/100\n`;
117
+ if (impact.breakingChanges) {
118
+ output += ` āš ļø WARNING: Potential breaking changes detected!\n`;
119
+ }
120
+ output += ` Estimated Review Time: ${impact.estimatedReviewTime} minutes\n\n`;
121
+ // Direct impacts
122
+ if (impact.directImpacts.length > 0) {
123
+ output += `šŸ“Ž DIRECT IMPACTS (${impact.directImpacts.length} files)\n`;
124
+ output += ` These files import the modified file:\n`;
125
+ impact.directImpacts.forEach(f => {
126
+ output += ` • ${f}\n`;
127
+ });
128
+ output += '\n';
129
+ }
130
+ // Indirect impacts
131
+ if (impact.indirectImpacts.length > 0) {
132
+ output += `šŸ”— INDIRECT IMPACTS (${impact.indirectImpacts.length} files)\n`;
133
+ output += ` These files are transitively affected:\n`;
134
+ impact.indirectImpacts.slice(0, 10).forEach(f => {
135
+ output += ` • ${f}\n`;
136
+ });
137
+ if (impact.indirectImpacts.length > 10) {
138
+ output += ` ... and ${impact.indirectImpacts.length - 10} more\n`;
139
+ }
140
+ output += '\n';
141
+ }
142
+ // Test recommendations
143
+ if (impact.testFiles.length > 0) {
144
+ output += `🧪 TEST FILES TO RUN (${impact.testFiles.length})\n`;
145
+ impact.testFiles.forEach(f => {
146
+ output += ` • ${f}\n`;
147
+ });
148
+ output += '\n';
149
+ }
150
+ else {
151
+ output += `āš ļø No test files found for this module\n\n`;
152
+ }
153
+ // Recommendations
154
+ output += `šŸ’” RECOMMENDATIONS\n`;
155
+ if (impact.riskScore > 70) {
156
+ output += ` • Consider breaking this into smaller changes\n`;
157
+ output += ` • Add comprehensive tests before changing\n`;
158
+ output += ` • Request code review from domain expert\n`;
159
+ }
160
+ else if (impact.riskScore > 40) {
161
+ output += ` • Run the recommended test suite\n`;
162
+ output += ` • Update documentation if API changes\n`;
163
+ }
164
+ else {
165
+ output += ` • Low risk change, standard review process\n`;
166
+ }
167
+ return { content: [{ type: "text", text: output }] };
168
+ }
169
+ catch (error) {
170
+ return {
171
+ content: [{ type: "text", text: `Impact Analysis Error: ${error instanceof Error ? error.message : String(error)}` }],
172
+ isError: true
173
+ };
174
+ }
175
+ });
176
+ // 3. intelligent_semantic_search
177
+ server.tool("intelligent_semantic_search", "Search code by concept/meaning, not just text. Finds related code even with different naming.", {
178
+ query: z.string().describe("What you're looking for (e.g., 'authentication middleware', 'database connection pool')"),
179
+ filePattern: z.string().optional().default("*.ts").describe("File pattern to search (e.g., '*.ts', '*.js')"),
180
+ maxResults: z.number().optional().default(10).describe("Maximum results to return")
181
+ }, async ({ query, filePattern, maxResults }) => {
182
+ try {
183
+ const results = await analyzer.semanticSearch(query, { filePattern, maxResults });
184
+ if (results.length === 0) {
185
+ return {
186
+ content: [{ type: "text", text: `No results found for "${query}"` }]
187
+ };
188
+ }
189
+ let output = `šŸ” SEMANTIC SEARCH: "${query}"\n`;
190
+ output += '═'.repeat(60) + '\n\n';
191
+ results.forEach((result, idx) => {
192
+ const relevanceBar = 'ā–ˆ'.repeat(Math.floor(result.relevance * 10)) + 'ā–‘'.repeat(10 - Math.floor(result.relevance * 10));
193
+ output += `${idx + 1}. ${result.filePath}\n`;
194
+ output += ` Relevance: [${relevanceBar}] ${(result.relevance * 100).toFixed(0)}%\n`;
195
+ output += ` Context: ${result.context}\n`;
196
+ if (result.matchedConcepts.length > 0) {
197
+ output += ` Matched: ${result.matchedConcepts.join(', ')}\n`;
198
+ }
199
+ output += `\n \`\`\`typescript\n`;
200
+ output += ` ${result.codeSnippet.split('\n').join('\n ')}\n`;
201
+ output += ` \`\`\`\n\n`;
202
+ });
203
+ return { content: [{ type: "text", text: output }] };
204
+ }
205
+ catch (error) {
206
+ return {
207
+ content: [{ type: "text", text: `Search Error: ${error instanceof Error ? error.message : String(error)}` }],
208
+ isError: true
209
+ };
210
+ }
211
+ });
212
+ // 4. intelligent_refactor_suggest
213
+ server.tool("intelligent_refactor_suggest", "Get intelligent refactoring suggestions with code examples and impact assessment.", {
214
+ filePath: z.string().describe("Path to the file to analyze for refactoring"),
215
+ minConfidence: z.number().optional().default(70).describe("Minimum confidence threshold (0-100)")
216
+ }, async ({ filePath, minConfidence }) => {
217
+ try {
218
+ const absolutePath = validatePath(filePath);
219
+ const suggestions = await analyzer.suggestRefactoring(absolutePath);
220
+ const filtered = suggestions.filter(s => s.confidence >= minConfidence);
221
+ if (filtered.length === 0) {
222
+ return {
223
+ content: [{ type: "text", text: `No high-confidence refactoring suggestions found for ${filePath}` }]
224
+ };
225
+ }
226
+ let output = `✨ REFACTORING SUGGESTIONS: ${filePath}\n`;
227
+ output += `═`.repeat(60) + '\n\n';
228
+ filtered.forEach((s, idx) => {
229
+ const confidenceEmoji = s.confidence >= 90 ? 'šŸ”„' : s.confidence >= 75 ? '⭐' : 'šŸ’”';
230
+ output += `${confidenceEmoji} SUGGESTION ${idx + 1}: ${s.type.toUpperCase()}\n`;
231
+ output += ` Confidence: ${s.confidence}% | Impact: ${s.impact} | Effort: ${s.effort}\n`;
232
+ output += ` ${s.description}\n\n`;
233
+ output += ` Benefits:\n`;
234
+ s.benefits.forEach(b => {
235
+ output += ` āœ“ ${b}\n`;
236
+ });
237
+ output += `\n CURRENT CODE:\n`;
238
+ output += ` \`\`\`typescript\n`;
239
+ output += ` ${s.currentCode.split('\n').join('\n ')}\n`;
240
+ output += ` \`\`\`\n\n`;
241
+ output += ` SUGGESTED:\n`;
242
+ output += ` \`\`\`typescript\n`;
243
+ output += ` ${s.suggestedCode.split('\n').join('\n ')}\n`;
244
+ output += ` \`\`\`\n`;
245
+ output += '\n' + '─'.repeat(60) + '\n\n';
246
+ });
247
+ return { content: [{ type: "text", text: output }] };
248
+ }
249
+ catch (error) {
250
+ return {
251
+ content: [{ type: "text", text: `Refactoring Error: ${error instanceof Error ? error.message : String(error)}` }],
252
+ isError: true
253
+ };
254
+ }
255
+ });
256
+ // 5. intelligent_code_compare
257
+ server.tool("intelligent_code_compare", "Compare two code snippets or files with detailed difference analysis.", {
258
+ original: z.string().describe("Original code or file path"),
259
+ modified: z.string().describe("Modified code or file path"),
260
+ isFilePath: z.boolean().optional().default(false).describe("Whether inputs are file paths")
261
+ }, async ({ original, modified, isFilePath }) => {
262
+ try {
263
+ let originalCode;
264
+ let modifiedCode;
265
+ if (isFilePath) {
266
+ originalCode = await fs.readFile(validatePath(original), 'utf-8');
267
+ modifiedCode = await fs.readFile(validatePath(modified), 'utf-8');
268
+ }
269
+ else {
270
+ originalCode = original;
271
+ modifiedCode = modified;
272
+ }
273
+ // Simple line-by-line comparison
274
+ const originalLines = originalCode.split('\n');
275
+ const modifiedLines = modifiedCode.split('\n');
276
+ let added = 0;
277
+ let removed = 0;
278
+ let modified_lines = 0;
279
+ const maxLines = Math.max(originalLines.length, modifiedLines.length);
280
+ const diff = [];
281
+ for (let i = 0; i < maxLines; i++) {
282
+ const orig = originalLines[i] || '';
283
+ const mod = modifiedLines[i] || '';
284
+ if (orig === mod) {
285
+ diff.push(` ${orig}`);
286
+ }
287
+ else if (!orig) {
288
+ added++;
289
+ diff.push(`+${mod}`);
290
+ }
291
+ else if (!mod) {
292
+ removed++;
293
+ diff.push(`-${orig}`);
294
+ }
295
+ else {
296
+ modified_lines++;
297
+ diff.push(`-${orig}`);
298
+ diff.push(`+${mod}`);
299
+ }
300
+ }
301
+ let output = `šŸ“Š CODE COMPARISON\n`;
302
+ output += `═`.repeat(60) + '\n\n';
303
+ output += `STATISTICS:\n`;
304
+ output += ` Lines Added: +${added}\n`;
305
+ output += ` Lines Removed: -${removed}\n`;
306
+ output += ` Lines Modified: ~${modified_lines}\n`;
307
+ output += ` Net Change: ${modifiedLines.length - originalLines.length > 0 ? '+' : ''}${modifiedLines.length - originalLines.length}\n\n`;
308
+ output += `DIFF:\n`;
309
+ output += `\`\`\`diff\n`;
310
+ output += diff.slice(0, 100).join('\n');
311
+ if (diff.length > 100) {
312
+ output += `\n... (${diff.length - 100} more lines)`;
313
+ }
314
+ output += `\n\`\`\`\n`;
315
+ return { content: [{ type: "text", text: output }] };
316
+ }
317
+ catch (error) {
318
+ return {
319
+ content: [{ type: "text", text: `Comparison Error: ${error instanceof Error ? error.message : String(error)}` }],
320
+ isError: true
321
+ };
322
+ }
323
+ });
324
+ // 6. intelligent_code_autofix
325
+ server.tool("intelligent_code_autofix", "Automatically fix common code issues like trailing whitespace, missing semicolons, and optimize imports.", {
326
+ filePath: z.string().describe("Path to the file to fix"),
327
+ fixTrailingWhitespace: z.boolean().optional().default(true).describe("Remove trailing whitespace"),
328
+ fixMissingSemicolons: z.boolean().optional().default(false).describe("Add missing semicolons (experimental)"),
329
+ optimizeImports: z.boolean().optional().default(false).describe("Sort and deduplicate imports"),
330
+ dryRun: z.boolean().optional().default(true).describe("Preview changes without applying")
331
+ }, async ({ filePath, fixTrailingWhitespace, fixMissingSemicolons, optimizeImports, dryRun }) => {
332
+ try {
333
+ const result = await analyzer.autoFix(filePath, {
334
+ fixTrailingWhitespace,
335
+ fixMissingSemicolons,
336
+ optimizeImports,
337
+ dryRun
338
+ });
339
+ let output = `šŸ”§ CODE AUTO-FIX: ${filePath}\n`;
340
+ output += `═`.repeat(60) + '\n\n';
341
+ if (result.fixes.length === 0) {
342
+ output += `āœ… No issues found! File is clean.\n`;
343
+ return { content: [{ type: "text", text: output }] };
344
+ }
345
+ output += `šŸ“Š SUMMARY:\n`;
346
+ output += ` Total fixes: ${result.fixes.length}\n`;
347
+ output += ` Mode: ${dryRun ? 'šŸ” DRY RUN (preview only)' : 'āœ… APPLIED'}\n\n`;
348
+ // Group fixes by type
349
+ const grouped = result.fixes.reduce((acc, fix) => {
350
+ acc[fix.type] = acc[fix.type] || [];
351
+ acc[fix.type].push(fix);
352
+ return acc;
353
+ }, {});
354
+ output += `šŸ“ FIXES BY TYPE:\n`;
355
+ for (const [type, fixes] of Object.entries(grouped)) {
356
+ output += `\n ${type.toUpperCase()} (${fixes.length}):\n`;
357
+ fixes.slice(0, 5).forEach(fix => {
358
+ output += ` Line ${fix.line}: ${fix.original.substring(0, 40)}${fix.original.length > 40 ? '...' : ''}\n`;
359
+ output += ` → ${fix.fixed.substring(0, 40)}${fix.fixed.length > 40 ? '...' : ''}\n`;
360
+ });
361
+ if (fixes.length > 5) {
362
+ output += ` ... and ${fixes.length - 5} more\n`;
363
+ }
364
+ }
365
+ if (dryRun && result.fixes.length > 0) {
366
+ output += `\nšŸ’” To apply these fixes, set dryRun: false\n`;
367
+ }
368
+ return { content: [{ type: "text", text: output }] };
369
+ }
370
+ catch (error) {
371
+ return {
372
+ content: [{ type: "text", text: `Auto-fix Error: ${error instanceof Error ? error.message : String(error)}` }],
373
+ isError: true
374
+ };
375
+ }
376
+ });
377
+ }
378
+ // Helper function
379
+ function getScoreEmoji(score) {
380
+ if (score >= 90)
381
+ return '🟢';
382
+ if (score >= 70)
383
+ return '🟔';
384
+ if (score >= 50)
385
+ return '🟠';
386
+ return 'šŸ”“';
387
+ }