add-skill-kit 3.2.4 → 3.2.5

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 (74) hide show
  1. package/README.md +1 -1
  2. package/bin/lib/commands/help.js +0 -4
  3. package/bin/lib/commands/install.js +90 -9
  4. package/bin/lib/ui.js +1 -1
  5. package/lib/agent-cli/__tests__/adaptive_engine.test.js +190 -0
  6. package/lib/agent-cli/__tests__/integration/cross_script.test.js +222 -0
  7. package/lib/agent-cli/__tests__/integration/full_cycle.test.js +230 -0
  8. package/lib/agent-cli/__tests__/pattern_analyzer.test.js +173 -0
  9. package/lib/agent-cli/__tests__/pre_execution_check.test.js +167 -0
  10. package/lib/agent-cli/__tests__/skill_injector.test.js +191 -0
  11. package/lib/agent-cli/bin/{ag-smart.js → agent.js} +48 -15
  12. package/lib/agent-cli/dashboard/dashboard_server.js +340 -0
  13. package/lib/agent-cli/dashboard/index.html +538 -0
  14. package/lib/agent-cli/lib/audit.js +2 -2
  15. package/lib/agent-cli/lib/auto-learn.js +8 -8
  16. package/lib/agent-cli/lib/eslint-fix.js +1 -1
  17. package/lib/agent-cli/lib/fix.js +5 -5
  18. package/lib/agent-cli/lib/hooks/install-hooks.js +4 -4
  19. package/lib/agent-cli/lib/hooks/lint-learn.js +4 -4
  20. package/lib/agent-cli/lib/learn.js +10 -10
  21. package/lib/agent-cli/lib/recall.js +1 -1
  22. package/lib/agent-cli/lib/settings.js +24 -0
  23. package/lib/agent-cli/lib/skill-learn.js +2 -2
  24. package/lib/agent-cli/lib/stats.js +3 -3
  25. package/lib/agent-cli/lib/ui/dashboard-ui.js +103 -4
  26. package/lib/agent-cli/lib/ui/index.js +36 -6
  27. package/lib/agent-cli/lib/watcher.js +2 -2
  28. package/lib/agent-cli/package.json +4 -4
  29. package/lib/agent-cli/scripts/adaptive_engine.js +381 -0
  30. package/lib/agent-cli/scripts/dashboard_server.js +224 -0
  31. package/lib/agent-cli/scripts/error_sensor.js +565 -0
  32. package/lib/agent-cli/scripts/learn_from_failure.js +225 -0
  33. package/lib/agent-cli/scripts/pattern_analyzer.js +781 -0
  34. package/lib/agent-cli/scripts/pre_execution_check.js +623 -0
  35. package/lib/agent-cli/scripts/rule_sharing.js +374 -0
  36. package/lib/agent-cli/scripts/skill_injector.js +387 -0
  37. package/lib/agent-cli/scripts/success_sensor.js +500 -0
  38. package/lib/agent-cli/scripts/user_correction_sensor.js +426 -0
  39. package/lib/agent-cli/services/auto-learn-service.js +247 -0
  40. package/lib/agent-cli/src/MIGRATION.md +418 -0
  41. package/lib/agent-cli/src/README.md +367 -0
  42. package/lib/agent-cli/src/core/evolution/evolution-signal.js +42 -0
  43. package/lib/agent-cli/src/core/evolution/index.js +17 -0
  44. package/lib/agent-cli/src/core/evolution/review-gate.js +40 -0
  45. package/lib/agent-cli/src/core/evolution/signal-detector.js +137 -0
  46. package/lib/agent-cli/src/core/evolution/signal-queue.js +79 -0
  47. package/lib/agent-cli/src/core/evolution/threshold-checker.js +79 -0
  48. package/lib/agent-cli/src/core/index.js +15 -0
  49. package/lib/agent-cli/src/core/learning/cognitive-enhancer.js +282 -0
  50. package/lib/agent-cli/src/core/learning/index.js +12 -0
  51. package/lib/agent-cli/src/core/learning/lesson-synthesizer.js +83 -0
  52. package/lib/agent-cli/src/core/scanning/index.js +14 -0
  53. package/lib/agent-cli/src/data/index.js +13 -0
  54. package/lib/agent-cli/src/data/repositories/index.js +8 -0
  55. package/lib/agent-cli/src/data/repositories/lesson-repository.js +130 -0
  56. package/lib/agent-cli/src/data/repositories/signal-repository.js +119 -0
  57. package/lib/agent-cli/src/data/storage/index.js +8 -0
  58. package/lib/agent-cli/src/data/storage/json-storage.js +64 -0
  59. package/lib/agent-cli/src/data/storage/yaml-storage.js +66 -0
  60. package/lib/agent-cli/src/infrastructure/index.js +13 -0
  61. package/lib/agent-cli/src/presentation/formatters/skill-formatter.js +232 -0
  62. package/lib/agent-cli/src/services/export-service.js +162 -0
  63. package/lib/agent-cli/src/services/index.js +13 -0
  64. package/lib/agent-cli/src/services/learning-service.js +99 -0
  65. package/lib/agent-cli/types/index.d.ts +343 -0
  66. package/lib/agent-cli/utils/benchmark.js +269 -0
  67. package/lib/agent-cli/utils/logger.js +303 -0
  68. package/lib/agent-cli/utils/ml_patterns.js +300 -0
  69. package/lib/agent-cli/utils/recovery.js +312 -0
  70. package/lib/agent-cli/utils/telemetry.js +290 -0
  71. package/lib/agentskillskit-cli/ag-smart.js +15 -15
  72. package/lib/agentskillskit-cli/package.json +3 -3
  73. package/package.json +11 -5
  74. /package/bin/{cli.js → kit.js} +0 -0
@@ -0,0 +1,99 @@
1
+ /**
2
+ * LearningService - Application Service
3
+ *
4
+ * Orchestrates learning workflow:
5
+ * - Load raw data (mistakes, improvements)
6
+ * - Synthesize cognitive lessons
7
+ * - Manage lesson CRUD operations
8
+ */
9
+
10
+ import { LessonSynthesizer } from '../core/learning/lesson-synthesizer.js';
11
+
12
+ export class LearningService {
13
+ constructor(lessonRepository) {
14
+ this.lessonRepository = lessonRepository;
15
+ }
16
+
17
+ /**
18
+ * Get all cognitive lessons
19
+ * @returns {Promise<Array>}
20
+ */
21
+ async getCognitiveLessons() {
22
+ const mistakesDb = await this.lessonRepository.loadMistakes();
23
+ const improvementsDb = await this.lessonRepository.loadImprovements();
24
+
25
+ return LessonSynthesizer.synthesize(
26
+ mistakesDb.mistakes || [],
27
+ improvementsDb.improvements || []
28
+ );
29
+ }
30
+
31
+ /**
32
+ * Add a lesson to legacy format
33
+ * @param {string} pattern - Regex pattern
34
+ * @param {string} message - Explanation message
35
+ * @param {string} severity - WARNING or ERROR
36
+ * @param {string} category - Category tag
37
+ * @returns {Promise<object>}
38
+ */
39
+ async addLesson(pattern, message, severity = 'WARNING', category = 'general') {
40
+ // Validate Regex
41
+ try {
42
+ new RegExp(pattern);
43
+ } catch (e) {
44
+ throw new Error(`Invalid Regex pattern: ${e.message}`);
45
+ }
46
+
47
+ // Validate severity
48
+ if (!['WARNING', 'ERROR'].includes(severity.toUpperCase())) {
49
+ throw new Error('Invalid severity. Must be WARNING or ERROR');
50
+ }
51
+
52
+ // Check for duplicates
53
+ const db = await this.lessonRepository.loadLegacyLessons();
54
+ const exists = db.lessons.some(l => l.pattern === pattern);
55
+
56
+ if (exists) {
57
+ throw new Error('Pattern already exists in knowledge base');
58
+ }
59
+
60
+ const id = `LEARN-${String(db.lessons.length + 1).padStart(3, '0')}`;
61
+
62
+ const lesson = {
63
+ id,
64
+ pattern,
65
+ message,
66
+ severity: severity.toUpperCase(),
67
+ category,
68
+ source: 'manual',
69
+ hitCount: 0,
70
+ lastHit: null,
71
+ autoEscalated: false,
72
+ addedAt: new Date().toISOString()
73
+ };
74
+
75
+ return this.lessonRepository.addLegacyLesson(lesson);
76
+ }
77
+
78
+ /**
79
+ * Remove a lesson
80
+ * @param {string} lessonId
81
+ */
82
+ async removeLesson(lessonId) {
83
+ return this.lessonRepository.removeLegacyLesson(lessonId);
84
+ }
85
+
86
+ /**
87
+ * List all lessons
88
+ * @param {string} category - Optional category filter
89
+ */
90
+ async listLessons(category = null) {
91
+ const db = await this.lessonRepository.loadLegacyLessons();
92
+
93
+ if (category) {
94
+ return db.lessons.filter(l => l.category === category);
95
+ }
96
+
97
+ return db.lessons;
98
+ }
99
+ }
@@ -0,0 +1,343 @@
1
+ /**
2
+ * Auto-Learn System TypeScript Definitions
3
+ *
4
+ * Provides type safety for consumers of Auto-Learn scripts.
5
+ * These types match the JSON structures used in .agent/knowledge/
6
+ */
7
+
8
+ // ==================== CORE TYPES ====================
9
+
10
+ /**
11
+ * Severity levels for rules and lessons
12
+ */
13
+ export type Severity = 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL';
14
+
15
+ /**
16
+ * Risk level for intent detection
17
+ */
18
+ export type RiskLevel = 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL';
19
+
20
+ /**
21
+ * Health status for trend analysis
22
+ */
23
+ export type HealthStatus = 'IMPROVING' | 'STABLE' | 'NEUTRAL' | 'DECLINING';
24
+
25
+ // ==================== LESSONS ====================
26
+
27
+ /**
28
+ * A learned lesson from errors or corrections
29
+ */
30
+ export interface Lesson {
31
+ id: string;
32
+ pattern: string;
33
+ message: string;
34
+ severity: Severity;
35
+ hitCount?: number;
36
+ successCount?: number;
37
+ lastHit?: string;
38
+ promoted?: boolean;
39
+ promotedAt?: string;
40
+ demoted?: boolean;
41
+ demotedAt?: string;
42
+ previousSeverity?: Severity;
43
+ confidence?: number;
44
+ adjustedAt?: string;
45
+ importedAt?: string;
46
+ source?: 'auto' | 'manual' | 'imported';
47
+ }
48
+
49
+ /**
50
+ * Collection of lessons
51
+ */
52
+ export interface LessonsData {
53
+ lessons: Lesson[];
54
+ lastUpdated?: string;
55
+ }
56
+
57
+ // ==================== ERRORS ====================
58
+
59
+ /**
60
+ * A detected error
61
+ */
62
+ export interface DetectedError {
63
+ id: string;
64
+ type: string;
65
+ source: 'test' | 'build' | 'lint' | 'runtime' | 'code';
66
+ message: string;
67
+ file?: string;
68
+ line?: number;
69
+ severity: Severity;
70
+ timestamp: string;
71
+ context?: ErrorContext;
72
+ }
73
+
74
+ /**
75
+ * Error context information
76
+ */
77
+ export interface ErrorContext {
78
+ project?: ProjectContext;
79
+ file?: FileContext;
80
+ }
81
+
82
+ /**
83
+ * Collection of errors
84
+ */
85
+ export interface ErrorsData {
86
+ errors: DetectedError[];
87
+ lastUpdated?: string;
88
+ }
89
+
90
+ // ==================== SUCCESSES ====================
91
+
92
+ /**
93
+ * A detected success pattern
94
+ */
95
+ export interface SuccessPattern {
96
+ id: string;
97
+ pattern: string;
98
+ type: 'pattern' | 'practice' | 'test' | 'build' | 'lint';
99
+ file?: string;
100
+ detectedAt: string;
101
+ context?: SuccessContext;
102
+ }
103
+
104
+ /**
105
+ * Success context information
106
+ */
107
+ export interface SuccessContext {
108
+ project?: ProjectContext;
109
+ file?: FileContext;
110
+ }
111
+
112
+ /**
113
+ * Collection of successes
114
+ */
115
+ export interface SuccessesData {
116
+ successes: SuccessPattern[];
117
+ lastUpdated?: string;
118
+ }
119
+
120
+ // ==================== CONTEXT ====================
121
+
122
+ /**
123
+ * Project context information
124
+ */
125
+ export interface ProjectContext {
126
+ projectType: 'unknown' | 'nextjs' | 'react' | 'react-native' | 'backend' | 'nodejs';
127
+ framework?: string;
128
+ language: 'javascript' | 'typescript';
129
+ hasTypeScript?: boolean;
130
+ hasTesting?: boolean;
131
+ }
132
+
133
+ /**
134
+ * File context information
135
+ */
136
+ export interface FileContext {
137
+ fileType: string;
138
+ isTypeScript: boolean;
139
+ isTest: boolean;
140
+ isComponent: boolean;
141
+ directory: string;
142
+ fullPath: string;
143
+ area?: 'source' | 'library' | 'test' | 'config' | 'other';
144
+ }
145
+
146
+ // ==================== RULES ====================
147
+
148
+ /**
149
+ * A matched rule from pre-execution check
150
+ */
151
+ export interface RuleMatch {
152
+ id: string;
153
+ name?: string;
154
+ pattern?: string;
155
+ prevention: string;
156
+ severity: Severity;
157
+ source: 'builtin' | 'lesson' | 'auto-rule' | 'active-rule' | 'intent-detection';
158
+ }
159
+
160
+ /**
161
+ * An auto-generated rule
162
+ */
163
+ export interface AutoRule {
164
+ id: string;
165
+ pattern: string;
166
+ prevention: string;
167
+ severity: Severity;
168
+ status: 'proposed' | 'approved' | 'rejected';
169
+ hitCount?: number;
170
+ successRate?: number;
171
+ }
172
+
173
+ // ==================== INTENT DETECTION ====================
174
+
175
+ /**
176
+ * A detected intent from user input
177
+ */
178
+ export interface DetectedIntent {
179
+ action: string;
180
+ target: string;
181
+ risk: RiskLevel;
182
+ }
183
+
184
+ /**
185
+ * Result of intent check
186
+ */
187
+ export interface IntentCheckResult {
188
+ violations: RuleMatch[];
189
+ warnings: RuleMatch[];
190
+ recommendations: RuleMatch[];
191
+ detectedIntents: DetectedIntent[];
192
+ }
193
+
194
+ // ==================== PATTERNS ====================
195
+
196
+ /**
197
+ * Error patterns analysis
198
+ */
199
+ export interface ErrorPatterns {
200
+ byType: Record<string, number>;
201
+ bySeverity: Record<Severity, number>;
202
+ byFile: Record<string, number>;
203
+ byTime: Record<string, number>;
204
+ total: number;
205
+ }
206
+
207
+ /**
208
+ * Correction patterns analysis
209
+ */
210
+ export interface CorrectionPatterns {
211
+ byCategory: Record<string, number>;
212
+ byFile: Record<string, number>;
213
+ total: number;
214
+ }
215
+
216
+ /**
217
+ * High-frequency pattern candidate for auto-rule
218
+ */
219
+ export interface HighFrequencyPattern {
220
+ pattern: string;
221
+ count: number;
222
+ type: 'error' | 'correction' | 'category';
223
+ suggestedRule?: AutoRule;
224
+ }
225
+
226
+ // ==================== TRENDS ====================
227
+
228
+ /**
229
+ * Weekly comparison data
230
+ */
231
+ export interface TrendData {
232
+ period: {
233
+ from: string;
234
+ to: string;
235
+ };
236
+ thisWeek: {
237
+ errors: number;
238
+ successes: number;
239
+ };
240
+ lastWeek: {
241
+ errors: number;
242
+ successes: number;
243
+ };
244
+ trends: {
245
+ errorChange: number;
246
+ successChange: number;
247
+ };
248
+ healthStatus: HealthStatus;
249
+ analysis: {
250
+ errorDirection: 'decreasing' | 'stable' | 'increasing';
251
+ successDirection: 'decreasing' | 'stable' | 'increasing';
252
+ };
253
+ }
254
+
255
+ /**
256
+ * Daily breakdown for charts
257
+ */
258
+ export interface DailyBreakdown {
259
+ date: string;
260
+ errors: number;
261
+ successes: number;
262
+ ratio: number;
263
+ }
264
+
265
+ // ==================== SUCCESS/FAILURE RATIO ====================
266
+
267
+ /**
268
+ * Success/failure ratio analysis
269
+ */
270
+ export interface BalanceRatio {
271
+ ratio: number;
272
+ status: 'EXCELLENT' | 'GOOD' | 'LEARNING' | 'NEEDS_ATTENTION' | 'NO_DATA';
273
+ message: string;
274
+ failures: number;
275
+ successes: number;
276
+ breakdown: {
277
+ errors: number;
278
+ corrections: number;
279
+ successPatterns: number;
280
+ };
281
+ }
282
+
283
+ // ==================== ADAPTIVE ENGINE ====================
284
+
285
+ /**
286
+ * Severity adjustment record
287
+ */
288
+ export interface SeverityAdjustment {
289
+ id: string;
290
+ from: Severity;
291
+ to: Severity;
292
+ reason: string;
293
+ }
294
+
295
+ /**
296
+ * Promotion/demotion record
297
+ */
298
+ export interface RulePromotion {
299
+ id: string;
300
+ pattern: string;
301
+ accuracy: number;
302
+ status: 'PROMOTED_TO_CORE' | 'DEMOTED_TO_LOW';
303
+ }
304
+
305
+ // ==================== SKILL INJECTION ====================
306
+
307
+ /**
308
+ * Skill candidate for generation
309
+ */
310
+ export interface SkillCandidate {
311
+ category: string;
312
+ count: number;
313
+ config: {
314
+ name: string;
315
+ description: string;
316
+ };
317
+ }
318
+
319
+ /**
320
+ * Generated skill result
321
+ */
322
+ export interface GeneratedSkill {
323
+ category: string;
324
+ name: string;
325
+ path: string;
326
+ lessonCount: number;
327
+ }
328
+
329
+ // ==================== RULE SHARING ====================
330
+
331
+ /**
332
+ * Exported rules in YAML format
333
+ */
334
+ export interface ExportedRules {
335
+ metadata: {
336
+ project: string;
337
+ exportedAt: string;
338
+ totalRules: number;
339
+ };
340
+ lessons: Lesson[];
341
+ autoRules: AutoRule[];
342
+ highFrequency: HighFrequencyPattern[];
343
+ }
@@ -0,0 +1,269 @@
1
+ /**
2
+ * Performance Benchmark Utility
3
+ *
4
+ * Provides tools for measuring and reporting performance:
5
+ * - Execution time measurement
6
+ * - Memory usage tracking
7
+ * - Performance reports
8
+ *
9
+ * Usage:
10
+ * import { benchmark, measure, report } from './benchmark.js';
11
+ *
12
+ * const result = await measure('operation-name', async () => {
13
+ * // code to measure
14
+ * });
15
+ *
16
+ * report();
17
+ */
18
+
19
+ import { fileURLToPath } from 'url';
20
+
21
+ const __filename = fileURLToPath(import.meta.url);
22
+
23
+ // ==================== STORAGE ====================
24
+
25
+ const metrics = new Map();
26
+ const thresholds = {
27
+ fast: 100, // < 100ms
28
+ normal: 500, // 100-500ms
29
+ slow: 1000, // 500-1000ms
30
+ // > 1000ms = very slow
31
+ };
32
+
33
+ // ==================== COLORS ====================
34
+
35
+ const c = {
36
+ reset: '\x1b[0m',
37
+ red: '\x1b[31m',
38
+ green: '\x1b[32m',
39
+ yellow: '\x1b[33m',
40
+ blue: '\x1b[34m',
41
+ cyan: '\x1b[36m',
42
+ gray: '\x1b[90m',
43
+ bold: '\x1b[1m'
44
+ };
45
+
46
+ // ==================== TIMING ====================
47
+
48
+ /**
49
+ * Measure execution time of a function
50
+ * @param {string} name - Operation name
51
+ * @param {Function} fn - Function to measure
52
+ * @returns {Promise<{result: any, duration: number, memory: object}>}
53
+ */
54
+ async function measure(name, fn) {
55
+ const startTime = performance.now();
56
+ const startMemory = process.memoryUsage();
57
+
58
+ let result;
59
+ let error = null;
60
+
61
+ try {
62
+ result = await fn();
63
+ } catch (e) {
64
+ error = e;
65
+ }
66
+
67
+ const endTime = performance.now();
68
+ const endMemory = process.memoryUsage();
69
+
70
+ const duration = Math.round((endTime - startTime) * 100) / 100;
71
+ const memoryDelta = {
72
+ heapUsed: endMemory.heapUsed - startMemory.heapUsed,
73
+ heapTotal: endMemory.heapTotal - startMemory.heapTotal,
74
+ external: endMemory.external - startMemory.external
75
+ };
76
+
77
+ // Store metric
78
+ const metric = {
79
+ name,
80
+ duration,
81
+ memory: memoryDelta,
82
+ timestamp: new Date().toISOString(),
83
+ success: !error
84
+ };
85
+
86
+ if (!metrics.has(name)) {
87
+ metrics.set(name, []);
88
+ }
89
+ metrics.get(name).push(metric);
90
+
91
+ if (error) {
92
+ throw error;
93
+ }
94
+
95
+ return { result, duration, memory: memoryDelta };
96
+ }
97
+
98
+ /**
99
+ * Simple timing wrapper
100
+ * @param {string} label - Operation label
101
+ */
102
+ function time(label) {
103
+ const start = performance.now();
104
+ return {
105
+ end: () => {
106
+ const duration = performance.now() - start;
107
+ console.log(`${c.gray}⏱️ ${label}: ${duration.toFixed(2)}ms${c.reset}`);
108
+ return duration;
109
+ }
110
+ };
111
+ }
112
+
113
+ /**
114
+ * Benchmark multiple iterations
115
+ * @param {string} name - Benchmark name
116
+ * @param {Function} fn - Function to benchmark
117
+ * @param {number} iterations - Number of iterations
118
+ */
119
+ async function benchmark(name, fn, iterations = 10) {
120
+ const results = [];
121
+
122
+ for (let i = 0; i < iterations; i++) {
123
+ const start = performance.now();
124
+ await fn();
125
+ results.push(performance.now() - start);
126
+ }
127
+
128
+ const avg = results.reduce((a, b) => a + b, 0) / results.length;
129
+ const min = Math.min(...results);
130
+ const max = Math.max(...results);
131
+ const p95 = results.sort((a, b) => a - b)[Math.floor(results.length * 0.95)];
132
+
133
+ return {
134
+ name,
135
+ iterations,
136
+ avg: Math.round(avg * 100) / 100,
137
+ min: Math.round(min * 100) / 100,
138
+ max: Math.round(max * 100) / 100,
139
+ p95: Math.round(p95 * 100) / 100
140
+ };
141
+ }
142
+
143
+ // ==================== MEMORY ====================
144
+
145
+ /**
146
+ * Get current memory usage
147
+ */
148
+ function getMemoryUsage() {
149
+ const usage = process.memoryUsage();
150
+ return {
151
+ heapUsed: formatBytes(usage.heapUsed),
152
+ heapTotal: formatBytes(usage.heapTotal),
153
+ external: formatBytes(usage.external),
154
+ rss: formatBytes(usage.rss)
155
+ };
156
+ }
157
+
158
+ /**
159
+ * Format bytes to human readable
160
+ */
161
+ function formatBytes(bytes) {
162
+ if (bytes < 1024) return `${bytes}B`;
163
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;
164
+ return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
165
+ }
166
+
167
+ // ==================== REPORTING ====================
168
+
169
+ /**
170
+ * Get performance status color
171
+ */
172
+ function getStatusColor(duration) {
173
+ if (duration < thresholds.fast) return c.green;
174
+ if (duration < thresholds.normal) return c.blue;
175
+ if (duration < thresholds.slow) return c.yellow;
176
+ return c.red;
177
+ }
178
+
179
+ /**
180
+ * Get performance status label
181
+ */
182
+ function getStatusLabel(duration) {
183
+ if (duration < thresholds.fast) return '🚀 FAST';
184
+ if (duration < thresholds.normal) return '✓ NORMAL';
185
+ if (duration < thresholds.slow) return '⚠️ SLOW';
186
+ return '❌ VERY SLOW';
187
+ }
188
+
189
+ /**
190
+ * Print performance report
191
+ */
192
+ function report() {
193
+ console.log(`\n${c.cyan}╔════════════════════════════════════════╗${c.reset}`);
194
+ console.log(`${c.cyan}║${c.reset} 📊 Performance Report ${c.cyan}║${c.reset}`);
195
+ console.log(`${c.cyan}╚════════════════════════════════════════╝${c.reset}\n`);
196
+
197
+ if (metrics.size === 0) {
198
+ console.log(`${c.gray}No metrics collected yet.${c.reset}`);
199
+ return;
200
+ }
201
+
202
+ for (const [name, data] of metrics) {
203
+ const durations = data.map(d => d.duration);
204
+ const avg = durations.reduce((a, b) => a + b, 0) / durations.length;
205
+ const color = getStatusColor(avg);
206
+ const status = getStatusLabel(avg);
207
+
208
+ console.log(`${c.bold}${name}${c.reset}`);
209
+ console.log(` Runs: ${data.length}`);
210
+ console.log(` Avg: ${color}${avg.toFixed(2)}ms${c.reset} ${status}`);
211
+ console.log(` Min: ${Math.min(...durations).toFixed(2)}ms`);
212
+ console.log(` Max: ${Math.max(...durations).toFixed(2)}ms`);
213
+ console.log('');
214
+ }
215
+
216
+ // Memory summary
217
+ const mem = getMemoryUsage();
218
+ console.log(`${c.bold}Memory Usage${c.reset}`);
219
+ console.log(` Heap: ${mem.heapUsed} / ${mem.heapTotal}`);
220
+ console.log(` RSS: ${mem.rss}`);
221
+ }
222
+
223
+ /**
224
+ * Get metrics as JSON
225
+ */
226
+ function getMetrics() {
227
+ const result = {};
228
+ for (const [name, data] of metrics) {
229
+ const durations = data.map(d => d.duration);
230
+ result[name] = {
231
+ runs: data.length,
232
+ avg: durations.reduce((a, b) => a + b, 0) / durations.length,
233
+ min: Math.min(...durations),
234
+ max: Math.max(...durations),
235
+ success: data.filter(d => d.success).length
236
+ };
237
+ }
238
+ return result;
239
+ }
240
+
241
+ /**
242
+ * Clear all metrics
243
+ */
244
+ function clear() {
245
+ metrics.clear();
246
+ }
247
+
248
+ // ==================== EXPORTS ====================
249
+
250
+ export {
251
+ measure,
252
+ time,
253
+ benchmark,
254
+ getMemoryUsage,
255
+ report,
256
+ getMetrics,
257
+ clear,
258
+ thresholds
259
+ };
260
+
261
+ export default {
262
+ measure,
263
+ time,
264
+ benchmark,
265
+ getMemoryUsage,
266
+ report,
267
+ getMetrics,
268
+ clear
269
+ };