vibecodingmachine-core 2026.2.20-438 → 2026.2.26-1642
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/README.md +240 -0
- package/package.json +10 -2
- package/src/agents/Agent.js +300 -0
- package/src/agents/AgentAdditionService.js +311 -0
- package/src/agents/AgentCheckService.js +690 -0
- package/src/agents/AgentInstallationService.js +140 -0
- package/src/agents/AgentSetupService.js +467 -0
- package/src/agents/AgentStatus.js +183 -0
- package/src/agents/AgentVerificationService.js +634 -0
- package/src/agents/ConfigurationSchemaValidator.js +543 -0
- package/src/agents/EnvironmentConfigurationManager.js +602 -0
- package/src/agents/InstallationErrorHandler.js +372 -0
- package/src/agents/InstallationLog.js +363 -0
- package/src/agents/InstallationMethod.js +510 -0
- package/src/agents/InstallationOrchestrator.js +352 -0
- package/src/agents/InstallationProgressReporter.js +372 -0
- package/src/agents/InstallationRetryManager.js +322 -0
- package/src/agents/InstallationType.js +254 -0
- package/src/agents/OperationTypes.js +310 -0
- package/src/agents/PerformanceMetricsCollector.js +493 -0
- package/src/agents/SecurityValidationService.js +534 -0
- package/src/agents/VerificationTest.js +354 -0
- package/src/agents/VerificationType.js +226 -0
- package/src/agents/WindowsPermissionHandler.js +518 -0
- package/src/agents/config/AgentConfigManager.js +393 -0
- package/src/agents/config/AgentDefaultsRegistry.js +373 -0
- package/src/agents/config/ConfigValidator.js +281 -0
- package/src/agents/discovery/AgentDiscoveryService.js +707 -0
- package/src/agents/logging/AgentLogger.js +511 -0
- package/src/agents/status/AgentStatusManager.js +481 -0
- package/src/agents/storage/FileManager.js +454 -0
- package/src/agents/verification/AgentCommunicationTester.js +474 -0
- package/src/agents/verification/BaseVerifier.js +430 -0
- package/src/agents/verification/CommandVerifier.js +480 -0
- package/src/agents/verification/FileOperationVerifier.js +453 -0
- package/src/agents/verification/ResultAnalyzer.js +707 -0
- package/src/agents/verification/TestRequirementManager.js +495 -0
- package/src/agents/verification/VerificationRunner.js +433 -0
- package/src/agents/windows/BaseWindowsInstaller.js +441 -0
- package/src/agents/windows/ChocolateyInstaller.js +509 -0
- package/src/agents/windows/DirectInstaller.js +443 -0
- package/src/agents/windows/InstallerFactory.js +391 -0
- package/src/agents/windows/NpmInstaller.js +505 -0
- package/src/agents/windows/PowerShellInstaller.js +458 -0
- package/src/agents/windows/WinGetInstaller.js +390 -0
- package/src/analysis/analysis-reporter.js +132 -0
- package/src/analysis/boundary-detector.js +712 -0
- package/src/analysis/categorizer.js +340 -0
- package/src/analysis/codebase-scanner.js +384 -0
- package/src/analysis/line-counter.js +513 -0
- package/src/analysis/priority-calculator.js +679 -0
- package/src/analysis/report/analysis-report.js +250 -0
- package/src/analysis/report/package-analyzer.js +278 -0
- package/src/analysis/report/recommendation-generator.js +382 -0
- package/src/analysis/report/statistics-generator.js +515 -0
- package/src/analysis/reports/analysis-report-model.js +101 -0
- package/src/analysis/reports/recommendation-generator.js +283 -0
- package/src/analysis/reports/report-generators.js +191 -0
- package/src/analysis/reports/statistics-calculator.js +231 -0
- package/src/analysis/reports/trend-analyzer.js +219 -0
- package/src/analysis/strategy-generator.js +814 -0
- package/src/auto-mode/AutoModeBusinessLogic.js +836 -0
- package/src/config/refactoring-config.js +307 -0
- package/src/health-tracking/json-storage.js +38 -2
- package/src/ide-integration/applescript-manager-core.js +233 -0
- package/src/ide-integration/applescript-manager.cjs +357 -28
- package/src/ide-integration/applescript-manager.js +89 -3599
- package/src/ide-integration/cdp-manager.js +306 -0
- package/src/ide-integration/claude-code-cli-manager.cjs +1 -1
- package/src/ide-integration/continuation-handler.js +337 -0
- package/src/ide-integration/ide-status-checker.js +292 -0
- package/src/ide-integration/macos-ide-manager.js +627 -0
- package/src/ide-integration/macos-text-sender.js +528 -0
- package/src/ide-integration/response-reader.js +548 -0
- package/src/ide-integration/windows-automation-manager.js +121 -0
- package/src/ide-integration/windows-ide-manager.js +373 -0
- package/src/index.cjs +25 -3
- package/src/index.js +15 -1
- package/src/llm/direct-llm-manager.cjs +90 -2
- package/src/models/compliance-report.js +538 -0
- package/src/models/file-analysis.js +681 -0
- package/src/models/refactoring-plan.js +770 -0
- package/src/monitoring/alert-system.js +834 -0
- package/src/monitoring/compliance-progress-tracker.js +437 -0
- package/src/monitoring/continuous-scan-notifications.js +661 -0
- package/src/monitoring/continuous-scanner.js +279 -0
- package/src/monitoring/file-monitor/file-analyzer.js +262 -0
- package/src/monitoring/file-monitor/file-monitor.js +237 -0
- package/src/monitoring/file-monitor/watcher.js +194 -0
- package/src/monitoring/file-monitor.js +17 -0
- package/src/monitoring/notification-manager.js +437 -0
- package/src/monitoring/scanner-core.js +368 -0
- package/src/monitoring/scanner-events.js +214 -0
- package/src/monitoring/violation-notification-system.js +515 -0
- package/src/refactoring/boundaries/cohesion-analyzer.js +316 -0
- package/src/refactoring/boundaries/extraction-result.js +285 -0
- package/src/refactoring/boundaries/extraction-strategies.js +392 -0
- package/src/refactoring/boundaries/module-boundary.js +209 -0
- package/src/refactoring/boundary/boundary-detector.js +741 -0
- package/src/refactoring/boundary/boundary-types.js +405 -0
- package/src/refactoring/boundary/extraction-strategies.js +554 -0
- package/src/refactoring/boundary-extraction-result.js +77 -0
- package/src/refactoring/boundary-extraction-strategies.js +330 -0
- package/src/refactoring/boundary-extractor.js +384 -0
- package/src/refactoring/boundary-types.js +46 -0
- package/src/refactoring/circular/circular-dependency.js +88 -0
- package/src/refactoring/circular/cycle-detection.js +147 -0
- package/src/refactoring/circular/dependency-node.js +82 -0
- package/src/refactoring/circular/dependency-result.js +107 -0
- package/src/refactoring/circular/dependency-types.js +58 -0
- package/src/refactoring/circular/graph-builder.js +213 -0
- package/src/refactoring/circular/resolution-strategy.js +72 -0
- package/src/refactoring/circular/strategy-generator.js +229 -0
- package/src/refactoring/circular-dependency-resolver-original.js +809 -0
- package/src/refactoring/circular-dependency-resolver.js +200 -0
- package/src/refactoring/code-mover.js +761 -0
- package/src/refactoring/file-splitter.js +696 -0
- package/src/refactoring/functionality-validator.js +816 -0
- package/src/refactoring/import-manager.js +774 -0
- package/src/refactoring/module-boundary.js +107 -0
- package/src/refactoring/refactoring-executor.js +672 -0
- package/src/refactoring/refactoring-rollback.js +614 -0
- package/src/refactoring/test-validator.js +631 -0
- package/src/requirement-management/default-requirement-manager.js +321 -0
- package/src/requirement-management/requirement-file-parser.js +159 -0
- package/src/requirement-management/requirement-sequencer.js +221 -0
- package/src/rui/commands/AgentCommandParser.js +600 -0
- package/src/rui/commands/AgentCommands.js +487 -0
- package/src/rui/commands/AgentResponseFormatter.js +832 -0
- package/src/scripts/verify-full-compliance.js +269 -0
- package/src/sync/sync-engine-core.js +1 -0
- package/src/sync/sync-engine-remote-handlers.js +135 -0
- package/src/task-generation/automated-task-generator.js +351 -0
- package/src/task-generation/prioritizer.js +287 -0
- package/src/task-generation/task-list-updater.js +215 -0
- package/src/task-generation/task-management-integration.js +480 -0
- package/src/task-generation/task-manager-integration.js +270 -0
- package/src/task-generation/violation-task-generator.js +474 -0
- package/src/task-management/continuous-scan-integration.js +342 -0
- package/src/timeout-management/index.js +12 -3
- package/src/timeout-management/response-time-tracker.js +167 -0
- package/src/timeout-management/timeout-calculator.js +159 -0
- package/src/timeout-management/timeout-config-manager.js +172 -0
- package/src/utils/ast-analyzer.js +417 -0
- package/src/utils/current-requirement-manager.js +276 -0
- package/src/utils/current-requirement-operations.js +472 -0
- package/src/utils/dependency-mapper.js +456 -0
- package/src/utils/download-with-progress.js +4 -2
- package/src/utils/electron-update-checker.js +4 -1
- package/src/utils/file-size-analyzer.js +272 -0
- package/src/utils/import-updater.js +280 -0
- package/src/utils/refactoring-tools.js +512 -0
- package/src/utils/report-generator.js +569 -0
- package/src/utils/reports/report-analysis.js +218 -0
- package/src/utils/reports/report-types.js +55 -0
- package/src/utils/reports/summary-generators.js +102 -0
- package/src/utils/requirement-file-management.js +157 -0
- package/src/utils/requirement-helpers/requirement-file-ops.js +392 -0
- package/src/utils/requirement-helpers/requirement-mover.js +414 -0
- package/src/utils/requirement-helpers/requirement-parser.js +326 -0
- package/src/utils/requirement-helpers/requirement-status.js +320 -0
- package/src/utils/requirement-helpers-new.js +55 -0
- package/src/utils/requirement-helpers-refactored.js +367 -0
- package/src/utils/requirement-helpers.js +291 -1191
- package/src/utils/requirement-movement-operations.js +450 -0
- package/src/utils/requirement-movement.js +312 -0
- package/src/utils/requirement-parsing-helpers.js +56 -0
- package/src/utils/requirement-statistics.js +200 -0
- package/src/utils/requirement-text-utils.js +58 -0
- package/src/utils/rollback/rollback-handlers.js +125 -0
- package/src/utils/rollback/rollback-operation.js +63 -0
- package/src/utils/rollback/rollback-recorder.js +166 -0
- package/src/utils/rollback/rollback-state-manager.js +175 -0
- package/src/utils/rollback/rollback-types.js +33 -0
- package/src/utils/rollback/rollback-utils.js +110 -0
- package/src/utils/rollback-manager-original.js +569 -0
- package/src/utils/rollback-manager.js +202 -0
- package/src/utils/smoke-test-cli.js +362 -0
- package/src/utils/smoke-test-gui.js +351 -0
- package/src/utils/smoke-test-orchestrator.js +321 -0
- package/src/utils/smoke-test-runner.js +60 -0
- package/src/utils/smoke-test-web.js +347 -0
- package/src/utils/specification-helpers.js +39 -13
- package/src/utils/specification-migration.js +97 -0
- package/src/utils/test-runner.js +579 -0
- package/src/utils/validation-framework.js +518 -0
- package/src/validation/compliance-analyzer.js +197 -0
- package/src/validation/compliance-report-generator.js +343 -0
- package/src/validation/compliance-reporter.js +711 -0
- package/src/validation/compliance-rules.js +127 -0
- package/src/validation/constitution-validator-new.js +196 -0
- package/src/validation/constitution-validator.js +17 -0
- package/src/validation/file-validators.js +170 -0
- package/src/validation/line-limit/file-analyzer.js +201 -0
- package/src/validation/line-limit/line-limit-validator.js +208 -0
- package/src/validation/line-limit/validation-result.js +144 -0
- package/src/validation/line-limit-core.js +225 -0
- package/src/validation/line-limit-reporter.js +134 -0
- package/src/validation/line-limit-result.js +125 -0
- package/src/validation/line-limit-validator.js +41 -0
- package/src/validation/metrics-calculator.js +660 -0
- package/src/sync/sync-engine-backup.js +0 -559
|
@@ -0,0 +1,515 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Violation Notification System
|
|
3
|
+
*
|
|
4
|
+
* Sends notifications when new file size violations are detected
|
|
5
|
+
* or when compliance thresholds are crossed.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const EventEmitter = require('events');
|
|
9
|
+
const fs = require('fs').promises;
|
|
10
|
+
const path = require('path');
|
|
11
|
+
|
|
12
|
+
class ViolationNotificationSystem extends EventEmitter {
|
|
13
|
+
constructor(options = {}) {
|
|
14
|
+
super();
|
|
15
|
+
this.enabled = options.enabled !== false;
|
|
16
|
+
this.thresholds = {
|
|
17
|
+
violationCount: options.violationCountThreshold || 5,
|
|
18
|
+
complianceDrop: options.complianceDropThreshold || 5,
|
|
19
|
+
criticalFile: options.criticalFileThreshold || 2000,
|
|
20
|
+
...options.thresholds
|
|
21
|
+
};
|
|
22
|
+
this.channels = this.setupNotificationChannels(options.channels || {});
|
|
23
|
+
this.cooldownPeriod = options.cooldownPeriod || 300000; // 5 minutes
|
|
24
|
+
this.lastNotifications = new Map();
|
|
25
|
+
this.notificationHistory = [];
|
|
26
|
+
this.maxHistorySize = options.maxHistorySize || 100;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Setup notification channels
|
|
31
|
+
*/
|
|
32
|
+
setupNotificationChannels(channels) {
|
|
33
|
+
return {
|
|
34
|
+
console: channels.console !== false,
|
|
35
|
+
file: channels.file !== false,
|
|
36
|
+
desktop: channels.desktop || false,
|
|
37
|
+
email: channels.email || null,
|
|
38
|
+
webhook: channels.webhook || null,
|
|
39
|
+
slack: channels.slack || null,
|
|
40
|
+
...channels
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Process scan results and send notifications if needed
|
|
46
|
+
*/
|
|
47
|
+
async processScanResults(scanResults, previousResults = null) {
|
|
48
|
+
if (!this.enabled) return;
|
|
49
|
+
|
|
50
|
+
const notifications = [];
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
// Check for new violations
|
|
54
|
+
const newViolations = this.findNewViolations(scanResults.violations, previousResults?.violations || []);
|
|
55
|
+
if (newViolations.length > 0) {
|
|
56
|
+
notifications.push(await this.createNewViolationsNotification(newViolations, scanResults));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Check violation count threshold
|
|
60
|
+
if (scanResults.violations.length >= this.thresholds.violationCount) {
|
|
61
|
+
notifications.push(await this.createViolationCountNotification(scanResults));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Check for critical files
|
|
65
|
+
const criticalViolations = scanResults.violations.filter(v => v.lineCount >= this.thresholds.criticalFile);
|
|
66
|
+
if (criticalViolations.length > 0) {
|
|
67
|
+
notifications.push(await this.createCriticalFilesNotification(criticalViolations));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Check compliance drop
|
|
71
|
+
if (previousResults) {
|
|
72
|
+
const complianceDrop = (previousResults.complianceRate - scanResults.complianceRate);
|
|
73
|
+
if (complianceDrop >= this.thresholds.complianceDrop) {
|
|
74
|
+
notifications.push(await this.createComplianceDropNotification(complianceDrop, scanResults));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Check for milestone events
|
|
79
|
+
notifications.push(...await this.checkMilestones(scanResults));
|
|
80
|
+
|
|
81
|
+
// Send notifications
|
|
82
|
+
for (const notification of notifications) {
|
|
83
|
+
await this.sendNotification(notification);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
} catch (error) {
|
|
87
|
+
console.error('Error processing scan results for notifications:', error);
|
|
88
|
+
this.emit('error', error);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Find new violations compared to previous scan
|
|
94
|
+
*/
|
|
95
|
+
findNewViolations(currentViolations, previousViolations) {
|
|
96
|
+
const previousFiles = new Set(previousViolations.map(v => v.filePath));
|
|
97
|
+
return currentViolations.filter(v => !previousFiles.has(v.filePath));
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Create notification for new violations
|
|
102
|
+
*/
|
|
103
|
+
async createNewViolationsNotification(newViolations, scanResults) {
|
|
104
|
+
const notification = {
|
|
105
|
+
type: 'new_violations',
|
|
106
|
+
title: 'New File Size Violations Detected',
|
|
107
|
+
message: `${newViolations.length} new file(s) exceed the 555-line limit`,
|
|
108
|
+
severity: newViolations.some(v => v.lineCount >= this.thresholds.criticalFile) ? 'critical' : 'warning',
|
|
109
|
+
data: {
|
|
110
|
+
violations: newViolations,
|
|
111
|
+
totalViolations: scanResults.violations.length,
|
|
112
|
+
complianceRate: scanResults.complianceRate
|
|
113
|
+
},
|
|
114
|
+
actions: [
|
|
115
|
+
{ label: 'View Details', action: 'view_violations' },
|
|
116
|
+
{ label: 'Generate Tasks', action: 'generate_tasks' }
|
|
117
|
+
],
|
|
118
|
+
timestamp: new Date().toISOString()
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
return notification;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Create notification for violation count threshold
|
|
126
|
+
*/
|
|
127
|
+
async createViolationCountNotification(scanResults) {
|
|
128
|
+
const notification = {
|
|
129
|
+
type: 'violation_threshold',
|
|
130
|
+
title: 'High Number of Violations',
|
|
131
|
+
message: `${scanResults.violations.length} files exceed the 555-line limit (threshold: ${this.thresholds.violationCount})`,
|
|
132
|
+
severity: scanResults.violations.length >= this.thresholds.violationCount * 2 ? 'critical' : 'warning',
|
|
133
|
+
data: {
|
|
134
|
+
violationCount: scanResults.violations.length,
|
|
135
|
+
threshold: this.thresholds.violationCount,
|
|
136
|
+
complianceRate: scanResults.complianceRate
|
|
137
|
+
},
|
|
138
|
+
actions: [
|
|
139
|
+
{ label: 'Run Analysis', action: 'run_analysis' },
|
|
140
|
+
{ label: 'View Dashboard', action: 'view_dashboard' }
|
|
141
|
+
],
|
|
142
|
+
timestamp: new Date().toISOString()
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
return notification;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Create notification for critical files
|
|
150
|
+
*/
|
|
151
|
+
async createCriticalFilesNotification(criticalViolations) {
|
|
152
|
+
const notification = {
|
|
153
|
+
type: 'critical_files',
|
|
154
|
+
title: 'Critical File Size Violations',
|
|
155
|
+
message: `${criticalViolations.length} file(s) exceed ${this.thresholds.criticalFile} lines`,
|
|
156
|
+
severity: 'critical',
|
|
157
|
+
data: {
|
|
158
|
+
criticalViolations,
|
|
159
|
+
threshold: this.thresholds.criticalFile
|
|
160
|
+
},
|
|
161
|
+
actions: [
|
|
162
|
+
{ label: 'Prioritize for Refactoring', action: 'prioritize_refactoring' },
|
|
163
|
+
{ label: 'View Critical Files', action: 'view_critical' }
|
|
164
|
+
],
|
|
165
|
+
timestamp: new Date().toISOString()
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
return notification;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Create notification for compliance drop
|
|
173
|
+
*/
|
|
174
|
+
async createComplianceDropNotification(drop, scanResults) {
|
|
175
|
+
const notification = {
|
|
176
|
+
type: 'compliance_drop',
|
|
177
|
+
title: 'Compliance Rate Drop',
|
|
178
|
+
message: `Compliance rate dropped by ${drop.toFixed(1)}% to ${scanResults.complianceRate.toFixed(1)}%`,
|
|
179
|
+
severity: drop >= 10 ? 'critical' : 'warning',
|
|
180
|
+
data: {
|
|
181
|
+
dropAmount: drop,
|
|
182
|
+
currentRate: scanResults.complianceRate,
|
|
183
|
+
previousRate: scanResults.complianceRate + drop
|
|
184
|
+
},
|
|
185
|
+
actions: [
|
|
186
|
+
{ label: 'Investigate Changes', action: 'investigate_changes' },
|
|
187
|
+
{ label: 'View History', action: 'view_history' }
|
|
188
|
+
],
|
|
189
|
+
timestamp: new Date().toISOString()
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
return notification;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Check for milestone events
|
|
197
|
+
*/
|
|
198
|
+
async checkMilestones(scanResults) {
|
|
199
|
+
const notifications = [];
|
|
200
|
+
|
|
201
|
+
// Compliance milestones
|
|
202
|
+
if (scanResults.complianceRate >= 95) {
|
|
203
|
+
notifications.push({
|
|
204
|
+
type: 'milestone',
|
|
205
|
+
title: '🎉 Compliance Milestone Achieved!',
|
|
206
|
+
message: `${scanResults.complianceRate.toFixed(1)}% compliance rate achieved!`,
|
|
207
|
+
severity: 'success',
|
|
208
|
+
data: { complianceRate: scanResults.complianceRate },
|
|
209
|
+
timestamp: new Date().toISOString()
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Zero violations milestone
|
|
214
|
+
if (scanResults.violations.length === 0) {
|
|
215
|
+
notifications.push({
|
|
216
|
+
type: 'milestone',
|
|
217
|
+
title: '🏆 Perfect Compliance Achieved!',
|
|
218
|
+
message: 'All files are compliant with the 555-line limit!',
|
|
219
|
+
severity: 'success',
|
|
220
|
+
data: { totalFiles: scanResults.totalFiles },
|
|
221
|
+
timestamp: new Date().toISOString()
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
return notifications;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Send notification through all configured channels
|
|
230
|
+
*/
|
|
231
|
+
async sendNotification(notification) {
|
|
232
|
+
// Check cooldown period
|
|
233
|
+
const cooldownKey = `${notification.type}_${notification.title}`;
|
|
234
|
+
if (this.isInCooldown(cooldownKey)) {
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
try {
|
|
239
|
+
// Console notification
|
|
240
|
+
if (this.channels.console) {
|
|
241
|
+
this.sendConsoleNotification(notification);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// File notification
|
|
245
|
+
if (this.channels.file) {
|
|
246
|
+
await this.sendFileNotification(notification);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Desktop notification
|
|
250
|
+
if (this.channels.desktop) {
|
|
251
|
+
await this.sendDesktopNotification(notification);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Email notification
|
|
255
|
+
if (this.channels.email) {
|
|
256
|
+
await this.sendEmailNotification(notification);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Webhook notification
|
|
260
|
+
if (this.channels.webhook) {
|
|
261
|
+
await this.sendWebhookNotification(notification);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Slack notification
|
|
265
|
+
if (this.channels.slack) {
|
|
266
|
+
await this.sendSlackNotification(notification);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Update last notification time
|
|
270
|
+
this.lastNotifications.set(cooldownKey, Date.now());
|
|
271
|
+
|
|
272
|
+
// Add to history
|
|
273
|
+
this.addToHistory(notification);
|
|
274
|
+
|
|
275
|
+
// Emit event
|
|
276
|
+
this.emit('notification_sent', notification);
|
|
277
|
+
|
|
278
|
+
} catch (error) {
|
|
279
|
+
console.error('Error sending notification:', error);
|
|
280
|
+
this.emit('notification_error', { notification, error });
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Send console notification
|
|
286
|
+
*/
|
|
287
|
+
sendConsoleNotification(notification) {
|
|
288
|
+
const colors = {
|
|
289
|
+
critical: '\x1b[31m', // red
|
|
290
|
+
warning: '\x1b[33m', // yellow
|
|
291
|
+
success: '\x1b[32m', // green
|
|
292
|
+
info: '\x1b[36m' // cyan
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
const reset = '\x1b[0m';
|
|
296
|
+
const color = colors[notification.severity] || colors.info;
|
|
297
|
+
|
|
298
|
+
console.log(`${color}🔔 ${notification.title}${reset}`);
|
|
299
|
+
console.log(`${notification.message}`);
|
|
300
|
+
|
|
301
|
+
if (notification.data && Object.keys(notification.data).length > 0) {
|
|
302
|
+
console.log('Data:', JSON.stringify(notification.data, null, 2));
|
|
303
|
+
}
|
|
304
|
+
console.log('---');
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Send file notification
|
|
309
|
+
*/
|
|
310
|
+
async sendFileNotification(notification) {
|
|
311
|
+
const logFile = path.join(process.cwd(), '.vibecodingmachine', 'notifications.log');
|
|
312
|
+
|
|
313
|
+
try {
|
|
314
|
+
await fs.mkdir(path.dirname(logFile), { recursive: true });
|
|
315
|
+
const logEntry = `${notification.timestamp} [${notification.severity.toUpperCase()}] ${notification.title}: ${notification.message}\n`;
|
|
316
|
+
await fs.appendFile(logFile, logEntry);
|
|
317
|
+
} catch (error) {
|
|
318
|
+
console.error('Failed to write notification to file:', error);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Send desktop notification
|
|
324
|
+
*/
|
|
325
|
+
async sendDesktopNotification(notification) {
|
|
326
|
+
try {
|
|
327
|
+
const { Notification } = require('electron');
|
|
328
|
+
|
|
329
|
+
if (Notification.isSupported()) {
|
|
330
|
+
const electronNotification = new Notification({
|
|
331
|
+
title: notification.title,
|
|
332
|
+
body: notification.message,
|
|
333
|
+
urgency: notification.severity === 'critical' ? 'critical' : 'normal'
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
electronNotification.on('click', () => {
|
|
337
|
+
this.emit('notification_clicked', notification);
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
electronNotification.show();
|
|
341
|
+
}
|
|
342
|
+
} catch (error) {
|
|
343
|
+
// Desktop notifications not available, silently fail
|
|
344
|
+
console.debug('Desktop notifications not available:', error.message);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Send email notification
|
|
350
|
+
*/
|
|
351
|
+
async sendEmailNotification(notification) {
|
|
352
|
+
if (!this.channels.email) return;
|
|
353
|
+
|
|
354
|
+
// Email implementation would go here
|
|
355
|
+
// This is a placeholder for actual email sending logic
|
|
356
|
+
console.log('Email notification would be sent:', notification.title);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Send webhook notification
|
|
361
|
+
*/
|
|
362
|
+
async sendWebhookNotification(notification) {
|
|
363
|
+
if (!this.channels.webhook) return;
|
|
364
|
+
|
|
365
|
+
try {
|
|
366
|
+
const fetch = require('node-fetch');
|
|
367
|
+
|
|
368
|
+
await fetch(this.channels.webhook, {
|
|
369
|
+
method: 'POST',
|
|
370
|
+
headers: {
|
|
371
|
+
'Content-Type': 'application/json'
|
|
372
|
+
},
|
|
373
|
+
body: JSON.stringify(notification)
|
|
374
|
+
});
|
|
375
|
+
} catch (error) {
|
|
376
|
+
console.error('Failed to send webhook notification:', error);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Send Slack notification
|
|
382
|
+
*/
|
|
383
|
+
async sendSlackNotification(notification) {
|
|
384
|
+
if (!this.channels.slack) return;
|
|
385
|
+
|
|
386
|
+
try {
|
|
387
|
+
const fetch = require('node-fetch');
|
|
388
|
+
|
|
389
|
+
const slackMessage = {
|
|
390
|
+
text: notification.title,
|
|
391
|
+
attachments: [{
|
|
392
|
+
color: this.getSlackColor(notification.severity),
|
|
393
|
+
text: notification.message,
|
|
394
|
+
fields: Object.entries(notification.data || {}).map(([key, value]) => ({
|
|
395
|
+
title: key,
|
|
396
|
+
value: typeof value === 'object' ? JSON.stringify(value) : String(value),
|
|
397
|
+
short: true
|
|
398
|
+
})),
|
|
399
|
+
ts: Math.floor(new Date(notification.timestamp).getTime() / 1000)
|
|
400
|
+
}]
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
await fetch(this.channels.slack, {
|
|
404
|
+
method: 'POST',
|
|
405
|
+
headers: {
|
|
406
|
+
'Content-Type': 'application/json'
|
|
407
|
+
},
|
|
408
|
+
body: JSON.stringify(slackMessage)
|
|
409
|
+
});
|
|
410
|
+
} catch (error) {
|
|
411
|
+
console.error('Failed to send Slack notification:', error);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Get Slack color based on severity
|
|
417
|
+
*/
|
|
418
|
+
getSlackColor(severity) {
|
|
419
|
+
switch (severity) {
|
|
420
|
+
case 'critical': return 'danger';
|
|
421
|
+
case 'warning': return 'warning';
|
|
422
|
+
case 'success': return 'good';
|
|
423
|
+
default: return '#439FE0';
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Check if notification type is in cooldown period
|
|
429
|
+
*/
|
|
430
|
+
isInCooldown(key) {
|
|
431
|
+
const lastTime = this.lastNotifications.get(key);
|
|
432
|
+
if (!lastTime) return false;
|
|
433
|
+
|
|
434
|
+
return (Date.now() - lastTime) < this.cooldownPeriod;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* Add notification to history
|
|
439
|
+
*/
|
|
440
|
+
addToHistory(notification) {
|
|
441
|
+
this.notificationHistory.unshift(notification);
|
|
442
|
+
|
|
443
|
+
// Trim history if it exceeds max size
|
|
444
|
+
if (this.notificationHistory.length > this.maxHistorySize) {
|
|
445
|
+
this.notificationHistory = this.notificationHistory.slice(0, this.maxHistorySize);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* Get notification history
|
|
451
|
+
*/
|
|
452
|
+
getNotificationHistory(limit = 50) {
|
|
453
|
+
return this.notificationHistory.slice(0, limit);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* Get notification statistics
|
|
458
|
+
*/
|
|
459
|
+
getNotificationStats() {
|
|
460
|
+
const stats = {
|
|
461
|
+
total: this.notificationHistory.length,
|
|
462
|
+
byType: {},
|
|
463
|
+
bySeverity: {},
|
|
464
|
+
recent24h: 0
|
|
465
|
+
};
|
|
466
|
+
|
|
467
|
+
const oneDayAgo = Date.now() - (24 * 60 * 60 * 1000);
|
|
468
|
+
|
|
469
|
+
this.notificationHistory.forEach(notification => {
|
|
470
|
+
// Count by type
|
|
471
|
+
stats.byType[notification.type] = (stats.byType[notification.type] || 0) + 1;
|
|
472
|
+
|
|
473
|
+
// Count by severity
|
|
474
|
+
stats.bySeverity[notification.severity] = (stats.bySeverity[notification.severity] || 0) + 1;
|
|
475
|
+
|
|
476
|
+
// Count recent notifications
|
|
477
|
+
if (new Date(notification.timestamp).getTime() > oneDayAgo) {
|
|
478
|
+
stats.recent24h++;
|
|
479
|
+
}
|
|
480
|
+
});
|
|
481
|
+
|
|
482
|
+
return stats;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
/**
|
|
486
|
+
* Clear notification history
|
|
487
|
+
*/
|
|
488
|
+
clearHistory() {
|
|
489
|
+
this.notificationHistory = [];
|
|
490
|
+
this.lastNotifications.clear();
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
/**
|
|
494
|
+
* Enable/disable notifications
|
|
495
|
+
*/
|
|
496
|
+
setEnabled(enabled) {
|
|
497
|
+
this.enabled = enabled;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* Update thresholds
|
|
502
|
+
*/
|
|
503
|
+
updateThresholds(newThresholds) {
|
|
504
|
+
this.thresholds = { ...this.thresholds, ...newThresholds };
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* Update notification channels
|
|
509
|
+
*/
|
|
510
|
+
updateChannels(newChannels) {
|
|
511
|
+
this.channels = { ...this.channels, ...newChannels };
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
module.exports = ViolationNotificationSystem;
|