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.
Files changed (202) hide show
  1. package/README.md +240 -0
  2. package/package.json +10 -2
  3. package/src/agents/Agent.js +300 -0
  4. package/src/agents/AgentAdditionService.js +311 -0
  5. package/src/agents/AgentCheckService.js +690 -0
  6. package/src/agents/AgentInstallationService.js +140 -0
  7. package/src/agents/AgentSetupService.js +467 -0
  8. package/src/agents/AgentStatus.js +183 -0
  9. package/src/agents/AgentVerificationService.js +634 -0
  10. package/src/agents/ConfigurationSchemaValidator.js +543 -0
  11. package/src/agents/EnvironmentConfigurationManager.js +602 -0
  12. package/src/agents/InstallationErrorHandler.js +372 -0
  13. package/src/agents/InstallationLog.js +363 -0
  14. package/src/agents/InstallationMethod.js +510 -0
  15. package/src/agents/InstallationOrchestrator.js +352 -0
  16. package/src/agents/InstallationProgressReporter.js +372 -0
  17. package/src/agents/InstallationRetryManager.js +322 -0
  18. package/src/agents/InstallationType.js +254 -0
  19. package/src/agents/OperationTypes.js +310 -0
  20. package/src/agents/PerformanceMetricsCollector.js +493 -0
  21. package/src/agents/SecurityValidationService.js +534 -0
  22. package/src/agents/VerificationTest.js +354 -0
  23. package/src/agents/VerificationType.js +226 -0
  24. package/src/agents/WindowsPermissionHandler.js +518 -0
  25. package/src/agents/config/AgentConfigManager.js +393 -0
  26. package/src/agents/config/AgentDefaultsRegistry.js +373 -0
  27. package/src/agents/config/ConfigValidator.js +281 -0
  28. package/src/agents/discovery/AgentDiscoveryService.js +707 -0
  29. package/src/agents/logging/AgentLogger.js +511 -0
  30. package/src/agents/status/AgentStatusManager.js +481 -0
  31. package/src/agents/storage/FileManager.js +454 -0
  32. package/src/agents/verification/AgentCommunicationTester.js +474 -0
  33. package/src/agents/verification/BaseVerifier.js +430 -0
  34. package/src/agents/verification/CommandVerifier.js +480 -0
  35. package/src/agents/verification/FileOperationVerifier.js +453 -0
  36. package/src/agents/verification/ResultAnalyzer.js +707 -0
  37. package/src/agents/verification/TestRequirementManager.js +495 -0
  38. package/src/agents/verification/VerificationRunner.js +433 -0
  39. package/src/agents/windows/BaseWindowsInstaller.js +441 -0
  40. package/src/agents/windows/ChocolateyInstaller.js +509 -0
  41. package/src/agents/windows/DirectInstaller.js +443 -0
  42. package/src/agents/windows/InstallerFactory.js +391 -0
  43. package/src/agents/windows/NpmInstaller.js +505 -0
  44. package/src/agents/windows/PowerShellInstaller.js +458 -0
  45. package/src/agents/windows/WinGetInstaller.js +390 -0
  46. package/src/analysis/analysis-reporter.js +132 -0
  47. package/src/analysis/boundary-detector.js +712 -0
  48. package/src/analysis/categorizer.js +340 -0
  49. package/src/analysis/codebase-scanner.js +384 -0
  50. package/src/analysis/line-counter.js +513 -0
  51. package/src/analysis/priority-calculator.js +679 -0
  52. package/src/analysis/report/analysis-report.js +250 -0
  53. package/src/analysis/report/package-analyzer.js +278 -0
  54. package/src/analysis/report/recommendation-generator.js +382 -0
  55. package/src/analysis/report/statistics-generator.js +515 -0
  56. package/src/analysis/reports/analysis-report-model.js +101 -0
  57. package/src/analysis/reports/recommendation-generator.js +283 -0
  58. package/src/analysis/reports/report-generators.js +191 -0
  59. package/src/analysis/reports/statistics-calculator.js +231 -0
  60. package/src/analysis/reports/trend-analyzer.js +219 -0
  61. package/src/analysis/strategy-generator.js +814 -0
  62. package/src/auto-mode/AutoModeBusinessLogic.js +836 -0
  63. package/src/config/refactoring-config.js +307 -0
  64. package/src/health-tracking/json-storage.js +38 -2
  65. package/src/ide-integration/applescript-manager-core.js +233 -0
  66. package/src/ide-integration/applescript-manager.cjs +357 -28
  67. package/src/ide-integration/applescript-manager.js +89 -3599
  68. package/src/ide-integration/cdp-manager.js +306 -0
  69. package/src/ide-integration/claude-code-cli-manager.cjs +1 -1
  70. package/src/ide-integration/continuation-handler.js +337 -0
  71. package/src/ide-integration/ide-status-checker.js +292 -0
  72. package/src/ide-integration/macos-ide-manager.js +627 -0
  73. package/src/ide-integration/macos-text-sender.js +528 -0
  74. package/src/ide-integration/response-reader.js +548 -0
  75. package/src/ide-integration/windows-automation-manager.js +121 -0
  76. package/src/ide-integration/windows-ide-manager.js +373 -0
  77. package/src/index.cjs +25 -3
  78. package/src/index.js +15 -1
  79. package/src/llm/direct-llm-manager.cjs +90 -2
  80. package/src/models/compliance-report.js +538 -0
  81. package/src/models/file-analysis.js +681 -0
  82. package/src/models/refactoring-plan.js +770 -0
  83. package/src/monitoring/alert-system.js +834 -0
  84. package/src/monitoring/compliance-progress-tracker.js +437 -0
  85. package/src/monitoring/continuous-scan-notifications.js +661 -0
  86. package/src/monitoring/continuous-scanner.js +279 -0
  87. package/src/monitoring/file-monitor/file-analyzer.js +262 -0
  88. package/src/monitoring/file-monitor/file-monitor.js +237 -0
  89. package/src/monitoring/file-monitor/watcher.js +194 -0
  90. package/src/monitoring/file-monitor.js +17 -0
  91. package/src/monitoring/notification-manager.js +437 -0
  92. package/src/monitoring/scanner-core.js +368 -0
  93. package/src/monitoring/scanner-events.js +214 -0
  94. package/src/monitoring/violation-notification-system.js +515 -0
  95. package/src/refactoring/boundaries/cohesion-analyzer.js +316 -0
  96. package/src/refactoring/boundaries/extraction-result.js +285 -0
  97. package/src/refactoring/boundaries/extraction-strategies.js +392 -0
  98. package/src/refactoring/boundaries/module-boundary.js +209 -0
  99. package/src/refactoring/boundary/boundary-detector.js +741 -0
  100. package/src/refactoring/boundary/boundary-types.js +405 -0
  101. package/src/refactoring/boundary/extraction-strategies.js +554 -0
  102. package/src/refactoring/boundary-extraction-result.js +77 -0
  103. package/src/refactoring/boundary-extraction-strategies.js +330 -0
  104. package/src/refactoring/boundary-extractor.js +384 -0
  105. package/src/refactoring/boundary-types.js +46 -0
  106. package/src/refactoring/circular/circular-dependency.js +88 -0
  107. package/src/refactoring/circular/cycle-detection.js +147 -0
  108. package/src/refactoring/circular/dependency-node.js +82 -0
  109. package/src/refactoring/circular/dependency-result.js +107 -0
  110. package/src/refactoring/circular/dependency-types.js +58 -0
  111. package/src/refactoring/circular/graph-builder.js +213 -0
  112. package/src/refactoring/circular/resolution-strategy.js +72 -0
  113. package/src/refactoring/circular/strategy-generator.js +229 -0
  114. package/src/refactoring/circular-dependency-resolver-original.js +809 -0
  115. package/src/refactoring/circular-dependency-resolver.js +200 -0
  116. package/src/refactoring/code-mover.js +761 -0
  117. package/src/refactoring/file-splitter.js +696 -0
  118. package/src/refactoring/functionality-validator.js +816 -0
  119. package/src/refactoring/import-manager.js +774 -0
  120. package/src/refactoring/module-boundary.js +107 -0
  121. package/src/refactoring/refactoring-executor.js +672 -0
  122. package/src/refactoring/refactoring-rollback.js +614 -0
  123. package/src/refactoring/test-validator.js +631 -0
  124. package/src/requirement-management/default-requirement-manager.js +321 -0
  125. package/src/requirement-management/requirement-file-parser.js +159 -0
  126. package/src/requirement-management/requirement-sequencer.js +221 -0
  127. package/src/rui/commands/AgentCommandParser.js +600 -0
  128. package/src/rui/commands/AgentCommands.js +487 -0
  129. package/src/rui/commands/AgentResponseFormatter.js +832 -0
  130. package/src/scripts/verify-full-compliance.js +269 -0
  131. package/src/sync/sync-engine-core.js +1 -0
  132. package/src/sync/sync-engine-remote-handlers.js +135 -0
  133. package/src/task-generation/automated-task-generator.js +351 -0
  134. package/src/task-generation/prioritizer.js +287 -0
  135. package/src/task-generation/task-list-updater.js +215 -0
  136. package/src/task-generation/task-management-integration.js +480 -0
  137. package/src/task-generation/task-manager-integration.js +270 -0
  138. package/src/task-generation/violation-task-generator.js +474 -0
  139. package/src/task-management/continuous-scan-integration.js +342 -0
  140. package/src/timeout-management/index.js +12 -3
  141. package/src/timeout-management/response-time-tracker.js +167 -0
  142. package/src/timeout-management/timeout-calculator.js +159 -0
  143. package/src/timeout-management/timeout-config-manager.js +172 -0
  144. package/src/utils/ast-analyzer.js +417 -0
  145. package/src/utils/current-requirement-manager.js +276 -0
  146. package/src/utils/current-requirement-operations.js +472 -0
  147. package/src/utils/dependency-mapper.js +456 -0
  148. package/src/utils/download-with-progress.js +4 -2
  149. package/src/utils/electron-update-checker.js +4 -1
  150. package/src/utils/file-size-analyzer.js +272 -0
  151. package/src/utils/import-updater.js +280 -0
  152. package/src/utils/refactoring-tools.js +512 -0
  153. package/src/utils/report-generator.js +569 -0
  154. package/src/utils/reports/report-analysis.js +218 -0
  155. package/src/utils/reports/report-types.js +55 -0
  156. package/src/utils/reports/summary-generators.js +102 -0
  157. package/src/utils/requirement-file-management.js +157 -0
  158. package/src/utils/requirement-helpers/requirement-file-ops.js +392 -0
  159. package/src/utils/requirement-helpers/requirement-mover.js +414 -0
  160. package/src/utils/requirement-helpers/requirement-parser.js +326 -0
  161. package/src/utils/requirement-helpers/requirement-status.js +320 -0
  162. package/src/utils/requirement-helpers-new.js +55 -0
  163. package/src/utils/requirement-helpers-refactored.js +367 -0
  164. package/src/utils/requirement-helpers.js +291 -1191
  165. package/src/utils/requirement-movement-operations.js +450 -0
  166. package/src/utils/requirement-movement.js +312 -0
  167. package/src/utils/requirement-parsing-helpers.js +56 -0
  168. package/src/utils/requirement-statistics.js +200 -0
  169. package/src/utils/requirement-text-utils.js +58 -0
  170. package/src/utils/rollback/rollback-handlers.js +125 -0
  171. package/src/utils/rollback/rollback-operation.js +63 -0
  172. package/src/utils/rollback/rollback-recorder.js +166 -0
  173. package/src/utils/rollback/rollback-state-manager.js +175 -0
  174. package/src/utils/rollback/rollback-types.js +33 -0
  175. package/src/utils/rollback/rollback-utils.js +110 -0
  176. package/src/utils/rollback-manager-original.js +569 -0
  177. package/src/utils/rollback-manager.js +202 -0
  178. package/src/utils/smoke-test-cli.js +362 -0
  179. package/src/utils/smoke-test-gui.js +351 -0
  180. package/src/utils/smoke-test-orchestrator.js +321 -0
  181. package/src/utils/smoke-test-runner.js +60 -0
  182. package/src/utils/smoke-test-web.js +347 -0
  183. package/src/utils/specification-helpers.js +39 -13
  184. package/src/utils/specification-migration.js +97 -0
  185. package/src/utils/test-runner.js +579 -0
  186. package/src/utils/validation-framework.js +518 -0
  187. package/src/validation/compliance-analyzer.js +197 -0
  188. package/src/validation/compliance-report-generator.js +343 -0
  189. package/src/validation/compliance-reporter.js +711 -0
  190. package/src/validation/compliance-rules.js +127 -0
  191. package/src/validation/constitution-validator-new.js +196 -0
  192. package/src/validation/constitution-validator.js +17 -0
  193. package/src/validation/file-validators.js +170 -0
  194. package/src/validation/line-limit/file-analyzer.js +201 -0
  195. package/src/validation/line-limit/line-limit-validator.js +208 -0
  196. package/src/validation/line-limit/validation-result.js +144 -0
  197. package/src/validation/line-limit-core.js +225 -0
  198. package/src/validation/line-limit-reporter.js +134 -0
  199. package/src/validation/line-limit-result.js +125 -0
  200. package/src/validation/line-limit-validator.js +41 -0
  201. package/src/validation/metrics-calculator.js +660 -0
  202. 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;