erosolar-cli 2.0.5 → 2.1.2

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.
Files changed (167) hide show
  1. package/agents/erosolar-security.rules.json +147 -0
  2. package/dist/capabilities/enhancedAnalysisCapability.d.ts +13 -0
  3. package/dist/capabilities/enhancedAnalysisCapability.d.ts.map +1 -0
  4. package/dist/capabilities/enhancedAnalysisCapability.js +20 -0
  5. package/dist/capabilities/enhancedAnalysisCapability.js.map +1 -0
  6. package/dist/capabilities/offsecOpsCapability.d.ts +6 -0
  7. package/dist/capabilities/offsecOpsCapability.d.ts.map +1 -0
  8. package/dist/capabilities/offsecOpsCapability.js +20 -0
  9. package/dist/capabilities/offsecOpsCapability.js.map +1 -0
  10. package/dist/capabilities/offsecSearchCapability.d.ts +12 -0
  11. package/dist/capabilities/offsecSearchCapability.d.ts.map +1 -0
  12. package/dist/capabilities/offsecSearchCapability.js +27 -0
  13. package/dist/capabilities/offsecSearchCapability.js.map +1 -0
  14. package/dist/capabilities/taoCapability.d.ts +6 -0
  15. package/dist/capabilities/taoCapability.d.ts.map +1 -0
  16. package/dist/capabilities/taoCapability.js +20 -0
  17. package/dist/capabilities/taoCapability.js.map +1 -0
  18. package/dist/capabilities/toolRegistry.d.ts +2 -1
  19. package/dist/capabilities/toolRegistry.d.ts.map +1 -1
  20. package/dist/capabilities/toolRegistry.js +6 -1
  21. package/dist/capabilities/toolRegistry.js.map +1 -1
  22. package/dist/contracts/agent-schemas.json +18 -19
  23. package/dist/contracts/tools.schema.json +38 -8
  24. package/dist/core/agent.js +4 -4
  25. package/dist/core/agent.js.map +1 -1
  26. package/dist/core/alphaZeroEngine.js +1 -1
  27. package/dist/core/alphaZeroEngine.js.map +1 -1
  28. package/dist/core/alphaZeroModular.js +2 -2
  29. package/dist/core/alphaZeroModular.js.map +1 -1
  30. package/dist/core/contextManager.d.ts +8 -2
  31. package/dist/core/contextManager.d.ts.map +1 -1
  32. package/dist/core/contextManager.js +15 -2
  33. package/dist/core/contextManager.js.map +1 -1
  34. package/dist/core/costTracker.js +1 -1
  35. package/dist/core/costTracker.js.map +1 -1
  36. package/dist/core/deepBugAnalyzer.d.ts +128 -0
  37. package/dist/core/deepBugAnalyzer.d.ts.map +1 -0
  38. package/dist/core/deepBugAnalyzer.js +406 -0
  39. package/dist/core/deepBugAnalyzer.js.map +1 -0
  40. package/dist/core/hypothesisEngine.d.ts +113 -0
  41. package/dist/core/hypothesisEngine.d.ts.map +1 -0
  42. package/dist/core/hypothesisEngine.js +264 -0
  43. package/dist/core/hypothesisEngine.js.map +1 -0
  44. package/dist/core/intelligentSummarizer.d.ts +79 -0
  45. package/dist/core/intelligentSummarizer.d.ts.map +1 -0
  46. package/dist/core/intelligentSummarizer.js +273 -0
  47. package/dist/core/intelligentSummarizer.js.map +1 -0
  48. package/dist/core/memorySystem.js +2 -2
  49. package/dist/core/memorySystem.js.map +1 -1
  50. package/dist/core/offsecAlphaZero.d.ts +3 -0
  51. package/dist/core/offsecAlphaZero.d.ts.map +1 -1
  52. package/dist/core/offsecAlphaZero.js +166 -5
  53. package/dist/core/offsecAlphaZero.js.map +1 -1
  54. package/dist/core/productTestHarness.d.ts +113 -0
  55. package/dist/core/productTestHarness.d.ts.map +1 -0
  56. package/dist/core/productTestHarness.js +345 -0
  57. package/dist/core/productTestHarness.js.map +1 -0
  58. package/dist/core/securityAssessment.js +1 -1
  59. package/dist/core/securityAssessment.js.map +1 -1
  60. package/dist/core/toolPatternAnalyzer.d.ts +87 -0
  61. package/dist/core/toolPatternAnalyzer.d.ts.map +1 -0
  62. package/dist/core/toolPatternAnalyzer.js +272 -0
  63. package/dist/core/toolPatternAnalyzer.js.map +1 -0
  64. package/dist/core/updateChecker.js +3 -3
  65. package/dist/core/updateChecker.js.map +1 -1
  66. package/dist/mcp/sseClient.js +1 -1
  67. package/dist/mcp/sseClient.js.map +1 -1
  68. package/dist/plugins/tools/enhancedAnalysis/enhancedAnalysisPlugin.d.ts +3 -0
  69. package/dist/plugins/tools/enhancedAnalysis/enhancedAnalysisPlugin.d.ts.map +1 -0
  70. package/dist/plugins/tools/enhancedAnalysis/enhancedAnalysisPlugin.js +14 -0
  71. package/dist/plugins/tools/enhancedAnalysis/enhancedAnalysisPlugin.js.map +1 -0
  72. package/dist/plugins/tools/enhancedCodeIntelligence/enhancedCodeIntelligencePlugin.d.ts +3 -0
  73. package/dist/plugins/tools/enhancedCodeIntelligence/enhancedCodeIntelligencePlugin.d.ts.map +1 -0
  74. package/dist/plugins/tools/enhancedCodeIntelligence/enhancedCodeIntelligencePlugin.js +12 -0
  75. package/dist/plugins/tools/enhancedCodeIntelligence/enhancedCodeIntelligencePlugin.js.map +1 -0
  76. package/dist/plugins/tools/enhancedDevWorkflow/enhancedDevWorkflowPlugin.d.ts +3 -0
  77. package/dist/plugins/tools/enhancedDevWorkflow/enhancedDevWorkflowPlugin.d.ts.map +1 -0
  78. package/dist/plugins/tools/enhancedDevWorkflow/enhancedDevWorkflowPlugin.js +12 -0
  79. package/dist/plugins/tools/enhancedDevWorkflow/enhancedDevWorkflowPlugin.js.map +1 -0
  80. package/dist/plugins/tools/nodeDefaults.d.ts.map +1 -1
  81. package/dist/plugins/tools/nodeDefaults.js +12 -0
  82. package/dist/plugins/tools/nodeDefaults.js.map +1 -1
  83. package/dist/plugins/tools/offsec/offsecOpsPlugin.d.ts +3 -0
  84. package/dist/plugins/tools/offsec/offsecOpsPlugin.d.ts.map +1 -0
  85. package/dist/plugins/tools/offsec/offsecOpsPlugin.js +10 -0
  86. package/dist/plugins/tools/offsec/offsecOpsPlugin.js.map +1 -0
  87. package/dist/plugins/tools/offsec/offsecSearchPlugin.d.ts +3 -0
  88. package/dist/plugins/tools/offsec/offsecSearchPlugin.d.ts.map +1 -0
  89. package/dist/plugins/tools/offsec/offsecSearchPlugin.js +12 -0
  90. package/dist/plugins/tools/offsec/offsecSearchPlugin.js.map +1 -0
  91. package/dist/plugins/tools/tao/taoPlugin.d.ts +3 -0
  92. package/dist/plugins/tools/tao/taoPlugin.d.ts.map +1 -0
  93. package/dist/plugins/tools/tao/taoPlugin.js +10 -0
  94. package/dist/plugins/tools/tao/taoPlugin.js.map +1 -0
  95. package/dist/shell/composableMessage.js +2 -2
  96. package/dist/shell/composableMessage.js.map +1 -1
  97. package/dist/shell/interactiveShell.d.ts +6 -0
  98. package/dist/shell/interactiveShell.d.ts.map +1 -1
  99. package/dist/shell/interactiveShell.js +50 -15
  100. package/dist/shell/interactiveShell.js.map +1 -1
  101. package/dist/shell/shellApp.js +1 -1
  102. package/dist/shell/shellApp.js.map +1 -1
  103. package/dist/shell/systemPrompt.d.ts.map +1 -1
  104. package/dist/shell/systemPrompt.js +3 -0
  105. package/dist/shell/systemPrompt.js.map +1 -1
  106. package/dist/tools/buildTools.js +1 -1
  107. package/dist/tools/buildTools.js.map +1 -1
  108. package/dist/tools/diffUtils.js +6 -6
  109. package/dist/tools/diffUtils.js.map +1 -1
  110. package/dist/tools/editTools.js +1 -1
  111. package/dist/tools/editTools.js.map +1 -1
  112. package/dist/tools/enhancedAnalysisTools.d.ts +9 -0
  113. package/dist/tools/enhancedAnalysisTools.d.ts.map +1 -0
  114. package/dist/tools/enhancedAnalysisTools.js +382 -0
  115. package/dist/tools/enhancedAnalysisTools.js.map +1 -0
  116. package/dist/tools/enhancedCodeIntelligenceTools.d.ts +1 -21
  117. package/dist/tools/enhancedCodeIntelligenceTools.d.ts.map +1 -1
  118. package/dist/tools/enhancedCodeIntelligenceTools.js +378 -256
  119. package/dist/tools/enhancedCodeIntelligenceTools.js.map +1 -1
  120. package/dist/tools/enhancedDevWorkflowTools.d.ts +2 -10
  121. package/dist/tools/enhancedDevWorkflowTools.d.ts.map +1 -1
  122. package/dist/tools/enhancedDevWorkflowTools.js +293 -165
  123. package/dist/tools/enhancedDevWorkflowTools.js.map +1 -1
  124. package/dist/tools/interactionTools.d.ts.map +1 -1
  125. package/dist/tools/interactionTools.js +55 -0
  126. package/dist/tools/interactionTools.js.map +1 -1
  127. package/dist/tools/learnTools.js +1 -1
  128. package/dist/tools/learnTools.js.map +1 -1
  129. package/dist/tools/offsec/offsecOperationsTools.d.ts +3 -0
  130. package/dist/tools/offsec/offsecOperationsTools.d.ts.map +1 -0
  131. package/dist/tools/offsec/offsecOperationsTools.js +333 -0
  132. package/dist/tools/offsec/offsecOperationsTools.js.map +1 -0
  133. package/dist/tools/offsecSearchTools.d.ts +3 -0
  134. package/dist/tools/offsecSearchTools.d.ts.map +1 -0
  135. package/dist/tools/offsecSearchTools.js +330 -0
  136. package/dist/tools/offsecSearchTools.js.map +1 -0
  137. package/dist/tools/taoOperations.d.ts +7 -0
  138. package/dist/tools/taoOperations.d.ts.map +1 -0
  139. package/dist/tools/taoOperations.js +744 -0
  140. package/dist/tools/taoOperations.js.map +1 -0
  141. package/dist/ui/ClaudeCodeRenderer.js +1 -1
  142. package/dist/ui/ClaudeCodeRenderer.js.map +1 -1
  143. package/dist/ui/ShellUIAdapter.d.ts +10 -6
  144. package/dist/ui/ShellUIAdapter.d.ts.map +1 -1
  145. package/dist/ui/ShellUIAdapter.js +69 -67
  146. package/dist/ui/ShellUIAdapter.js.map +1 -1
  147. package/dist/ui/UnifiedUIRenderer.d.ts +2 -0
  148. package/dist/ui/UnifiedUIRenderer.d.ts.map +1 -1
  149. package/dist/ui/UnifiedUIRenderer.js +64 -13
  150. package/dist/ui/UnifiedUIRenderer.js.map +1 -1
  151. package/dist/ui/globalWriteLock.d.ts.map +1 -1
  152. package/dist/ui/globalWriteLock.js +6 -0
  153. package/dist/ui/globalWriteLock.js.map +1 -1
  154. package/dist/ui/inPlaceUpdater.js +1 -1
  155. package/dist/ui/inPlaceUpdater.js.map +1 -1
  156. package/dist/ui/outputMode.d.ts.map +1 -1
  157. package/dist/ui/outputMode.js +1 -2
  158. package/dist/ui/outputMode.js.map +1 -1
  159. package/dist/ui/richText.js +4 -4
  160. package/dist/ui/richText.js.map +1 -1
  161. package/dist/ui/streamingFormatter.d.ts +11 -0
  162. package/dist/ui/streamingFormatter.d.ts.map +1 -1
  163. package/dist/ui/streamingFormatter.js +27 -1
  164. package/dist/ui/streamingFormatter.js.map +1 -1
  165. package/dist/ui/toolDisplay.js +1 -1
  166. package/dist/ui/toolDisplay.js.map +1 -1
  167. package/package.json +4 -13
@@ -1,418 +1,540 @@
1
1
  /**
2
2
  * Enhanced Code Intelligence Tools
3
- * Advanced code analysis, refactoring assistance, and quality improvement
3
+ * Production-ready code analysis, refactoring, and automation helpers.
4
4
  */
5
- import { readFileSync, existsSync } from 'node:fs';
6
- import { join, relative } from 'node:path';
5
+ import { existsSync, readFileSync, readdirSync, statSync, writeFileSync } from 'node:fs';
6
+ import { join, relative, resolve } from 'node:path';
7
7
  import { performAdvancedAstAnalysis } from './codeAnalysisTools.js';
8
+ import { CodeIntelligenceEngine } from '../intelligence/codeIntelligence.js';
9
+ import { RefactoringEngine } from '../intelligence/refactoring.js';
10
+ import { CodeIntelligenceSuite } from '../intelligence/index.js';
11
+ const SUPPORTED_EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs'];
12
+ const IGNORED_DIRECTORIES = new Set(['node_modules', '.git', 'dist', 'build', '.next', '.turbo']);
8
13
  export function createEnhancedCodeIntelligenceTools(workingDir) {
9
14
  return [
10
15
  {
11
16
  name: 'analyze_code_complexity',
12
- description: 'Analyze code complexity metrics across files and identify refactoring opportunities.',
17
+ description: 'Analyze code complexity across files, highlighting hotspots and risky symbols.',
13
18
  parameters: {
14
19
  type: 'object',
15
20
  properties: {
16
21
  path: {
17
22
  type: 'string',
18
- description: 'File or directory path to analyze (default: current directory).',
23
+ description: 'File or directory path to analyze (default: working directory).',
19
24
  },
20
25
  maxFiles: {
21
26
  type: 'number',
22
- description: 'Maximum number of files to analyze (default: 50).',
27
+ description: 'Maximum number of files to scan (default: 50).',
23
28
  },
24
29
  },
25
30
  additionalProperties: false,
26
31
  },
27
32
  handler: async (args) => {
28
- const path = args['path'] ?? workingDir;
33
+ const target = resolveTargetPath(workingDir, args['path'] ?? workingDir);
29
34
  const maxFiles = args['maxFiles'] ?? 50;
30
- return analyzeComplexity(path, maxFiles);
35
+ return analyzeCodeComplexity(target, workingDir, maxFiles);
31
36
  },
32
37
  },
33
38
  {
34
39
  name: 'suggest_refactoring',
35
- description: 'Generate specific refactoring suggestions for complex or problematic code.',
40
+ description: 'Generate refactoring suggestions with previews from the refactoring engine.',
36
41
  parameters: {
37
42
  type: 'object',
38
43
  properties: {
39
44
  path: {
40
45
  type: 'string',
41
- description: 'File or directory path to analyze for refactoring.',
46
+ description: 'File or directory to scan (default: working directory).',
42
47
  },
43
48
  priority: {
44
49
  type: 'string',
45
50
  enum: ['low', 'medium', 'high'],
46
- description: 'Priority level for suggestions (default: all).',
51
+ description: 'Filter suggestions by impact priority.',
47
52
  },
48
53
  },
49
54
  additionalProperties: false,
50
55
  },
51
56
  handler: async (args) => {
52
- const path = args['path'] ?? workingDir;
57
+ const target = resolveTargetPath(workingDir, args['path'] ?? workingDir);
53
58
  const priority = args['priority'];
54
- return generateRefactoringSuggestions(path, priority);
59
+ return suggestRefactoring(target, workingDir, priority);
55
60
  },
56
61
  },
57
62
  {
58
63
  name: 'auto_refactor_complexity',
59
- description: 'Automatically refactor complex functions by reducing nesting and improving readability.',
64
+ description: 'Apply safe refactorings for complex code paths. Uses previews by default.',
60
65
  parameters: {
61
66
  type: 'object',
62
67
  properties: {
63
68
  path: {
64
69
  type: 'string',
65
- description: 'File path to refactor.',
66
- },
67
- maxNestingDepth: {
68
- type: 'number',
69
- description: 'Maximum allowed nesting depth (default: 4).',
70
+ description: 'File or directory to refactor.',
70
71
  },
71
72
  preview: {
72
73
  type: 'boolean',
73
- description: 'Show preview without applying changes (default: true).',
74
+ description: 'If true, only show planned changes without writing files (default: true).',
74
75
  },
75
76
  },
76
77
  required: ['path'],
77
78
  additionalProperties: false,
78
79
  },
79
80
  handler: async (args) => {
80
- const filePath = resolveFilePath(workingDir, args['path']);
81
- const maxNestingDepth = args['maxNestingDepth'] ?? 4;
81
+ const target = resolveTargetPath(workingDir, args['path']);
82
82
  const preview = args['preview'] ?? true;
83
- return autoRefactorComplexity(filePath, workingDir, maxNestingDepth, preview);
83
+ return autoRefactorComplexity(target, workingDir, preview);
84
84
  },
85
85
  },
86
86
  {
87
87
  name: 'improve_type_safety',
88
- description: 'Replace any types with proper TypeScript types and improve type safety.',
88
+ description: 'Find and optionally replace unsafe `any` usage with safer defaults.',
89
89
  parameters: {
90
90
  type: 'object',
91
91
  properties: {
92
92
  path: {
93
93
  type: 'string',
94
- description: 'File path to improve type safety.',
94
+ description: 'File path to analyze for unsafe types.',
95
95
  },
96
96
  preview: {
97
97
  type: 'boolean',
98
- description: 'Show preview without applying changes (default: true).',
98
+ description: 'If true, only report findings; if false, applies safer replacements (default: true).',
99
99
  },
100
100
  },
101
101
  required: ['path'],
102
102
  additionalProperties: false,
103
103
  },
104
104
  handler: async (args) => {
105
- const filePath = resolveFilePath(workingDir, args['path']);
105
+ const target = resolveTargetPath(workingDir, args['path']);
106
106
  const preview = args['preview'] ?? true;
107
- return improveTypeSafety(filePath, workingDir, preview);
107
+ return improveTypeSafety(target, workingDir, preview);
108
108
  },
109
109
  },
110
110
  {
111
111
  name: 'detect_code_smells',
112
- description: 'Detect common code smells and anti-patterns across the codebase.',
112
+ description: 'Detect common code smells and anti-patterns using the intelligence engine.',
113
113
  parameters: {
114
114
  type: 'object',
115
115
  properties: {
116
116
  path: {
117
117
  type: 'string',
118
- description: 'Path to analyze (default: current directory).',
119
- },
120
- maxFiles: {
121
- type: 'number',
122
- description: 'Maximum number of files to analyze (default: 50).',
118
+ description: 'File or directory to scan (default: working directory).',
123
119
  },
124
120
  },
125
121
  additionalProperties: false,
126
122
  },
127
123
  handler: async (args) => {
128
- const path = args['path'] ?? workingDir;
129
- const maxFiles = args['maxFiles'] ?? 50;
130
- return detectCodeSmells(path, maxFiles);
124
+ const target = resolveTargetPath(workingDir, args['path'] ?? workingDir);
125
+ return detectCodeSmells(target, workingDir);
131
126
  },
132
127
  },
133
128
  {
134
129
  name: 'generate_code_quality_report',
135
- description: 'Generate comprehensive code quality report with actionable recommendations.',
130
+ description: 'Generate a quality report (issues, metrics, refactor hotspots) and return a condensed summary.',
136
131
  parameters: {
137
132
  type: 'object',
138
133
  properties: {
139
134
  path: {
140
135
  type: 'string',
141
- description: 'File or directory path to analyze (default: current directory).',
136
+ description: 'File or directory to analyze (default: working directory).',
137
+ },
138
+ },
139
+ additionalProperties: false,
140
+ },
141
+ handler: async (args) => {
142
+ const target = resolveTargetPath(workingDir, args['path'] ?? workingDir);
143
+ return generateQualityReport(target, workingDir);
144
+ },
145
+ },
146
+ {
147
+ name: 'run_code_intelligence_suite',
148
+ description: 'Run the full code intelligence suite (analysis, safe auto-fixes, refactor suggestions, docs/tests generation).',
149
+ parameters: {
150
+ type: 'object',
151
+ properties: {
152
+ enableAutoFix: {
153
+ type: 'boolean',
154
+ description: 'Apply safe auto-fixes and refactorings (default: false).',
155
+ },
156
+ generateTests: {
157
+ type: 'boolean',
158
+ description: 'Generate test plans/files (default: true).',
159
+ },
160
+ generateDocs: {
161
+ type: 'boolean',
162
+ description: 'Generate documentation summaries (default: true).',
163
+ },
164
+ outputDir: {
165
+ type: 'string',
166
+ description: 'Custom output directory for reports (default: .intelligence under workingDir).',
142
167
  },
143
168
  },
144
169
  additionalProperties: false,
145
170
  },
146
171
  handler: async (args) => {
147
- const path = args['path'] ?? workingDir;
148
- return generateQualityReport(path);
172
+ const enableAutoFix = args['enableAutoFix'] === true;
173
+ const generateTests = args['generateTests'] !== false;
174
+ const generateDocs = args['generateDocs'] !== false;
175
+ const outputDir = typeof args['outputDir'] === 'string'
176
+ ? resolveTargetPath(workingDir, args['outputDir'])
177
+ : undefined;
178
+ return runCodeIntelligenceSuite({
179
+ workingDir,
180
+ enableAutoFix,
181
+ generateTests,
182
+ generateDocs,
183
+ outputDir,
184
+ });
149
185
  },
150
186
  },
151
187
  ];
152
188
  }
153
- function resolveFilePath(workingDir, path) {
154
- if (path.startsWith('/')) {
155
- return path;
189
+ function resolveTargetPath(workingDir, targetPath) {
190
+ return targetPath.startsWith('/') ? targetPath : resolve(workingDir, targetPath);
191
+ }
192
+ function collectSourceFiles(target, maxFiles) {
193
+ const files = [];
194
+ const visit = (current) => {
195
+ if (files.length >= maxFiles) {
196
+ return;
197
+ }
198
+ const stats = statSync(current);
199
+ if (stats.isFile()) {
200
+ if (SUPPORTED_EXTENSIONS.some((ext) => current.endsWith(ext))) {
201
+ files.push(current);
202
+ }
203
+ return;
204
+ }
205
+ if (!stats.isDirectory()) {
206
+ return;
207
+ }
208
+ const entries = readdirSync(current, { withFileTypes: true });
209
+ for (const entry of entries) {
210
+ if (files.length >= maxFiles) {
211
+ break;
212
+ }
213
+ if (entry.isDirectory() && IGNORED_DIRECTORIES.has(entry.name)) {
214
+ continue;
215
+ }
216
+ visit(join(current, entry.name));
217
+ }
218
+ };
219
+ if (existsSync(target)) {
220
+ visit(target);
156
221
  }
157
- return join(workingDir, path);
222
+ return files;
158
223
  }
159
- function analyzeComplexity(_path, _maxFiles) {
224
+ function analyzeCodeComplexity(target, workingDir, maxFiles) {
225
+ if (!existsSync(target)) {
226
+ return `Error: path not found: ${target}`;
227
+ }
228
+ const files = collectSourceFiles(target, Math.max(1, maxFiles));
229
+ if (files.length === 0) {
230
+ return `No TypeScript/JavaScript files found under ${target}.`;
231
+ }
232
+ const hotspots = [];
233
+ let totalLines = 0;
234
+ let totalSymbols = 0;
235
+ let totalCyclomatic = 0;
236
+ for (const file of files) {
237
+ const content = readFileSync(file, 'utf-8');
238
+ const lines = content.split(/\r?\n/).length;
239
+ totalLines += lines;
240
+ const analysis = performAdvancedAstAnalysis(content, file);
241
+ totalSymbols += analysis.symbols.length;
242
+ totalCyclomatic += analysis.totalCyclomaticComplexity;
243
+ const worst = selectWorstSymbol(analysis.symbols);
244
+ if (worst) {
245
+ const span = worst.endLine - worst.startLine + 1;
246
+ const reasons = [];
247
+ if (worst.cyclomaticComplexity > 10) {
248
+ reasons.push(`high complexity (${worst.cyclomaticComplexity})`);
249
+ }
250
+ if (worst.statementCount > 50) {
251
+ reasons.push(`long body (${worst.statementCount} statements)`);
252
+ }
253
+ if (span > 120) {
254
+ reasons.push(`spans ${span} lines`);
255
+ }
256
+ hotspots.push({ file, symbol: worst, span, reasons });
257
+ }
258
+ }
259
+ hotspots.sort((a, b) => {
260
+ if (b.symbol.cyclomaticComplexity !== a.symbol.cyclomaticComplexity) {
261
+ return b.symbol.cyclomaticComplexity - a.symbol.cyclomaticComplexity;
262
+ }
263
+ return b.symbol.statementCount - a.symbol.statementCount;
264
+ });
265
+ const averageCyclomatic = totalSymbols === 0 ? 0 : Math.round((totalCyclomatic / totalSymbols) * 10) / 10;
160
266
  const output = [];
161
267
  output.push('# Code Complexity Analysis');
268
+ output.push(`Files scanned: ${files.length} (limit ${maxFiles})`);
269
+ output.push(`Lines of code: ${totalLines.toLocaleString()}`);
270
+ output.push(`Average cyclomatic complexity per symbol: ${averageCyclomatic}`);
162
271
  output.push('');
163
- // Implementation would scan files and calculate complexity metrics
164
- // For now, return a placeholder implementation
165
- output.push('🔍 Complexity analysis would scan files and calculate:');
166
- output.push('- Cyclomatic complexity');
167
- output.push('- Cognitive complexity');
168
- output.push('- Maintainability index');
169
- output.push('- Nesting depth analysis');
170
- output.push('- Type safety metrics');
171
- output.push('');
172
- output.push('📊 This tool identifies complex functions, deep nesting, and type safety issues.');
272
+ output.push('## Top Complexity Hotspots');
273
+ const topHotspots = hotspots.slice(0, 10);
274
+ if (topHotspots.length === 0) {
275
+ output.push('No complex symbols detected.');
276
+ }
277
+ else {
278
+ topHotspots.forEach((hotspot, index) => {
279
+ output.push(`${index + 1}. ${relative(workingDir, hotspot.file)} :: ${hotspot.symbol.name} (lines ${hotspot.symbol.startLine}-${hotspot.symbol.endLine})`);
280
+ output.push(` - CC: ${hotspot.symbol.cyclomaticComplexity}, statements: ${hotspot.symbol.statementCount}, span: ${hotspot.span} lines`);
281
+ if (hotspot.reasons.length > 0) {
282
+ output.push(` - Reasons: ${hotspot.reasons.join(', ')}`);
283
+ }
284
+ });
285
+ }
173
286
  output.push('');
174
- output.push('💡 Use `suggest_refactoring` for specific improvement suggestions.');
287
+ output.push('Use `suggest_refactoring` to get concrete improvement steps or `auto_refactor_complexity` to apply safe changes.');
175
288
  return output.join('\n');
176
289
  }
177
- function generateRefactoringSuggestions(_path, priority) {
290
+ function selectWorstSymbol(symbols) {
291
+ if (!symbols.length) {
292
+ return null;
293
+ }
294
+ const initial = symbols[0];
295
+ return symbols.reduce((worst, current) => {
296
+ const score = current.cyclomaticComplexity * 2 + current.statementCount;
297
+ const worstScore = worst.cyclomaticComplexity * 2 + worst.statementCount;
298
+ return score > worstScore ? current : worst;
299
+ }, initial);
300
+ }
301
+ function suggestRefactoring(target, workingDir, priority) {
302
+ const engine = new RefactoringEngine(workingDir);
303
+ const opportunities = engine.findOpportunities(target);
304
+ const filtered = priority ? opportunities.filter((o) => mapImpactToPriority(o.impact) === priority) : opportunities;
305
+ if (filtered.length === 0) {
306
+ return 'No refactoring opportunities detected for the specified scope.';
307
+ }
178
308
  const output = [];
179
309
  output.push('# Refactoring Suggestions');
180
- output.push('');
181
- // Implementation would analyze code and generate specific suggestions
182
- output.push('🔧 Refactoring suggestions would include:');
183
- output.push('- Breaking down complex functions');
184
- output.push('- Reducing nesting depth');
185
- output.push('- Replacing `any` types with proper types');
186
- output.push('- Improving function naming');
187
- output.push('- Removing code duplication');
188
- output.push('');
189
310
  if (priority) {
190
- output.push(`📋 Priority filter: ${priority}`);
311
+ output.push(`Filtered by priority: ${priority}`);
191
312
  }
192
313
  output.push('');
193
- output.push('💡 Use `auto_refactor_complexity` for automated refactoring assistance.');
314
+ filtered.slice(0, 20).forEach((opp, index) => {
315
+ const preview = opp.preview
316
+ ? `${opp.preview.before.trim().slice(0, 80)} → ${opp.preview.after.trim().slice(0, 80)}`
317
+ : 'Preview unavailable';
318
+ output.push(`${index + 1}. ${opp.type} (${opp.impact}/${opp.risk}) - ${opp.description}`);
319
+ output.push(` • ${opp.file}:${opp.line}`);
320
+ output.push(` • ${preview}`);
321
+ });
322
+ if (filtered.length > 20) {
323
+ output.push('');
324
+ output.push(`…${filtered.length - 20} additional opportunities not shown.`);
325
+ }
326
+ output.push('');
327
+ output.push('Run `auto_refactor_complexity` to apply safe changes automatically.');
194
328
  return output.join('\n');
195
329
  }
196
- function autoRefactorComplexity(filePath, workingDir, maxNestingDepth, preview) {
197
- if (!existsSync(filePath)) {
198
- return `Error: File not found: ${filePath}`;
330
+ function mapImpactToPriority(impact) {
331
+ return impact;
332
+ }
333
+ function autoRefactorComplexity(target, workingDir, preview) {
334
+ if (!existsSync(target)) {
335
+ return `Error: path not found: ${target}`;
199
336
  }
200
- const content = readFileSync(filePath, 'utf-8');
201
- const ast = performAdvancedAstAnalysis(content, filePath);
202
- const output = [];
203
- output.push('# Automatic Complexity Refactoring');
204
- output.push('');
205
- output.push(`📁 File: ${relative(workingDir, filePath)}`);
206
- output.push(`🎯 Target nesting depth: ${maxNestingDepth}`);
207
- output.push(`👁️ Preview mode: ${preview ? 'ON' : 'OFF'}`);
208
- output.push('');
209
- // Find complex functions
210
- const complexFunctions = ast.symbols.filter(symbol => symbol.kind === 'function' &&
211
- (symbol.cyclomaticComplexity > 10 || symbol.statementCount > 30));
212
- if (complexFunctions.length === 0) {
213
- output.push('✅ No complex functions found that need refactoring.');
337
+ const engine = new RefactoringEngine(workingDir);
338
+ const opportunities = engine.findOpportunities(target);
339
+ const safe = opportunities.filter((o) => o.risk === 'safe');
340
+ if (safe.length === 0) {
341
+ return 'No safe refactorings available to apply.';
342
+ }
343
+ if (preview) {
344
+ const output = [];
345
+ output.push('# Preview: Safe Refactorings');
346
+ safe.slice(0, 15).forEach((opp, index) => {
347
+ output.push(`${index + 1}. ${opp.type} :: ${opp.file}:${opp.line} (${opp.description})`);
348
+ });
349
+ if (safe.length > 15) {
350
+ output.push(`…${safe.length - 15} additional safe refactorings not shown.`);
351
+ }
352
+ output.push('');
353
+ output.push('Run again with `preview: false` to apply these changes.');
214
354
  return output.join('\n');
215
355
  }
216
- output.push('## Complex Functions Found');
217
- complexFunctions.forEach(func => {
218
- output.push(`- ${func.name}: ${func.statementCount} statements, CC: ${func.cyclomaticComplexity}`);
356
+ const result = engine.applySafeRefactorings(safe);
357
+ const output = [];
358
+ output.push('# Applied Safe Refactorings');
359
+ output.push(`Files modified: ${result.filesModified.length}`);
360
+ result.changes.forEach((change, index) => {
361
+ output.push(`${index + 1}. ${change.file} - ${change.description} (${change.linesChanged} lines changed)`);
219
362
  });
220
- if (preview) {
363
+ if (result.errors.length > 0) {
221
364
  output.push('');
222
- output.push('💡 Run with `preview: false` to apply automatic refactoring.');
365
+ output.push('Errors:');
366
+ result.errors.forEach((err) => output.push(`- ${err}`));
223
367
  }
224
368
  return output.join('\n');
225
369
  }
226
- function improveTypeSafety(filePath, workingDir, preview) {
227
- if (!existsSync(filePath)) {
228
- return `Error: File not found: ${filePath}`;
370
+ function improveTypeSafety(target, workingDir, preview) {
371
+ if (!existsSync(target)) {
372
+ return `Error: file not found: ${target}`;
229
373
  }
230
- const content = readFileSync(filePath, 'utf-8');
231
- const output = [];
232
- output.push('# Type Safety Improvements');
233
- output.push('');
234
- output.push(`📁 File: ${relative(workingDir, filePath)}`);
235
- output.push(`👁️ Preview mode: ${preview ? 'ON' : 'OFF'}`);
236
- output.push('');
237
- // Count any types
238
- const anyCount = (content.match(/\bany\b/g) || []).length;
239
- output.push(`🔍 Found ${anyCount} instances of 'any' type`);
240
- if (anyCount === 0) {
241
- output.push('✅ No type safety issues found.');
242
- return output.join('\n');
374
+ const content = readFileSync(target, 'utf-8');
375
+ const occurrences = findAnyOccurrences(content);
376
+ if (occurrences.length === 0) {
377
+ return 'No unsafe `any` usage detected.';
243
378
  }
244
- output.push('');
245
- output.push('## Type Safety Issues');
246
- output.push('- Replace `any` with specific types');
247
- output.push('- Add proper interface definitions');
248
- output.push('- Improve function return types');
249
- output.push('- Add parameter types');
250
379
  if (preview) {
380
+ const output = [];
381
+ output.push('# Type Safety Findings');
382
+ occurrences.slice(0, 20).forEach((occurrence, index) => {
383
+ output.push(`${index + 1}. line ${occurrence.line} → ${occurrence.snippet}`);
384
+ });
385
+ if (occurrences.length > 20) {
386
+ output.push(`…${occurrences.length - 20} additional occurrences not shown.`);
387
+ }
251
388
  output.push('');
252
- output.push('💡 Run with `preview: false` to apply type safety improvements.');
389
+ output.push('Run with `preview: false` to replace `any` with `unknown` in-place.');
390
+ return output.join('\n');
391
+ }
392
+ let updated = content;
393
+ const replacements = [
394
+ { pattern: /:\s*any\b/g, replacement: ': unknown' },
395
+ { pattern: /\bas any\b/g, replacement: ' as unknown' },
396
+ { pattern: /<any>/g, replacement: '<unknown>' },
397
+ ];
398
+ replacements.forEach(({ pattern, replacement }) => {
399
+ updated = updated.replace(pattern, replacement);
400
+ });
401
+ if (updated === content) {
402
+ return 'No replaceable `any` tokens found after analysis.';
253
403
  }
404
+ writeFileSync(target, updated, 'utf-8');
405
+ const output = [];
406
+ output.push('# Type Safety Applied');
407
+ output.push(`File updated: ${relative(workingDir, target)}`);
408
+ output.push(`Occurrences replaced: ${occurrences.length}`);
409
+ output.push('Re-run type checking to validate changes.');
254
410
  return output.join('\n');
255
411
  }
256
- function scanFiles(basePath, maxFiles) {
257
- const files = [];
258
- // Simple file scanning using existsSync
259
- // For a directory, we'd normally use readdirSync recursively
260
- // but since we're keeping this simple, just check if it's a single file
261
- if (existsSync(basePath)) {
262
- const { statSync, readdirSync } = require('node:fs');
263
- const stats = statSync(basePath);
264
- if (stats.isFile() && (basePath.endsWith('.ts') || basePath.endsWith('.js') || basePath.endsWith('.tsx') || basePath.endsWith('.jsx'))) {
265
- return [basePath];
266
- }
267
- if (stats.isDirectory()) {
268
- const scanDir = (dir) => {
269
- if (files.length >= maxFiles)
270
- return;
271
- try {
272
- const entries = readdirSync(dir, { withFileTypes: true });
273
- for (const entry of entries) {
274
- if (files.length >= maxFiles)
275
- break;
276
- const fullPath = join(dir, entry.name);
277
- if (entry.isDirectory() && !entry.name.startsWith('.') && entry.name !== 'node_modules' && entry.name !== 'dist') {
278
- scanDir(fullPath);
279
- }
280
- else if (entry.isFile() && (entry.name.endsWith('.ts') || entry.name.endsWith('.js') || entry.name.endsWith('.tsx') || entry.name.endsWith('.jsx'))) {
281
- files.push(fullPath);
282
- }
283
- }
284
- }
285
- catch {
286
- // Ignore permission errors
287
- }
288
- };
289
- scanDir(basePath);
290
- }
412
+ function findAnyOccurrences(content) {
413
+ const regex = /\bany\b/g;
414
+ const occurrences = [];
415
+ let match;
416
+ while ((match = regex.exec(content))) {
417
+ const before = content.slice(0, match.index);
418
+ const line = before.split(/\r?\n/).length;
419
+ const lineText = content.split(/\r?\n/)[line - 1] ?? '';
420
+ occurrences.push({ line, snippet: lineText.trim().slice(0, 120) });
291
421
  }
292
- return files;
422
+ return occurrences;
293
423
  }
294
- function detectCodeSmells(path, maxFiles = 50) {
424
+ async function detectCodeSmells(target, workingDir) {
425
+ if (!existsSync(target)) {
426
+ return `Error: path not found: ${target}`;
427
+ }
428
+ const engine = new CodeIntelligenceEngine(workingDir);
429
+ const result = await engine.analyze(target);
430
+ const smells = result.issues.filter((issue) => ['complexity', 'duplication', 'maintainability', 'bug', 'performance'].includes(issue.type));
431
+ if (smells.length === 0) {
432
+ return 'No code smells detected.';
433
+ }
434
+ const severityOrder = { critical: 0, high: 1, medium: 2, low: 3, info: 4 };
435
+ smells.sort((a, b) => (severityOrder[a.severity] ?? 5) - (severityOrder[b.severity] ?? 5));
295
436
  const output = [];
296
- output.push('# Code Smell Detection Report');
437
+ output.push('# Code Smells');
438
+ output.push(`Total smells: ${smells.length}`);
297
439
  output.push('');
298
- // Common code smells to detect
299
- const codeSmells = [
300
- {
301
- name: 'Long Method',
302
- pattern: /function\s+\w+\s*\([^)]*\)\s*\{[\s\S]{200,}/g,
303
- description: 'Methods longer than 200 characters suggest they do too much',
304
- fix: 'Extract smaller methods with single responsibilities'
305
- },
306
- {
307
- name: 'Large Class',
308
- pattern: /class\s+\w+\s*\{[\s\S]{500,}/g,
309
- description: 'Classes with excessive lines violate single responsibility principle',
310
- fix: 'Split into smaller, focused classes'
311
- },
312
- {
313
- name: 'Primitive Obsession',
314
- pattern: /(?:let|const|var)\s+\w+\s*:\s*(string|number|boolean)\b/g,
315
- description: 'Overuse of primitives instead of domain-specific types',
316
- fix: 'Create value objects or domain-specific types'
317
- },
318
- {
319
- name: 'Data Clumps',
320
- pattern: /(?:\w+,\s*){3,}\w+/g,
321
- description: 'Groups of data items that appear together frequently',
322
- fix: 'Extract into parameter objects or data classes'
323
- },
324
- {
325
- name: 'Feature Envy',
326
- pattern: /this\.\w+\.\w+/g,
327
- description: 'Method uses more features of another class than its own',
328
- fix: 'Move method to the class it envies'
329
- },
330
- {
331
- name: 'Inappropriate Intimacy',
332
- pattern: /private\s+\w+\s*:\s*\w+/g,
333
- description: 'Classes know too much about each other\'s internals',
334
- fix: 'Reduce coupling through interfaces or mediators'
335
- },
336
- {
337
- name: 'Message Chains',
338
- pattern: /\.\w+\(\)\.\w+\(\)\.\w+\(\)/g,
339
- description: 'Long chains of method calls indicate tight coupling',
340
- fix: 'Hide delegate or extract intermediate object'
341
- },
342
- {
343
- name: 'Shotgun Surgery',
344
- pattern: /\/\/\s*TODO.*change|FIXME.*multiple/i,
345
- description: 'Single change requires modifications in many places',
346
- fix: 'Move related behavior into single class'
440
+ smells.slice(0, 20).forEach((issue, index) => {
441
+ output.push(`${index + 1}. [${issue.severity}] ${issue.file}:${issue.line ?? '?'} - ${issue.message}`);
442
+ if (issue.suggestion) {
443
+ output.push(` → ${issue.suggestion}`);
347
444
  }
348
- ];
349
- output.push('## Common Code Smells Detected');
445
+ });
446
+ if (smells.length > 20) {
447
+ output.push(`…${smells.length - 20} additional smells not shown.`);
448
+ }
449
+ return output.join('\n');
450
+ }
451
+ async function generateQualityReport(target, workingDir) {
452
+ const engine = new CodeIntelligenceEngine(workingDir);
453
+ const result = await engine.analyze(target);
454
+ const refEngine = new RefactoringEngine(workingDir);
455
+ const refOps = refEngine.findOpportunities(target).slice(0, 5);
456
+ const output = [];
457
+ output.push('# Code Quality Report');
458
+ output.push(`Files analyzed: ${result.files}`);
459
+ output.push(`Lines of code: ${result.linesOfCode.toLocaleString()}`);
460
+ output.push('');
461
+ output.push('## Metrics (0-100, higher is better)');
462
+ output.push(`- Complexity: ${Math.round(result.metrics.complexity)}`);
463
+ output.push(`- Maintainability: ${Math.round(result.metrics.maintainability)}`);
464
+ output.push(`- Testability: ${Math.round(result.metrics.testability)}`);
465
+ output.push(`- Duplication: ${Math.round(result.metrics.duplication)}`);
466
+ output.push(`- Documentation: ${Math.round(result.metrics.documentation)}`);
350
467
  output.push('');
351
- let totalSmells = 0;
352
- const files = scanFiles(path, maxFiles);
353
- files.forEach(file => {
354
- const content = readFileSync(file, 'utf8');
355
- const fileSmells = [];
356
- codeSmells.forEach(smell => {
357
- const matches = content.match(smell.pattern);
358
- if (matches && matches.length > 0) {
359
- fileSmells.push(`- **${smell.name}**: ${matches.length} instances - ${smell.description}`);
360
- totalSmells += matches.length;
468
+ output.push('## Top Issues');
469
+ const topIssues = result.issues
470
+ .slice()
471
+ .sort((a, b) => {
472
+ const order = { critical: 0, high: 1, medium: 2, low: 3, info: 4 };
473
+ return (order[a.severity] ?? 5) - (order[b.severity] ?? 5);
474
+ })
475
+ .slice(0, 10);
476
+ if (topIssues.length === 0) {
477
+ output.push('No issues detected.');
478
+ }
479
+ else {
480
+ topIssues.forEach((issue, index) => {
481
+ output.push(`${index + 1}. [${issue.severity}] ${issue.file}:${issue.line ?? '?'} - ${issue.message}`);
482
+ if (issue.suggestion) {
483
+ output.push(` → ${issue.suggestion}`);
361
484
  }
362
485
  });
363
- if (fileSmells.length > 0) {
364
- output.push(`### ${file}`);
365
- output.push(...fileSmells);
366
- output.push('');
367
- }
368
- });
369
- if (totalSmells === 0) {
370
- output.push('✅ No significant code smells detected.');
371
- output.push('');
372
- output.push('The codebase appears to follow good design principles.');
486
+ }
487
+ output.push('');
488
+ output.push('## Refactor Hotspots');
489
+ if (refOps.length === 0) {
490
+ output.push('No refactor hotspots identified.');
373
491
  }
374
492
  else {
375
- output.push(`## Summary`);
376
- output.push(`- **Total smells detected**: ${totalSmells}`);
377
- output.push(`- **Files analyzed**: ${files.length}`);
378
- output.push('');
379
- output.push('## Recommended Refactoring Actions');
380
- output.push('');
381
- codeSmells.forEach(smell => {
382
- output.push(`- **${smell.name}**: ${smell.fix}`);
493
+ refOps.forEach((opp, index) => {
494
+ output.push(`${index + 1}. ${opp.file}:${opp.line} - ${opp.description} (${opp.impact}/${opp.risk})`);
383
495
  });
384
496
  }
385
497
  output.push('');
386
- output.push('💡 Use `suggest_refactoring` for specific improvement suggestions.');
387
- output.push('💡 Use `auto_refactor_complexity` for automated refactoring.');
498
+ output.push('Use `run_code_intelligence_suite` for a full analysis + optional auto-fixes and documentation generation.');
388
499
  return output.join('\n');
389
500
  }
390
- function generateQualityReport(_path) {
501
+ async function runCodeIntelligenceSuite(options) {
502
+ const suite = new CodeIntelligenceSuite({
503
+ workingDir: options.workingDir,
504
+ enableAutoFix: options.enableAutoFix,
505
+ generateTests: options.generateTests,
506
+ generateDocs: options.generateDocs,
507
+ outputDir: options.outputDir ?? join(options.workingDir, '.intelligence'),
508
+ });
509
+ const report = await suite.runFullAnalysis();
391
510
  const output = [];
392
- output.push('# Comprehensive Code Quality Report');
511
+ output.push('# Code Intelligence Suite');
512
+ output.push(`Analysis completed at ${report.timestamp}`);
513
+ output.push(`Issues found: ${report.analysis.issues.length}`);
514
+ output.push(`Refactoring opportunities: ${report.refactoring.length}`);
515
+ output.push(`Auto-fix enabled: ${options.enableAutoFix ? 'yes' : 'no'}`);
393
516
  output.push('');
394
- output.push('📊 This report provides:');
395
- output.push('- Complexity metrics analysis');
396
- output.push('- Type safety assessment');
397
- output.push('- Code duplication detection');
398
- output.push('- Performance optimization suggestions');
399
- output.push('- Maintainability scoring');
400
- output.push('- **Code smell detection**');
401
- output.push('');
402
- output.push('🔍 Analysis covers:');
403
- output.push('- Function complexity (cyclomatic, cognitive)');
404
- output.push('- Nesting depth violations');
405
- output.push('- Type safety issues');
406
- output.push('- Code style consistency');
407
- output.push('- Documentation coverage');
408
- output.push('- **Common code smells and anti-patterns**');
517
+ const actions = report.actions ?? [];
518
+ if (actions.length > 0) {
519
+ output.push('## Actions Taken');
520
+ actions.forEach((action, index) => {
521
+ output.push(`${index + 1}. [${action.type}] ${action.description} (${action.success ? 'success' : 'partial'})`);
522
+ if (action.filesAffected.length > 0) {
523
+ output.push(` Files: ${action.filesAffected.join(', ')}`);
524
+ }
525
+ });
526
+ output.push('');
527
+ }
528
+ if (report.documentation) {
529
+ output.push('Documentation generated: API.md and API-reference.md');
530
+ }
531
+ if (report.tests) {
532
+ output.push('Tests generated: see .intelligence/generated-tests');
533
+ }
534
+ const dest = options.outputDir ?? join(options.workingDir, '.intelligence');
409
535
  output.push('');
410
- output.push('💡 Use individual tools for specific improvements:');
411
- output.push('- `analyze_code_complexity` for complexity analysis');
412
- output.push('- `suggest_refactoring` for improvement suggestions');
413
- output.push('- `auto_refactor_complexity` for automated refactoring');
414
- output.push('- `improve_type_safety` for type improvements');
415
- output.push('- `detect_code_smells` for anti-pattern detection');
536
+ output.push(`Artifacts written to: ${dest}`);
537
+ output.push('Re-run this tool to keep reports fresh after additional edits.');
416
538
  return output.join('\n');
417
539
  }
418
540
  //# sourceMappingURL=enhancedCodeIntelligenceTools.js.map