monomind 1.17.0 → 1.17.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.
- package/.claude/agents/engineering/engineering-security-engineer.md +1 -1
- package/.claude/commands/mastermind/_repeat.md +4 -0
- package/.claude/commands/mastermind/master.md +52 -1
- package/.claude/scheduled_tasks.lock +1 -1
- package/.claude/skills/mastermind/_repeat.md +2 -0
- package/package.json +1 -1
- package/packages/@monomind/cli/.claude/agents/engineering/engineering-security-engineer.md +1 -1
- package/packages/@monomind/cli/.claude/commands/mastermind/_repeat.md +4 -0
- package/packages/@monomind/cli/.claude/commands/mastermind/master.md +52 -1
- package/packages/@monomind/cli/.claude/skills/mastermind/_repeat.md +2 -0
- package/packages/@monomind/cli/dist/src/__tests__/browse-analyzer.test.js +42 -59
- package/packages/@monomind/cli/dist/src/agents/registry-builder.d.ts +8 -0
- package/packages/@monomind/cli/dist/src/agents/registry-builder.js +22 -0
- package/packages/@monomind/cli/dist/src/browser/dashboard/server.js +18 -0
- package/packages/@monomind/cli/dist/src/browser/dashboard/ui.html +37 -125
- package/packages/@monomind/cli/dist/src/commands/agent-lifecycle.d.ts +17 -0
- package/packages/@monomind/cli/dist/src/commands/agent-lifecycle.js +320 -0
- package/packages/@monomind/cli/dist/src/commands/agent-ops.d.ts +9 -0
- package/packages/@monomind/cli/dist/src/commands/agent-ops.js +329 -0
- package/packages/@monomind/cli/dist/src/commands/agent.js +5 -907
- package/packages/@monomind/cli/dist/src/commands/analyze-ast.d.ts +26 -0
- package/packages/@monomind/cli/dist/src/commands/analyze-ast.js +284 -0
- package/packages/@monomind/cli/dist/src/commands/analyze-boundaries.d.ts +14 -0
- package/packages/@monomind/cli/dist/src/commands/analyze-boundaries.js +295 -0
- package/packages/@monomind/cli/dist/src/commands/analyze-diff.d.ts +8 -0
- package/packages/@monomind/cli/dist/src/commands/analyze-diff.js +395 -0
- package/packages/@monomind/cli/dist/src/commands/analyze-graph.d.ts +14 -0
- package/packages/@monomind/cli/dist/src/commands/analyze-graph.js +304 -0
- package/packages/@monomind/cli/dist/src/commands/analyze-imports.d.ts +11 -0
- package/packages/@monomind/cli/dist/src/commands/analyze-imports.js +287 -0
- package/packages/@monomind/cli/dist/src/commands/analyze-symbols.d.ts +14 -0
- package/packages/@monomind/cli/dist/src/commands/analyze-symbols.js +302 -0
- package/packages/@monomind/cli/dist/src/commands/analyze.d.ts +38 -0
- package/packages/@monomind/cli/dist/src/commands/analyze.js +12 -1827
- package/packages/@monomind/cli/dist/src/commands/doctor-env-checks.d.ts +26 -0
- package/packages/@monomind/cli/dist/src/commands/doctor-env-checks.js +189 -0
- package/packages/@monomind/cli/dist/src/commands/doctor-project-checks.d.ts +20 -0
- package/packages/@monomind/cli/dist/src/commands/doctor-project-checks.js +432 -0
- package/packages/@monomind/cli/dist/src/commands/doctor.js +54 -943
- package/packages/@monomind/cli/dist/src/commands/hive-mind-comms.d.ts +11 -0
- package/packages/@monomind/cli/dist/src/commands/hive-mind-comms.js +242 -0
- package/packages/@monomind/cli/dist/src/commands/hive-mind-helpers.d.ts +35 -0
- package/packages/@monomind/cli/dist/src/commands/hive-mind-helpers.js +203 -0
- package/packages/@monomind/cli/dist/src/commands/hive-mind-ops.d.ts +8 -0
- package/packages/@monomind/cli/dist/src/commands/hive-mind-ops.js +233 -0
- package/packages/@monomind/cli/dist/src/commands/hive-mind-spawn.d.ts +12 -0
- package/packages/@monomind/cli/dist/src/commands/hive-mind-spawn.js +274 -0
- package/packages/@monomind/cli/dist/src/commands/hive-mind.js +10 -1129
- package/packages/@monomind/cli/dist/src/commands/hooks-coverage-commands.d.ts +4 -4
- package/packages/@monomind/cli/dist/src/commands/hooks-coverage-commands.js +19 -819
- package/packages/@monomind/cli/dist/src/commands/hooks-coverage-gaps.d.ts +7 -0
- package/packages/@monomind/cli/dist/src/commands/hooks-coverage-gaps.js +334 -0
- package/packages/@monomind/cli/dist/src/commands/hooks-coverage-routing.d.ts +7 -0
- package/packages/@monomind/cli/dist/src/commands/hooks-coverage-routing.js +399 -0
- package/packages/@monomind/cli/dist/src/commands/init-subcommands.d.ts +8 -0
- package/packages/@monomind/cli/dist/src/commands/init-subcommands.js +156 -0
- package/packages/@monomind/cli/dist/src/commands/init-upgrade.d.ts +6 -0
- package/packages/@monomind/cli/dist/src/commands/init-upgrade.js +203 -0
- package/packages/@monomind/cli/dist/src/commands/init-wizard.d.ts +6 -0
- package/packages/@monomind/cli/dist/src/commands/init-wizard.js +246 -0
- package/packages/@monomind/cli/dist/src/commands/init.js +6 -623
- package/packages/@monomind/cli/dist/src/commands/memory-admin.d.ts +10 -0
- package/packages/@monomind/cli/dist/src/commands/memory-admin.js +433 -0
- package/packages/@monomind/cli/dist/src/commands/memory-crud.d.ts +9 -0
- package/packages/@monomind/cli/dist/src/commands/memory-crud.js +342 -0
- package/packages/@monomind/cli/dist/src/commands/memory-list.d.ts +10 -0
- package/packages/@monomind/cli/dist/src/commands/memory-list.js +321 -0
- package/packages/@monomind/cli/dist/src/commands/memory-transfer.d.ts +9 -0
- package/packages/@monomind/cli/dist/src/commands/memory-transfer.js +372 -0
- package/packages/@monomind/cli/dist/src/commands/memory.d.ts +6 -0
- package/packages/@monomind/cli/dist/src/commands/memory.js +10 -1441
- package/packages/@monomind/cli/dist/src/commands/neural-core.d.ts +8 -0
- package/packages/@monomind/cli/dist/src/commands/neural-core.js +274 -0
- package/packages/@monomind/cli/dist/src/commands/neural-optimize.d.ts +7 -0
- package/packages/@monomind/cli/dist/src/commands/neural-optimize.js +332 -0
- package/packages/@monomind/cli/dist/src/commands/neural-registry.d.ts +7 -0
- package/packages/@monomind/cli/dist/src/commands/neural-registry.js +290 -0
- package/packages/@monomind/cli/dist/src/commands/neural.js +3 -974
- package/packages/@monomind/cli/dist/src/commands/platforms.js +327 -7
- package/packages/@monomind/cli/dist/src/commands/security-cve.d.ts +6 -0
- package/packages/@monomind/cli/dist/src/commands/security-cve.js +310 -0
- package/packages/@monomind/cli/dist/src/commands/security-misc.d.ts +9 -0
- package/packages/@monomind/cli/dist/src/commands/security-misc.js +293 -0
- package/packages/@monomind/cli/dist/src/commands/security-scan.d.ts +18 -0
- package/packages/@monomind/cli/dist/src/commands/security-scan.js +328 -0
- package/packages/@monomind/cli/dist/src/commands/security.js +3 -958
- package/packages/@monomind/cli/dist/src/commands/session.js +1 -1
- package/packages/@monomind/cli/dist/src/commands/swarm.js +23 -17
- package/packages/@monomind/cli/dist/src/index.js +8 -37
- package/packages/@monomind/cli/dist/src/mcp-tools/swarm-tools.js +77 -0
- package/packages/@monomind/cli/dist/src/parser.js +11 -6
- package/packages/@monomind/cli/dist/src/routing/llm-caller.js +1 -2
- package/packages/@monomind/cli/package.json +2 -3
- package/packages/@monomind/cli/scripts/understand-analyze.mjs +1 -1
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Analyze complexity and symbols subcommands
|
|
3
|
+
* Complexity analysis and symbol extraction from code files
|
|
4
|
+
*/
|
|
5
|
+
import { output } from '../output.js';
|
|
6
|
+
import * as fs from 'fs/promises';
|
|
7
|
+
import { resolve } from 'path';
|
|
8
|
+
import { getASTAnalyzer, safeWriteOutputFile, scanSourceFiles, fallbackAnalyze } from './analyze.js';
|
|
9
|
+
import { truncatePathAst, formatComplexityValueAst, getTypeMarkerAst } from './analyze-ast.js';
|
|
10
|
+
/**
|
|
11
|
+
* Complexity analysis subcommand
|
|
12
|
+
*/
|
|
13
|
+
export const complexityAstCommand = {
|
|
14
|
+
name: 'complexity',
|
|
15
|
+
aliases: ['cx'],
|
|
16
|
+
description: 'Analyze code complexity metrics',
|
|
17
|
+
options: [
|
|
18
|
+
{
|
|
19
|
+
name: 'threshold',
|
|
20
|
+
short: 't',
|
|
21
|
+
description: 'Complexity threshold to flag (default: 10)',
|
|
22
|
+
type: 'number',
|
|
23
|
+
default: 10,
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: 'format',
|
|
27
|
+
short: 'f',
|
|
28
|
+
description: 'Output format (text, json)',
|
|
29
|
+
type: 'string',
|
|
30
|
+
default: 'text',
|
|
31
|
+
choices: ['text', 'json'],
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
name: 'output',
|
|
35
|
+
short: 'o',
|
|
36
|
+
description: 'Output file path',
|
|
37
|
+
type: 'string',
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
examples: [
|
|
41
|
+
{ command: 'monomind analyze complexity src/', description: 'Analyze complexity' },
|
|
42
|
+
{ command: 'monomind analyze complexity src/ --threshold 15', description: 'Flag high complexity' },
|
|
43
|
+
],
|
|
44
|
+
action: async (ctx) => {
|
|
45
|
+
const targetPath = ctx.args[0] || ctx.cwd;
|
|
46
|
+
const threshold = ctx.flags.threshold || 10;
|
|
47
|
+
const formatType = ctx.flags.format || 'text';
|
|
48
|
+
const outputFile = ctx.flags.output;
|
|
49
|
+
output.printInfo(`Analyzing complexity: ${output.highlight(targetPath)}`);
|
|
50
|
+
output.writeln();
|
|
51
|
+
const spinner = output.createSpinner({ text: 'Calculating complexity...', spinner: 'dots' });
|
|
52
|
+
spinner.start();
|
|
53
|
+
try {
|
|
54
|
+
const astModule = await getASTAnalyzer();
|
|
55
|
+
const resolvedPath = resolve(targetPath);
|
|
56
|
+
const stat = await fs.stat(resolvedPath);
|
|
57
|
+
const files = stat.isDirectory() ? await scanSourceFiles(resolvedPath) : [resolvedPath];
|
|
58
|
+
const results = [];
|
|
59
|
+
for (const file of files.slice(0, 100)) {
|
|
60
|
+
try {
|
|
61
|
+
const content = await fs.readFile(file, 'utf-8');
|
|
62
|
+
let analysis;
|
|
63
|
+
if (astModule) {
|
|
64
|
+
const analyzer = astModule.createASTAnalyzer();
|
|
65
|
+
analysis = analyzer.analyze(content, file);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
analysis = fallbackAnalyze(content, file);
|
|
69
|
+
}
|
|
70
|
+
const flagged = analysis.complexity.cyclomatic > threshold;
|
|
71
|
+
const rating = analysis.complexity.cyclomatic <= 5 ? 'Simple' :
|
|
72
|
+
analysis.complexity.cyclomatic <= 10 ? 'Moderate' :
|
|
73
|
+
analysis.complexity.cyclomatic <= 20 ? 'Complex' : 'Very Complex';
|
|
74
|
+
results.push({
|
|
75
|
+
file: file,
|
|
76
|
+
cyclomatic: analysis.complexity.cyclomatic,
|
|
77
|
+
cognitive: analysis.complexity.cognitive,
|
|
78
|
+
loc: analysis.complexity.loc,
|
|
79
|
+
commentDensity: analysis.complexity.commentDensity,
|
|
80
|
+
rating,
|
|
81
|
+
flagged,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
// Skip files that can't be analyzed
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
spinner.stop();
|
|
89
|
+
// Sort by complexity descending
|
|
90
|
+
results.sort((a, b) => b.cyclomatic - a.cyclomatic);
|
|
91
|
+
const flaggedCount = results.filter(r => r.flagged).length;
|
|
92
|
+
const avgComplexity = results.length > 0
|
|
93
|
+
? results.reduce((sum, r) => sum + r.cyclomatic, 0) / results.length
|
|
94
|
+
: 0;
|
|
95
|
+
if (formatType === 'json') {
|
|
96
|
+
const jsonOutput = { files: results, summary: { total: results.length, flagged: flaggedCount, avgComplexity, threshold } };
|
|
97
|
+
if (outputFile) {
|
|
98
|
+
await safeWriteOutputFile(outputFile, JSON.stringify(jsonOutput, null, 2));
|
|
99
|
+
output.printSuccess(`Results written to ${outputFile}`);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
output.printJson(jsonOutput);
|
|
103
|
+
}
|
|
104
|
+
return { success: true, data: jsonOutput };
|
|
105
|
+
}
|
|
106
|
+
// Summary
|
|
107
|
+
output.printBox([
|
|
108
|
+
`Files analyzed: ${results.length}`,
|
|
109
|
+
`Threshold: ${threshold}`,
|
|
110
|
+
`Flagged files: ${flaggedCount > 0 ? output.error(String(flaggedCount)) : output.success('0')}`,
|
|
111
|
+
`Average complexity: ${formatComplexityValueAst(Math.round(avgComplexity))}`,
|
|
112
|
+
].join('\n'), 'Complexity Analysis');
|
|
113
|
+
// Show flagged files first
|
|
114
|
+
if (flaggedCount > 0) {
|
|
115
|
+
output.writeln();
|
|
116
|
+
output.writeln(output.bold(output.warning(`High Complexity Files (>${threshold})`)));
|
|
117
|
+
output.writeln(output.dim('-'.repeat(60)));
|
|
118
|
+
const flaggedFiles = results.filter(r => r.flagged).slice(0, 10);
|
|
119
|
+
output.printTable({
|
|
120
|
+
columns: [
|
|
121
|
+
{ key: 'file', header: 'File', width: 40, format: (v) => truncatePathAst(v) },
|
|
122
|
+
{ key: 'cyclomatic', header: 'Cyclo', width: 8, align: 'right', format: (v) => output.error(String(v)) },
|
|
123
|
+
{ key: 'cognitive', header: 'Cogni', width: 8, align: 'right' },
|
|
124
|
+
{ key: 'loc', header: 'LOC', width: 8, align: 'right' },
|
|
125
|
+
{ key: 'rating', header: 'Rating', width: 15 },
|
|
126
|
+
],
|
|
127
|
+
data: flaggedFiles,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
// Show all files in table format
|
|
131
|
+
output.writeln();
|
|
132
|
+
output.writeln(output.bold('All Files'));
|
|
133
|
+
output.writeln(output.dim('-'.repeat(60)));
|
|
134
|
+
const displayFiles = results.slice(0, 15);
|
|
135
|
+
output.printTable({
|
|
136
|
+
columns: [
|
|
137
|
+
{ key: 'file', header: 'File', width: 40, format: (v) => truncatePathAst(v) },
|
|
138
|
+
{ key: 'cyclomatic', header: 'Cyclo', width: 8, align: 'right', format: (v) => formatComplexityValueAst(v) },
|
|
139
|
+
{ key: 'cognitive', header: 'Cogni', width: 8, align: 'right' },
|
|
140
|
+
{ key: 'loc', header: 'LOC', width: 8, align: 'right' },
|
|
141
|
+
],
|
|
142
|
+
data: displayFiles,
|
|
143
|
+
});
|
|
144
|
+
if (results.length > 15) {
|
|
145
|
+
output.writeln(output.dim(` ... and ${results.length - 15} more files`));
|
|
146
|
+
}
|
|
147
|
+
if (outputFile) {
|
|
148
|
+
await safeWriteOutputFile(outputFile, JSON.stringify({ files: results, summary: { total: results.length, flagged: flaggedCount, avgComplexity, threshold } }, null, 2));
|
|
149
|
+
output.printSuccess(`Results written to ${outputFile}`);
|
|
150
|
+
}
|
|
151
|
+
return { success: true, data: { files: results, flaggedCount } };
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
spinner.stop();
|
|
155
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
156
|
+
output.printError(`Complexity analysis failed: ${message}`);
|
|
157
|
+
return { success: false, exitCode: 1 };
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
/**
|
|
162
|
+
* Symbol extraction subcommand
|
|
163
|
+
*/
|
|
164
|
+
export const symbolsCommand = {
|
|
165
|
+
name: 'symbols',
|
|
166
|
+
aliases: ['sym'],
|
|
167
|
+
description: 'Extract and list code symbols (functions, classes, types)',
|
|
168
|
+
options: [
|
|
169
|
+
{
|
|
170
|
+
name: 'type',
|
|
171
|
+
short: 't',
|
|
172
|
+
description: 'Filter by symbol type (function, class, all)',
|
|
173
|
+
type: 'string',
|
|
174
|
+
default: 'all',
|
|
175
|
+
choices: ['function', 'class', 'all'],
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
name: 'format',
|
|
179
|
+
short: 'f',
|
|
180
|
+
description: 'Output format (text, json)',
|
|
181
|
+
type: 'string',
|
|
182
|
+
default: 'text',
|
|
183
|
+
choices: ['text', 'json'],
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
name: 'output',
|
|
187
|
+
short: 'o',
|
|
188
|
+
description: 'Output file path',
|
|
189
|
+
type: 'string',
|
|
190
|
+
},
|
|
191
|
+
],
|
|
192
|
+
examples: [
|
|
193
|
+
{ command: 'monomind analyze symbols src/', description: 'Extract all symbols' },
|
|
194
|
+
{ command: 'monomind analyze symbols src/ --type function', description: 'Only functions' },
|
|
195
|
+
{ command: 'monomind analyze symbols src/ --format json', description: 'JSON output' },
|
|
196
|
+
],
|
|
197
|
+
action: async (ctx) => {
|
|
198
|
+
const targetPath = ctx.args[0] || ctx.cwd;
|
|
199
|
+
const symbolType = ctx.flags.type || 'all';
|
|
200
|
+
const formatType = ctx.flags.format || 'text';
|
|
201
|
+
const outputFile = ctx.flags.output;
|
|
202
|
+
output.printInfo(`Extracting symbols: ${output.highlight(targetPath)}`);
|
|
203
|
+
output.writeln();
|
|
204
|
+
const spinner = output.createSpinner({ text: 'Parsing code...', spinner: 'dots' });
|
|
205
|
+
spinner.start();
|
|
206
|
+
try {
|
|
207
|
+
const astModule = await getASTAnalyzer();
|
|
208
|
+
const resolvedPath = resolve(targetPath);
|
|
209
|
+
const stat = await fs.stat(resolvedPath);
|
|
210
|
+
const files = stat.isDirectory() ? await scanSourceFiles(resolvedPath) : [resolvedPath];
|
|
211
|
+
const symbols = [];
|
|
212
|
+
for (const file of files.slice(0, 100)) {
|
|
213
|
+
try {
|
|
214
|
+
const content = await fs.readFile(file, 'utf-8');
|
|
215
|
+
let analysis;
|
|
216
|
+
if (astModule) {
|
|
217
|
+
const analyzer = astModule.createASTAnalyzer();
|
|
218
|
+
analysis = analyzer.analyze(content, file);
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
analysis = fallbackAnalyze(content, file);
|
|
222
|
+
}
|
|
223
|
+
if (symbolType === 'all' || symbolType === 'function') {
|
|
224
|
+
for (const fn of analysis.functions) {
|
|
225
|
+
symbols.push({
|
|
226
|
+
name: fn.name,
|
|
227
|
+
type: 'function',
|
|
228
|
+
file,
|
|
229
|
+
startLine: fn.startLine,
|
|
230
|
+
endLine: fn.endLine,
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
if (symbolType === 'all' || symbolType === 'class') {
|
|
235
|
+
for (const cls of analysis.classes) {
|
|
236
|
+
symbols.push({
|
|
237
|
+
name: cls.name,
|
|
238
|
+
type: 'class',
|
|
239
|
+
file,
|
|
240
|
+
startLine: cls.startLine,
|
|
241
|
+
endLine: cls.endLine,
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
catch {
|
|
247
|
+
// Skip files that can't be parsed
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
spinner.stop();
|
|
251
|
+
// Sort by file then name
|
|
252
|
+
symbols.sort((a, b) => a.file.localeCompare(b.file) || a.name.localeCompare(b.name));
|
|
253
|
+
if (formatType === 'json') {
|
|
254
|
+
if (outputFile) {
|
|
255
|
+
await safeWriteOutputFile(outputFile, JSON.stringify(symbols, null, 2));
|
|
256
|
+
output.printSuccess(`Results written to ${outputFile}`);
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
output.printJson(symbols);
|
|
260
|
+
}
|
|
261
|
+
return { success: true, data: symbols };
|
|
262
|
+
}
|
|
263
|
+
// Summary
|
|
264
|
+
const functionCount = symbols.filter(s => s.type === 'function').length;
|
|
265
|
+
const classCount = symbols.filter(s => s.type === 'class').length;
|
|
266
|
+
output.printBox([
|
|
267
|
+
`Total symbols: ${symbols.length}`,
|
|
268
|
+
`Functions: ${functionCount}`,
|
|
269
|
+
`Classes: ${classCount}`,
|
|
270
|
+
`Files: ${files.length}`,
|
|
271
|
+
].join('\n'), 'Symbol Extraction');
|
|
272
|
+
output.writeln();
|
|
273
|
+
output.writeln(output.bold('Symbols'));
|
|
274
|
+
output.writeln(output.dim('-'.repeat(60)));
|
|
275
|
+
const displaySymbols = symbols.slice(0, 30);
|
|
276
|
+
output.printTable({
|
|
277
|
+
columns: [
|
|
278
|
+
{ key: 'type', header: 'Type', width: 10, format: (v) => getTypeMarkerAst(v) },
|
|
279
|
+
{ key: 'name', header: 'Name', width: 30 },
|
|
280
|
+
{ key: 'file', header: 'File', width: 35, format: (v) => truncatePathAst(v, 33) },
|
|
281
|
+
{ key: 'startLine', header: 'Line', width: 8, align: 'right' },
|
|
282
|
+
],
|
|
283
|
+
data: displaySymbols,
|
|
284
|
+
});
|
|
285
|
+
if (symbols.length > 30) {
|
|
286
|
+
output.writeln(output.dim(` ... and ${symbols.length - 30} more symbols`));
|
|
287
|
+
}
|
|
288
|
+
if (outputFile) {
|
|
289
|
+
await safeWriteOutputFile(outputFile, JSON.stringify(symbols, null, 2));
|
|
290
|
+
output.printSuccess(`Results written to ${outputFile}`);
|
|
291
|
+
}
|
|
292
|
+
return { success: true, data: symbols };
|
|
293
|
+
}
|
|
294
|
+
catch (error) {
|
|
295
|
+
spinner.stop();
|
|
296
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
297
|
+
output.printError(`Symbol extraction failed: ${message}`);
|
|
298
|
+
return { success: false, exitCode: 1 };
|
|
299
|
+
}
|
|
300
|
+
},
|
|
301
|
+
};
|
|
302
|
+
//# sourceMappingURL=analyze-symbols.js.map
|
|
@@ -14,6 +14,44 @@
|
|
|
14
14
|
* github.com/monoes/monomind
|
|
15
15
|
*/
|
|
16
16
|
import type { Command } from '../types.js';
|
|
17
|
+
type AnalyzerModule = any;
|
|
18
|
+
export declare function getASTAnalyzer(): Promise<AnalyzerModule | null>;
|
|
19
|
+
export declare function getGraphAnalyzer(): Promise<AnalyzerModule | null>;
|
|
20
|
+
/**
|
|
21
|
+
* Write analysis output to a file, constraining the path to the current working
|
|
22
|
+
* directory to prevent path traversal attacks via --output /etc/cron.d/x or
|
|
23
|
+
* similar. Throws if the resolved path escapes cwd.
|
|
24
|
+
*/
|
|
25
|
+
export declare function safeWriteOutputFile(outputFile: string, data: string): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Helper: Scan directory for source files
|
|
28
|
+
*/
|
|
29
|
+
export declare function scanSourceFiles(dir: string, maxDepth?: number): Promise<string[]>;
|
|
30
|
+
/**
|
|
31
|
+
* Fallback analysis when monovector is not available
|
|
32
|
+
*/
|
|
33
|
+
export declare function fallbackAnalyze(code: string, filePath: string): {
|
|
34
|
+
filePath: string;
|
|
35
|
+
language: string;
|
|
36
|
+
functions: {
|
|
37
|
+
name: string;
|
|
38
|
+
startLine: number;
|
|
39
|
+
endLine: number;
|
|
40
|
+
}[];
|
|
41
|
+
classes: {
|
|
42
|
+
name: string;
|
|
43
|
+
startLine: number;
|
|
44
|
+
endLine: number;
|
|
45
|
+
}[];
|
|
46
|
+
imports: string[];
|
|
47
|
+
exports: string[];
|
|
48
|
+
complexity: {
|
|
49
|
+
cyclomatic: number;
|
|
50
|
+
cognitive: number;
|
|
51
|
+
loc: number;
|
|
52
|
+
commentDensity: number;
|
|
53
|
+
};
|
|
54
|
+
};
|
|
17
55
|
export declare const analyzeCommand: Command;
|
|
18
56
|
export default analyzeCommand;
|
|
19
57
|
//# sourceMappingURL=analyze.d.ts.map
|