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.
Files changed (94) hide show
  1. package/.claude/agents/engineering/engineering-security-engineer.md +1 -1
  2. package/.claude/commands/mastermind/_repeat.md +4 -0
  3. package/.claude/commands/mastermind/master.md +52 -1
  4. package/.claude/scheduled_tasks.lock +1 -1
  5. package/.claude/skills/mastermind/_repeat.md +2 -0
  6. package/package.json +1 -1
  7. package/packages/@monomind/cli/.claude/agents/engineering/engineering-security-engineer.md +1 -1
  8. package/packages/@monomind/cli/.claude/commands/mastermind/_repeat.md +4 -0
  9. package/packages/@monomind/cli/.claude/commands/mastermind/master.md +52 -1
  10. package/packages/@monomind/cli/.claude/skills/mastermind/_repeat.md +2 -0
  11. package/packages/@monomind/cli/dist/src/__tests__/browse-analyzer.test.js +42 -59
  12. package/packages/@monomind/cli/dist/src/agents/registry-builder.d.ts +8 -0
  13. package/packages/@monomind/cli/dist/src/agents/registry-builder.js +22 -0
  14. package/packages/@monomind/cli/dist/src/browser/dashboard/server.js +18 -0
  15. package/packages/@monomind/cli/dist/src/browser/dashboard/ui.html +37 -125
  16. package/packages/@monomind/cli/dist/src/commands/agent-lifecycle.d.ts +17 -0
  17. package/packages/@monomind/cli/dist/src/commands/agent-lifecycle.js +320 -0
  18. package/packages/@monomind/cli/dist/src/commands/agent-ops.d.ts +9 -0
  19. package/packages/@monomind/cli/dist/src/commands/agent-ops.js +329 -0
  20. package/packages/@monomind/cli/dist/src/commands/agent.js +5 -907
  21. package/packages/@monomind/cli/dist/src/commands/analyze-ast.d.ts +26 -0
  22. package/packages/@monomind/cli/dist/src/commands/analyze-ast.js +284 -0
  23. package/packages/@monomind/cli/dist/src/commands/analyze-boundaries.d.ts +14 -0
  24. package/packages/@monomind/cli/dist/src/commands/analyze-boundaries.js +295 -0
  25. package/packages/@monomind/cli/dist/src/commands/analyze-diff.d.ts +8 -0
  26. package/packages/@monomind/cli/dist/src/commands/analyze-diff.js +395 -0
  27. package/packages/@monomind/cli/dist/src/commands/analyze-graph.d.ts +14 -0
  28. package/packages/@monomind/cli/dist/src/commands/analyze-graph.js +304 -0
  29. package/packages/@monomind/cli/dist/src/commands/analyze-imports.d.ts +11 -0
  30. package/packages/@monomind/cli/dist/src/commands/analyze-imports.js +287 -0
  31. package/packages/@monomind/cli/dist/src/commands/analyze-symbols.d.ts +14 -0
  32. package/packages/@monomind/cli/dist/src/commands/analyze-symbols.js +302 -0
  33. package/packages/@monomind/cli/dist/src/commands/analyze.d.ts +38 -0
  34. package/packages/@monomind/cli/dist/src/commands/analyze.js +12 -1827
  35. package/packages/@monomind/cli/dist/src/commands/doctor-env-checks.d.ts +26 -0
  36. package/packages/@monomind/cli/dist/src/commands/doctor-env-checks.js +189 -0
  37. package/packages/@monomind/cli/dist/src/commands/doctor-project-checks.d.ts +20 -0
  38. package/packages/@monomind/cli/dist/src/commands/doctor-project-checks.js +432 -0
  39. package/packages/@monomind/cli/dist/src/commands/doctor.js +54 -943
  40. package/packages/@monomind/cli/dist/src/commands/hive-mind-comms.d.ts +11 -0
  41. package/packages/@monomind/cli/dist/src/commands/hive-mind-comms.js +242 -0
  42. package/packages/@monomind/cli/dist/src/commands/hive-mind-helpers.d.ts +35 -0
  43. package/packages/@monomind/cli/dist/src/commands/hive-mind-helpers.js +203 -0
  44. package/packages/@monomind/cli/dist/src/commands/hive-mind-ops.d.ts +8 -0
  45. package/packages/@monomind/cli/dist/src/commands/hive-mind-ops.js +233 -0
  46. package/packages/@monomind/cli/dist/src/commands/hive-mind-spawn.d.ts +12 -0
  47. package/packages/@monomind/cli/dist/src/commands/hive-mind-spawn.js +274 -0
  48. package/packages/@monomind/cli/dist/src/commands/hive-mind.js +10 -1129
  49. package/packages/@monomind/cli/dist/src/commands/hooks-coverage-commands.d.ts +4 -4
  50. package/packages/@monomind/cli/dist/src/commands/hooks-coverage-commands.js +19 -819
  51. package/packages/@monomind/cli/dist/src/commands/hooks-coverage-gaps.d.ts +7 -0
  52. package/packages/@monomind/cli/dist/src/commands/hooks-coverage-gaps.js +334 -0
  53. package/packages/@monomind/cli/dist/src/commands/hooks-coverage-routing.d.ts +7 -0
  54. package/packages/@monomind/cli/dist/src/commands/hooks-coverage-routing.js +399 -0
  55. package/packages/@monomind/cli/dist/src/commands/init-subcommands.d.ts +8 -0
  56. package/packages/@monomind/cli/dist/src/commands/init-subcommands.js +156 -0
  57. package/packages/@monomind/cli/dist/src/commands/init-upgrade.d.ts +6 -0
  58. package/packages/@monomind/cli/dist/src/commands/init-upgrade.js +203 -0
  59. package/packages/@monomind/cli/dist/src/commands/init-wizard.d.ts +6 -0
  60. package/packages/@monomind/cli/dist/src/commands/init-wizard.js +246 -0
  61. package/packages/@monomind/cli/dist/src/commands/init.js +6 -623
  62. package/packages/@monomind/cli/dist/src/commands/memory-admin.d.ts +10 -0
  63. package/packages/@monomind/cli/dist/src/commands/memory-admin.js +433 -0
  64. package/packages/@monomind/cli/dist/src/commands/memory-crud.d.ts +9 -0
  65. package/packages/@monomind/cli/dist/src/commands/memory-crud.js +342 -0
  66. package/packages/@monomind/cli/dist/src/commands/memory-list.d.ts +10 -0
  67. package/packages/@monomind/cli/dist/src/commands/memory-list.js +321 -0
  68. package/packages/@monomind/cli/dist/src/commands/memory-transfer.d.ts +9 -0
  69. package/packages/@monomind/cli/dist/src/commands/memory-transfer.js +372 -0
  70. package/packages/@monomind/cli/dist/src/commands/memory.d.ts +6 -0
  71. package/packages/@monomind/cli/dist/src/commands/memory.js +10 -1441
  72. package/packages/@monomind/cli/dist/src/commands/neural-core.d.ts +8 -0
  73. package/packages/@monomind/cli/dist/src/commands/neural-core.js +274 -0
  74. package/packages/@monomind/cli/dist/src/commands/neural-optimize.d.ts +7 -0
  75. package/packages/@monomind/cli/dist/src/commands/neural-optimize.js +332 -0
  76. package/packages/@monomind/cli/dist/src/commands/neural-registry.d.ts +7 -0
  77. package/packages/@monomind/cli/dist/src/commands/neural-registry.js +290 -0
  78. package/packages/@monomind/cli/dist/src/commands/neural.js +3 -974
  79. package/packages/@monomind/cli/dist/src/commands/platforms.js +327 -7
  80. package/packages/@monomind/cli/dist/src/commands/security-cve.d.ts +6 -0
  81. package/packages/@monomind/cli/dist/src/commands/security-cve.js +310 -0
  82. package/packages/@monomind/cli/dist/src/commands/security-misc.d.ts +9 -0
  83. package/packages/@monomind/cli/dist/src/commands/security-misc.js +293 -0
  84. package/packages/@monomind/cli/dist/src/commands/security-scan.d.ts +18 -0
  85. package/packages/@monomind/cli/dist/src/commands/security-scan.js +328 -0
  86. package/packages/@monomind/cli/dist/src/commands/security.js +3 -958
  87. package/packages/@monomind/cli/dist/src/commands/session.js +1 -1
  88. package/packages/@monomind/cli/dist/src/commands/swarm.js +23 -17
  89. package/packages/@monomind/cli/dist/src/index.js +8 -37
  90. package/packages/@monomind/cli/dist/src/mcp-tools/swarm-tools.js +77 -0
  91. package/packages/@monomind/cli/dist/src/parser.js +11 -6
  92. package/packages/@monomind/cli/dist/src/routing/llm-caller.js +1 -2
  93. package/packages/@monomind/cli/package.json +2 -3
  94. package/packages/@monomind/cli/scripts/understand-analyze.mjs +1 -1
@@ -0,0 +1,304 @@
1
+ /**
2
+ * Analyze dependencies and circular subcommands
3
+ * Full dependency graph building and circular dependency detection
4
+ */
5
+ import { output } from '../output.js';
6
+ import { resolve } from 'path';
7
+ import { getGraphAnalyzer, safeWriteOutputFile } from './analyze.js';
8
+ /**
9
+ * Build and export dependency graph
10
+ */
11
+ export const dependenciesCommand = {
12
+ name: 'dependencies',
13
+ aliases: ['graph'],
14
+ description: 'Build and export full dependency graph',
15
+ options: [
16
+ {
17
+ name: 'output',
18
+ short: 'o',
19
+ description: 'Output file path',
20
+ type: 'string',
21
+ },
22
+ {
23
+ name: 'format',
24
+ short: 'f',
25
+ description: 'Output format (text, json, dot)',
26
+ type: 'string',
27
+ default: 'text',
28
+ choices: ['text', 'json', 'dot'],
29
+ },
30
+ {
31
+ name: 'include',
32
+ short: 'i',
33
+ description: 'File extensions to include (comma-separated)',
34
+ type: 'string',
35
+ default: '.ts,.tsx,.js,.jsx,.mjs,.cjs',
36
+ },
37
+ {
38
+ name: 'exclude',
39
+ short: 'e',
40
+ description: 'Patterns to exclude (comma-separated)',
41
+ type: 'string',
42
+ default: 'node_modules,dist,build,.git',
43
+ },
44
+ {
45
+ name: 'depth',
46
+ short: 'd',
47
+ description: 'Maximum directory depth',
48
+ type: 'number',
49
+ default: 10,
50
+ },
51
+ ],
52
+ examples: [
53
+ { command: 'monomind analyze dependencies src/', description: 'Build dependency graph' },
54
+ { command: 'monomind analyze dependencies -f dot -o deps.dot src/', description: 'Export to DOT' },
55
+ { command: 'monomind analyze dependencies -i .ts,.tsx src/', description: 'Only TypeScript files' },
56
+ ],
57
+ action: async (ctx) => {
58
+ const targetDir = ctx.args[0] || ctx.cwd;
59
+ const outputFile = ctx.flags.output;
60
+ const format = ctx.flags.format || 'text';
61
+ const include = (ctx.flags.include || '.ts,.tsx,.js,.jsx,.mjs,.cjs').split(',');
62
+ const exclude = (ctx.flags.exclude || 'node_modules,dist,build,.git').split(',');
63
+ const rawDepth = ctx.flags.depth || 10;
64
+ const maxDepth = Number.isFinite(rawDepth) ? Math.max(1, Math.min(rawDepth, 50)) : 10;
65
+ output.printInfo(`Building dependency graph for: ${output.highlight(targetDir)}`);
66
+ output.writeln();
67
+ const spinner = output.createSpinner({ text: 'Scanning files...', spinner: 'dots' });
68
+ spinner.start();
69
+ try {
70
+ const analyzer = await getGraphAnalyzer();
71
+ if (!analyzer) {
72
+ spinner.stop();
73
+ output.printError('Graph analyzer module not available');
74
+ return { success: false, exitCode: 1 };
75
+ }
76
+ const graph = await analyzer.buildDependencyGraph(resolve(targetDir), {
77
+ include,
78
+ exclude,
79
+ maxDepth,
80
+ });
81
+ spinner.stop();
82
+ // Detect circular dependencies
83
+ const circularDeps = analyzer.detectCircularDependencies(graph);
84
+ // Handle different output formats
85
+ if (format === 'json') {
86
+ const jsonOutput = {
87
+ nodes: Array.from(graph.nodes.values()),
88
+ edges: graph.edges,
89
+ metadata: graph.metadata,
90
+ circularDependencies: circularDeps,
91
+ };
92
+ if (outputFile) {
93
+ await safeWriteOutputFile(outputFile, JSON.stringify(jsonOutput, null, 2));
94
+ output.printSuccess(`Graph written to ${outputFile}`);
95
+ }
96
+ else {
97
+ output.printJson(jsonOutput);
98
+ }
99
+ return { success: true, data: jsonOutput };
100
+ }
101
+ if (format === 'dot') {
102
+ const result = { graph, circularDependencies: circularDeps, statistics: {
103
+ nodeCount: graph.nodes.size,
104
+ edgeCount: graph.edges.length,
105
+ avgDegree: 0,
106
+ maxDegree: 0,
107
+ density: 0,
108
+ componentCount: 0,
109
+ } };
110
+ const dotOutput = analyzer.exportToDot(result, {
111
+ includeLabels: true,
112
+ highlightCycles: true,
113
+ });
114
+ if (outputFile) {
115
+ await safeWriteOutputFile(outputFile, dotOutput);
116
+ output.printSuccess(`DOT graph written to ${outputFile}`);
117
+ output.writeln(output.dim('Visualize with: dot -Tpng -o deps.png ' + outputFile));
118
+ }
119
+ else {
120
+ output.writeln(dotOutput);
121
+ }
122
+ return { success: true };
123
+ }
124
+ // Text format (default)
125
+ output.printBox([
126
+ `Files: ${graph.metadata.totalFiles}`,
127
+ `Dependencies: ${graph.metadata.totalEdges}`,
128
+ `Build time: ${graph.metadata.buildTime}ms`,
129
+ `Root: ${graph.metadata.rootDir}`,
130
+ ].join('\n'), 'Dependency Graph');
131
+ // Show top files by imports
132
+ output.writeln();
133
+ output.writeln(output.bold('Most Connected Files'));
134
+ output.writeln();
135
+ const nodesByDegree = Array.from(graph.nodes.values())
136
+ .map((n) => ({
137
+ ...n,
138
+ degree: graph.edges.filter((e) => e.source === n.id || e.target === n.id).length,
139
+ }))
140
+ .sort((a, b) => b.degree - a.degree)
141
+ .slice(0, 10);
142
+ output.printTable({
143
+ columns: [
144
+ { key: 'path', header: 'File', width: 50 },
145
+ { key: 'degree', header: 'Connections', width: 12, align: 'right' },
146
+ { key: 'complexity', header: 'Complexity', width: 12, align: 'right' },
147
+ ],
148
+ data: nodesByDegree.map(n => ({
149
+ path: n.path.length > 48 ? '...' + n.path.slice(-45) : n.path,
150
+ degree: n.degree,
151
+ complexity: n.complexity || 0,
152
+ })),
153
+ });
154
+ // Show circular dependencies
155
+ if (circularDeps.length > 0) {
156
+ output.writeln();
157
+ output.writeln(output.bold(output.warning(`Circular Dependencies: ${circularDeps.length}`)));
158
+ output.writeln();
159
+ for (const cycle of circularDeps.slice(0, 3)) {
160
+ output.writeln(` ${cycle.cycle.join(' -> ')}`);
161
+ }
162
+ if (circularDeps.length > 3) {
163
+ output.writeln(output.dim(` ... and ${circularDeps.length - 3} more`));
164
+ }
165
+ }
166
+ if (outputFile) {
167
+ const fullOutput = {
168
+ nodes: Array.from(graph.nodes.values()),
169
+ edges: graph.edges,
170
+ metadata: graph.metadata,
171
+ circularDependencies: circularDeps,
172
+ };
173
+ await safeWriteOutputFile(outputFile, JSON.stringify(fullOutput, null, 2));
174
+ output.printSuccess(`Full results written to ${outputFile}`);
175
+ }
176
+ return { success: true };
177
+ }
178
+ catch (error) {
179
+ spinner.stop();
180
+ const message = error instanceof Error ? error.message : String(error);
181
+ output.printError(`Analysis failed: ${message}`);
182
+ return { success: false, exitCode: 1 };
183
+ }
184
+ },
185
+ };
186
+ /**
187
+ * Detect circular dependencies
188
+ */
189
+ export const circularCommand = {
190
+ name: 'circular',
191
+ aliases: ['cycles'],
192
+ description: 'Detect circular dependencies in codebase',
193
+ options: [
194
+ {
195
+ name: 'output',
196
+ short: 'o',
197
+ description: 'Output file path',
198
+ type: 'string',
199
+ },
200
+ {
201
+ name: 'format',
202
+ short: 'f',
203
+ description: 'Output format (text, json)',
204
+ type: 'string',
205
+ default: 'text',
206
+ choices: ['text', 'json'],
207
+ },
208
+ {
209
+ name: 'severity',
210
+ short: 's',
211
+ description: 'Minimum severity to show (low, medium, high)',
212
+ type: 'string',
213
+ default: 'low',
214
+ choices: ['low', 'medium', 'high'],
215
+ },
216
+ ],
217
+ examples: [
218
+ { command: 'monomind analyze circular src/', description: 'Find circular dependencies' },
219
+ { command: 'monomind analyze circular -s high src/', description: 'Only high severity cycles' },
220
+ ],
221
+ action: async (ctx) => {
222
+ const targetDir = ctx.args[0] || ctx.cwd;
223
+ const outputFile = ctx.flags.output;
224
+ const format = ctx.flags.format || 'text';
225
+ const minSeverity = ctx.flags.severity || 'low';
226
+ output.printInfo(`Detecting circular dependencies in: ${output.highlight(targetDir)}`);
227
+ output.writeln();
228
+ const spinner = output.createSpinner({ text: 'Analyzing dependencies...', spinner: 'dots' });
229
+ spinner.start();
230
+ try {
231
+ const analyzer = await getGraphAnalyzer();
232
+ if (!analyzer) {
233
+ spinner.stop();
234
+ output.printError('Graph analyzer module not available');
235
+ return { success: false, exitCode: 1 };
236
+ }
237
+ const graph = await analyzer.buildDependencyGraph(resolve(targetDir));
238
+ const cycles = analyzer.detectCircularDependencies(graph);
239
+ spinner.stop();
240
+ // Filter by severity
241
+ const severityOrder = { low: 0, medium: 1, high: 2 };
242
+ const minLevel = severityOrder[minSeverity] || 0;
243
+ const filtered = cycles.filter(c => severityOrder[c.severity] >= minLevel);
244
+ if (format === 'json') {
245
+ const jsonOutput = { cycles: filtered, total: cycles.length, filtered: filtered.length };
246
+ if (outputFile) {
247
+ await safeWriteOutputFile(outputFile, JSON.stringify(jsonOutput, null, 2));
248
+ output.printSuccess(`Results written to ${outputFile}`);
249
+ }
250
+ else {
251
+ output.printJson(jsonOutput);
252
+ }
253
+ return { success: true, data: jsonOutput };
254
+ }
255
+ // Text format
256
+ if (filtered.length === 0) {
257
+ output.printSuccess('No circular dependencies found!');
258
+ return { success: true };
259
+ }
260
+ output.printBox([
261
+ `Total cycles: ${cycles.length}`,
262
+ `Shown (${minSeverity}+): ${filtered.length}`,
263
+ `High severity: ${cycles.filter(c => c.severity === 'high').length}`,
264
+ `Medium severity: ${cycles.filter(c => c.severity === 'medium').length}`,
265
+ `Low severity: ${cycles.filter(c => c.severity === 'low').length}`,
266
+ ].join('\n'), 'Circular Dependencies');
267
+ output.writeln();
268
+ // Group by severity
269
+ const grouped = {
270
+ high: filtered.filter(c => c.severity === 'high'),
271
+ medium: filtered.filter(c => c.severity === 'medium'),
272
+ low: filtered.filter(c => c.severity === 'low'),
273
+ };
274
+ for (const [severity, items] of Object.entries(grouped)) {
275
+ if (items.length === 0)
276
+ continue;
277
+ const color = severity === 'high' ? output.error : severity === 'medium' ? output.warning : output.dim;
278
+ output.writeln(color(output.bold(`${severity.toUpperCase()} SEVERITY (${items.length})`)));
279
+ output.writeln();
280
+ for (const cycle of items.slice(0, 5)) {
281
+ output.writeln(` ${cycle.cycle.join(' -> ')}`);
282
+ output.writeln(output.dim(` Fix: ${cycle.suggestion}`));
283
+ output.writeln();
284
+ }
285
+ if (items.length > 5) {
286
+ output.writeln(output.dim(` ... and ${items.length - 5} more ${severity} cycles`));
287
+ output.writeln();
288
+ }
289
+ }
290
+ if (outputFile) {
291
+ await safeWriteOutputFile(outputFile, JSON.stringify({ cycles: filtered }, null, 2));
292
+ output.printSuccess(`Results written to ${outputFile}`);
293
+ }
294
+ return { success: true, data: { cycles: filtered } };
295
+ }
296
+ catch (error) {
297
+ spinner.stop();
298
+ const message = error instanceof Error ? error.message : String(error);
299
+ output.printError(`Analysis failed: ${message}`);
300
+ return { success: false, exitCode: 1 };
301
+ }
302
+ },
303
+ };
304
+ //# sourceMappingURL=analyze-graph.js.map
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Analyze imports and deps subcommands
3
+ * Import dependency analysis and project dependency checking
4
+ */
5
+ import type { Command } from '../types.js';
6
+ /**
7
+ * Imports analysis subcommand
8
+ */
9
+ export declare const importsCommand: Command;
10
+ export declare const depsCommand: Command;
11
+ //# sourceMappingURL=analyze-imports.d.ts.map
@@ -0,0 +1,287 @@
1
+ /**
2
+ * Analyze imports and deps subcommands
3
+ * Import dependency analysis and project dependency checking
4
+ */
5
+ import { output } from '../output.js';
6
+ import * as fs from 'fs/promises';
7
+ import { resolve } from 'path';
8
+ import { execSync } from 'child_process';
9
+ import { getASTAnalyzer, safeWriteOutputFile, scanSourceFiles, fallbackAnalyze } from './analyze.js';
10
+ /**
11
+ * Imports analysis subcommand
12
+ */
13
+ export const importsCommand = {
14
+ name: 'imports',
15
+ aliases: ['imp'],
16
+ description: 'Analyze import dependencies across files',
17
+ options: [
18
+ {
19
+ name: 'format',
20
+ short: 'f',
21
+ description: 'Output format (text, json)',
22
+ type: 'string',
23
+ default: 'text',
24
+ choices: ['text', 'json'],
25
+ },
26
+ {
27
+ name: 'output',
28
+ short: 'o',
29
+ description: 'Output file path',
30
+ type: 'string',
31
+ },
32
+ {
33
+ name: 'external',
34
+ short: 'e',
35
+ description: 'Show only external (npm) imports',
36
+ type: 'boolean',
37
+ default: false,
38
+ },
39
+ ],
40
+ examples: [
41
+ { command: 'monomind analyze imports src/', description: 'Analyze all imports' },
42
+ { command: 'monomind analyze imports src/ --external', description: 'Only npm packages' },
43
+ ],
44
+ action: async (ctx) => {
45
+ const targetPath = ctx.args[0] || ctx.cwd;
46
+ const formatType = ctx.flags.format || 'text';
47
+ const outputFile = ctx.flags.output;
48
+ const externalOnly = ctx.flags.external;
49
+ output.printInfo(`Analyzing imports: ${output.highlight(targetPath)}`);
50
+ output.writeln();
51
+ const spinner = output.createSpinner({ text: 'Scanning imports...', 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 importCounts = new Map();
59
+ const fileImports = new Map();
60
+ for (const file of files.slice(0, 100)) {
61
+ try {
62
+ const content = await fs.readFile(file, 'utf-8');
63
+ let analysis;
64
+ if (astModule) {
65
+ const analyzer = astModule.createASTAnalyzer();
66
+ analysis = analyzer.analyze(content, file);
67
+ }
68
+ else {
69
+ analysis = fallbackAnalyze(content, file);
70
+ }
71
+ const imports = analysis.imports.filter(imp => {
72
+ if (externalOnly) {
73
+ return !imp.startsWith('.') && !imp.startsWith('/');
74
+ }
75
+ return true;
76
+ });
77
+ fileImports.set(file, imports);
78
+ for (const imp of imports) {
79
+ const existing = importCounts.get(imp) || { count: 0, files: [] };
80
+ existing.count++;
81
+ existing.files.push(file);
82
+ importCounts.set(imp, existing);
83
+ }
84
+ }
85
+ catch {
86
+ // Skip files that can't be parsed
87
+ }
88
+ }
89
+ spinner.stop();
90
+ // Sort by count
91
+ const sortedImports = Array.from(importCounts.entries())
92
+ .sort((a, b) => b[1].count - a[1].count);
93
+ if (formatType === 'json') {
94
+ const jsonOutput = {
95
+ imports: Object.fromEntries(sortedImports),
96
+ fileImports: Object.fromEntries(fileImports),
97
+ };
98
+ if (outputFile) {
99
+ await safeWriteOutputFile(outputFile, JSON.stringify(jsonOutput, null, 2));
100
+ output.printSuccess(`Results written to ${outputFile}`);
101
+ }
102
+ else {
103
+ output.printJson(jsonOutput);
104
+ }
105
+ return { success: true, data: jsonOutput };
106
+ }
107
+ // Summary
108
+ const externalImports = sortedImports.filter(([imp]) => !imp.startsWith('.') && !imp.startsWith('/'));
109
+ const localImports = sortedImports.filter(([imp]) => imp.startsWith('.') || imp.startsWith('/'));
110
+ output.printBox([
111
+ `Total unique imports: ${sortedImports.length}`,
112
+ `External (npm): ${externalImports.length}`,
113
+ `Local (relative): ${localImports.length}`,
114
+ `Files scanned: ${files.length}`,
115
+ ].join('\n'), 'Import Analysis');
116
+ // Most used imports
117
+ output.writeln();
118
+ output.writeln(output.bold('Most Used Imports'));
119
+ output.writeln(output.dim('-'.repeat(60)));
120
+ const topImports = sortedImports.slice(0, 20);
121
+ output.printTable({
122
+ columns: [
123
+ { key: 'count', header: 'Uses', width: 8, align: 'right' },
124
+ { key: 'import', header: 'Import', width: 50 },
125
+ { key: 'type', header: 'Type', width: 10 },
126
+ ],
127
+ data: topImports.map(([imp, data]) => ({
128
+ count: data.count,
129
+ import: imp,
130
+ type: imp.startsWith('.') || imp.startsWith('/') ? output.dim('local') : output.highlight('npm'),
131
+ })),
132
+ });
133
+ if (sortedImports.length > 20) {
134
+ output.writeln(output.dim(` ... and ${sortedImports.length - 20} more imports`));
135
+ }
136
+ if (outputFile) {
137
+ await safeWriteOutputFile(outputFile, JSON.stringify({
138
+ imports: Object.fromEntries(sortedImports),
139
+ fileImports: Object.fromEntries(fileImports),
140
+ }, null, 2));
141
+ output.printSuccess(`Results written to ${outputFile}`);
142
+ }
143
+ return { success: true, data: { imports: sortedImports } };
144
+ }
145
+ catch (error) {
146
+ spinner.stop();
147
+ const message = error instanceof Error ? error.message : String(error);
148
+ output.printError(`Import analysis failed: ${message}`);
149
+ return { success: false, exitCode: 1 };
150
+ }
151
+ },
152
+ };
153
+ // Dependencies subcommand
154
+ export const depsCommand = {
155
+ name: 'deps',
156
+ description: 'Analyze project dependencies',
157
+ options: [
158
+ { name: 'outdated', short: 'o', type: 'boolean', description: 'Show only outdated dependencies' },
159
+ { name: 'security', short: 's', type: 'boolean', description: 'Check for security vulnerabilities' },
160
+ { name: 'format', short: 'f', type: 'string', description: 'Output format: text, json', default: 'text' },
161
+ ],
162
+ examples: [
163
+ { command: 'monomind analyze deps --outdated', description: 'Show outdated dependencies' },
164
+ { command: 'monomind analyze deps --security', description: 'Check for vulnerabilities' },
165
+ ],
166
+ action: async (ctx) => {
167
+ const showOutdated = ctx.flags.outdated;
168
+ const checkSecurity = ctx.flags.security;
169
+ const formatJson = ctx.flags.format === 'json';
170
+ output.writeln();
171
+ output.writeln(output.bold('Dependency Analysis'));
172
+ output.writeln(output.dim('-'.repeat(50)));
173
+ try {
174
+ const pkgPath = resolve('package.json');
175
+ let pkgContent;
176
+ try {
177
+ pkgContent = await fs.readFile(pkgPath, 'utf-8');
178
+ }
179
+ catch {
180
+ output.printError('No package.json found in current directory');
181
+ return { success: false, exitCode: 1 };
182
+ }
183
+ const pkg = JSON.parse(pkgContent);
184
+ const deps = Object.entries(pkg.dependencies || {});
185
+ const devDeps = Object.entries(pkg.devDependencies || {});
186
+ const optDeps = Object.entries(pkg.optionalDependencies || {});
187
+ const peerDeps = Object.entries(pkg.peerDependencies || {});
188
+ const total = deps.length + devDeps.length + optDeps.length + peerDeps.length;
189
+ if (formatJson && !showOutdated && !checkSecurity) {
190
+ const jsonData = { name: pkg.name, version: pkg.version, dependencies: deps.length, devDependencies: devDeps.length, optionalDependencies: optDeps.length, peerDependencies: peerDeps.length, total };
191
+ output.printJson(jsonData);
192
+ return { success: true, data: jsonData };
193
+ }
194
+ output.printBox([`Package: ${pkg.name || 'unknown'} @ ${pkg.version || '0.0.0'}`, `Dependencies: ${deps.length}`, `Dev Dependencies: ${devDeps.length}`, `Optional: ${optDeps.length}`, `Peer: ${peerDeps.length}`, `Total: ${total}`].join('\n'), 'Dependency Summary');
195
+ if (showOutdated) {
196
+ output.writeln();
197
+ output.writeln(output.bold('Outdated Check'));
198
+ output.writeln(output.dim('-'.repeat(60)));
199
+ const outdated = [];
200
+ const checkDeps = async (entries, category) => {
201
+ for (const [name, declared] of entries) {
202
+ try {
203
+ const installedPkg = resolve('node_modules', name, 'package.json');
204
+ const raw = await fs.readFile(installedPkg, 'utf-8');
205
+ const installedContent = JSON.parse(raw);
206
+ const installed = installedContent.version || 'unknown';
207
+ const cleanDeclared = declared.replace(/^[\^~>=<]+/, '');
208
+ if (installed !== cleanDeclared) {
209
+ outdated.push({ name, declared: declared, installed, category });
210
+ }
211
+ }
212
+ catch {
213
+ outdated.push({ name, declared: declared, installed: 'not installed', category });
214
+ }
215
+ }
216
+ };
217
+ await checkDeps(deps, 'prod');
218
+ await checkDeps(devDeps, 'dev');
219
+ if (outdated.length === 0) {
220
+ output.printSuccess('All dependencies match declared versions');
221
+ }
222
+ else {
223
+ output.printTable({
224
+ columns: [
225
+ { key: 'name', header: 'Package', width: 30 },
226
+ { key: 'declared', header: 'Declared', width: 14 },
227
+ { key: 'installed', header: 'Installed', width: 14 },
228
+ { key: 'category', header: 'Type', width: 6 },
229
+ ],
230
+ data: outdated.slice(0, 30),
231
+ });
232
+ if (outdated.length > 30) {
233
+ output.writeln(output.dim(` ... and ${outdated.length - 30} more`));
234
+ }
235
+ }
236
+ }
237
+ if (checkSecurity) {
238
+ output.writeln();
239
+ output.writeln(output.bold('Security Audit'));
240
+ output.writeln(output.dim('-'.repeat(60)));
241
+ try {
242
+ const auditRaw = execSync('npm audit --json 2>/dev/null', { encoding: 'utf-8', maxBuffer: 10 * 1024 * 1024 });
243
+ const audit = JSON.parse(auditRaw);
244
+ const vulns = audit.metadata?.vulnerabilities || audit.vulnerabilities || {};
245
+ const info = vulns.info || 0;
246
+ const low = vulns.low || 0;
247
+ const moderate = vulns.moderate || 0;
248
+ const high = vulns.high || 0;
249
+ const critical = vulns.critical || 0;
250
+ const totalVulns = info + low + moderate + high + critical;
251
+ if (totalVulns === 0) {
252
+ output.printSuccess('No known vulnerabilities found');
253
+ }
254
+ else {
255
+ output.printTable({
256
+ columns: [
257
+ { key: 'severity', header: 'Severity', width: 12 },
258
+ { key: 'count', header: 'Count', width: 8, align: 'right' },
259
+ ],
260
+ data: [
261
+ ...(critical > 0 ? [{ severity: 'Critical', count: critical }] : []),
262
+ ...(high > 0 ? [{ severity: 'High', count: high }] : []),
263
+ ...(moderate > 0 ? [{ severity: 'Moderate', count: moderate }] : []),
264
+ ...(low > 0 ? [{ severity: 'Low', count: low }] : []),
265
+ ...(info > 0 ? [{ severity: 'Info', count: info }] : []),
266
+ { severity: 'Total', count: totalVulns },
267
+ ],
268
+ });
269
+ if (critical > 0 || high > 0) {
270
+ output.printWarning(`${critical + high} high/critical vulnerabilities found. Run 'npm audit' for details.`);
271
+ }
272
+ }
273
+ }
274
+ catch {
275
+ output.printWarning('npm audit failed. Ensure npm is available and node_modules is installed.');
276
+ }
277
+ }
278
+ return { success: true };
279
+ }
280
+ catch (error) {
281
+ const message = error instanceof Error ? error.message : String(error);
282
+ output.printError(`Dependency analysis failed: ${message}`);
283
+ return { success: false, exitCode: 1 };
284
+ }
285
+ },
286
+ };
287
+ //# sourceMappingURL=analyze-imports.js.map
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Analyze complexity and symbols subcommands
3
+ * Complexity analysis and symbol extraction from code files
4
+ */
5
+ import type { Command } from '../types.js';
6
+ /**
7
+ * Complexity analysis subcommand
8
+ */
9
+ export declare const complexityAstCommand: Command;
10
+ /**
11
+ * Symbol extraction subcommand
12
+ */
13
+ export declare const symbolsCommand: Command;
14
+ //# sourceMappingURL=analyze-symbols.d.ts.map