@sparkleideas/shared 3.0.0-alpha.7

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 (96) hide show
  1. package/README.md +323 -0
  2. package/__tests__/hooks/bash-safety.test.ts +289 -0
  3. package/__tests__/hooks/file-organization.test.ts +335 -0
  4. package/__tests__/hooks/git-commit.test.ts +336 -0
  5. package/__tests__/hooks/index.ts +23 -0
  6. package/__tests__/hooks/session-hooks.test.ts +357 -0
  7. package/__tests__/hooks/task-hooks.test.ts +193 -0
  8. package/docs/EVENTS_IMPLEMENTATION_SUMMARY.md +388 -0
  9. package/docs/EVENTS_QUICK_REFERENCE.md +470 -0
  10. package/docs/EVENTS_README.md +352 -0
  11. package/package.json +39 -0
  12. package/src/core/config/defaults.ts +207 -0
  13. package/src/core/config/index.ts +15 -0
  14. package/src/core/config/loader.ts +271 -0
  15. package/src/core/config/schema.ts +188 -0
  16. package/src/core/config/validator.ts +209 -0
  17. package/src/core/event-bus.ts +236 -0
  18. package/src/core/index.ts +22 -0
  19. package/src/core/interfaces/agent.interface.ts +251 -0
  20. package/src/core/interfaces/coordinator.interface.ts +363 -0
  21. package/src/core/interfaces/event.interface.ts +267 -0
  22. package/src/core/interfaces/index.ts +19 -0
  23. package/src/core/interfaces/memory.interface.ts +332 -0
  24. package/src/core/interfaces/task.interface.ts +223 -0
  25. package/src/core/orchestrator/event-coordinator.ts +122 -0
  26. package/src/core/orchestrator/health-monitor.ts +214 -0
  27. package/src/core/orchestrator/index.ts +89 -0
  28. package/src/core/orchestrator/lifecycle-manager.ts +263 -0
  29. package/src/core/orchestrator/session-manager.ts +279 -0
  30. package/src/core/orchestrator/task-manager.ts +317 -0
  31. package/src/events/domain-events.ts +584 -0
  32. package/src/events/event-store.test.ts +387 -0
  33. package/src/events/event-store.ts +588 -0
  34. package/src/events/example-usage.ts +293 -0
  35. package/src/events/index.ts +90 -0
  36. package/src/events/projections.ts +561 -0
  37. package/src/events/state-reconstructor.ts +349 -0
  38. package/src/events.ts +367 -0
  39. package/src/hooks/INTEGRATION.md +658 -0
  40. package/src/hooks/README.md +532 -0
  41. package/src/hooks/example-usage.ts +499 -0
  42. package/src/hooks/executor.ts +379 -0
  43. package/src/hooks/hooks.test.ts +421 -0
  44. package/src/hooks/index.ts +131 -0
  45. package/src/hooks/registry.ts +333 -0
  46. package/src/hooks/safety/bash-safety.ts +604 -0
  47. package/src/hooks/safety/file-organization.ts +473 -0
  48. package/src/hooks/safety/git-commit.ts +623 -0
  49. package/src/hooks/safety/index.ts +46 -0
  50. package/src/hooks/session-hooks.ts +559 -0
  51. package/src/hooks/task-hooks.ts +513 -0
  52. package/src/hooks/types.ts +357 -0
  53. package/src/hooks/verify-exports.test.ts +125 -0
  54. package/src/index.ts +195 -0
  55. package/src/mcp/connection-pool.ts +438 -0
  56. package/src/mcp/index.ts +183 -0
  57. package/src/mcp/server.ts +774 -0
  58. package/src/mcp/session-manager.ts +428 -0
  59. package/src/mcp/tool-registry.ts +566 -0
  60. package/src/mcp/transport/http.ts +557 -0
  61. package/src/mcp/transport/index.ts +294 -0
  62. package/src/mcp/transport/stdio.ts +324 -0
  63. package/src/mcp/transport/websocket.ts +484 -0
  64. package/src/mcp/types.ts +565 -0
  65. package/src/plugin-interface.ts +663 -0
  66. package/src/plugin-loader.ts +638 -0
  67. package/src/plugin-registry.ts +604 -0
  68. package/src/plugins/index.ts +34 -0
  69. package/src/plugins/official/hive-mind-plugin.ts +330 -0
  70. package/src/plugins/official/index.ts +24 -0
  71. package/src/plugins/official/maestro-plugin.ts +508 -0
  72. package/src/plugins/types.ts +108 -0
  73. package/src/resilience/bulkhead.ts +277 -0
  74. package/src/resilience/circuit-breaker.ts +326 -0
  75. package/src/resilience/index.ts +26 -0
  76. package/src/resilience/rate-limiter.ts +420 -0
  77. package/src/resilience/retry.ts +224 -0
  78. package/src/security/index.ts +39 -0
  79. package/src/security/input-validation.ts +265 -0
  80. package/src/security/secure-random.ts +159 -0
  81. package/src/services/index.ts +16 -0
  82. package/src/services/v3-progress.service.ts +505 -0
  83. package/src/types/agent.types.ts +144 -0
  84. package/src/types/index.ts +22 -0
  85. package/src/types/mcp.types.ts +300 -0
  86. package/src/types/memory.types.ts +263 -0
  87. package/src/types/swarm.types.ts +255 -0
  88. package/src/types/task.types.ts +205 -0
  89. package/src/types.ts +367 -0
  90. package/src/utils/secure-logger.d.ts +69 -0
  91. package/src/utils/secure-logger.d.ts.map +1 -0
  92. package/src/utils/secure-logger.js +208 -0
  93. package/src/utils/secure-logger.js.map +1 -0
  94. package/src/utils/secure-logger.ts +257 -0
  95. package/tmp.json +0 -0
  96. package/tsconfig.json +9 -0
@@ -0,0 +1,499 @@
1
+ /**
2
+ * V3 Hooks System - Example Usage
3
+ *
4
+ * Demonstrates practical use cases for the hooks system.
5
+ *
6
+ * @module v3/shared/hooks/example-usage
7
+ */
8
+
9
+ import { createHookRegistry } from './registry.js';
10
+ import { createHookExecutor } from './executor.js';
11
+ import { HookEvent, HookPriority, HookContext } from './types.js';
12
+ import { createEventBus } from '../core/event-bus.js';
13
+
14
+ // =============================================================================
15
+ // Example 1: Security Hooks - Prevent Dangerous Commands
16
+ // =============================================================================
17
+
18
+ export function setupSecurityHooks() {
19
+ const registry = createHookRegistry();
20
+ const eventBus = createEventBus();
21
+ const executor = createHookExecutor(registry, eventBus);
22
+
23
+ // Block dangerous commands
24
+ registry.register(
25
+ HookEvent.PreCommand,
26
+ async (context) => {
27
+ const dangerousPatterns = [
28
+ /rm\s+-rf\s+\//,
29
+ /format\s+c:/i,
30
+ /del\s+\/f\s+\/s\s+\/q/i,
31
+ /dd\s+if=/,
32
+ ];
33
+
34
+ const command = context.command?.command || '';
35
+
36
+ for (const pattern of dangerousPatterns) {
37
+ if (pattern.test(command)) {
38
+ return {
39
+ success: false,
40
+ abort: true,
41
+ error: new Error(`šŸ›”ļø Dangerous command blocked: ${command}`),
42
+ };
43
+ }
44
+ }
45
+
46
+ return { success: true };
47
+ },
48
+ HookPriority.Critical,
49
+ {
50
+ name: 'Security: Block Dangerous Commands',
51
+ metadata: { category: 'security' },
52
+ }
53
+ );
54
+
55
+ // Log security-sensitive commands
56
+ registry.register(
57
+ HookEvent.PostCommand,
58
+ async (context) => {
59
+ const sensitiveKeywords = ['password', 'secret', 'key', 'token', 'auth'];
60
+ const command = context.command?.command.toLowerCase() || '';
61
+
62
+ if (sensitiveKeywords.some(keyword => command.includes(keyword))) {
63
+ console.warn('āš ļø Security-sensitive command executed:', command);
64
+ }
65
+
66
+ return { success: true };
67
+ },
68
+ HookPriority.Normal,
69
+ {
70
+ name: 'Security: Audit Sensitive Commands',
71
+ }
72
+ );
73
+
74
+ return { registry, executor };
75
+ }
76
+
77
+ // =============================================================================
78
+ // Example 2: Learning Hooks - ReasoningBank Integration
79
+ // =============================================================================
80
+
81
+ export function setupLearningHooks() {
82
+ const registry = createHookRegistry();
83
+ const eventBus = createEventBus();
84
+ const executor = createHookExecutor(registry, eventBus);
85
+
86
+ // Pre-edit: Retrieve similar past edits
87
+ registry.register(
88
+ HookEvent.PreEdit,
89
+ async (context) => {
90
+ const filePath = context.file?.path;
91
+ if (!filePath) {
92
+ return { success: true };
93
+ }
94
+
95
+ console.log(`šŸ“š Searching for similar edits to ${filePath}...`);
96
+
97
+ // Example ReasoningBank search results (replace with actual @sparkleideas/agentic-flow call)
98
+ const similarEdits = [
99
+ { task: `Edit ${filePath}`, reward: 0.92, critique: 'Good test coverage' },
100
+ { task: `Edit ${filePath}`, reward: 0.88, critique: 'Could improve error handling' },
101
+ ];
102
+
103
+ return {
104
+ success: true,
105
+ data: {
106
+ metadata: {
107
+ ...context.metadata,
108
+ learningContext: similarEdits,
109
+ },
110
+ },
111
+ };
112
+ },
113
+ HookPriority.High,
114
+ {
115
+ name: 'Learning: Pre-Edit Context Retrieval',
116
+ timeout: 2000,
117
+ }
118
+ );
119
+
120
+ // Post-edit: Store edit pattern
121
+ registry.register(
122
+ HookEvent.PostEdit,
123
+ async (context) => {
124
+ const success = context.metadata?.editSuccess ?? true;
125
+ const filePath = context.file?.path;
126
+
127
+ if (!filePath) {
128
+ return { success: true };
129
+ }
130
+
131
+ console.log(`šŸ’¾ Storing edit pattern for ${filePath} (success: ${success})`);
132
+
133
+ // Example ReasoningBank storage (replace with actual @sparkleideas/agentic-flow call)
134
+ const pattern = {
135
+ task: `Edit ${filePath}`,
136
+ reward: success ? 0.9 : 0.3,
137
+ success,
138
+ };
139
+
140
+ console.log('Pattern stored:', pattern);
141
+
142
+ return { success: true };
143
+ },
144
+ HookPriority.Normal,
145
+ {
146
+ name: 'Learning: Post-Edit Pattern Storage',
147
+ }
148
+ );
149
+
150
+ return { registry, executor };
151
+ }
152
+
153
+ // =============================================================================
154
+ // Example 3: Performance Monitoring Hooks
155
+ // =============================================================================
156
+
157
+ export function setupPerformanceHooks() {
158
+ const registry = createHookRegistry();
159
+ const eventBus = createEventBus();
160
+ const executor = createHookExecutor(registry, eventBus);
161
+
162
+ const performanceMetrics = new Map<string, { start: number; end?: number }>();
163
+
164
+ // Start performance tracking
165
+ registry.register(
166
+ HookEvent.PreToolUse,
167
+ async (context) => {
168
+ const toolName = context.tool?.name;
169
+ if (!toolName) {
170
+ return { success: true };
171
+ }
172
+
173
+ const metricId = `tool-${toolName}-${Date.now()}`;
174
+ performanceMetrics.set(metricId, { start: Date.now() });
175
+
176
+ return {
177
+ success: true,
178
+ data: {
179
+ metadata: {
180
+ ...context.metadata,
181
+ performanceMetricId: metricId,
182
+ },
183
+ },
184
+ };
185
+ },
186
+ HookPriority.High,
187
+ {
188
+ name: 'Performance: Start Tool Tracking',
189
+ }
190
+ );
191
+
192
+ // End performance tracking
193
+ registry.register(
194
+ HookEvent.PostToolUse,
195
+ async (context) => {
196
+ const metricId = context.metadata?.performanceMetricId as string;
197
+ if (!metricId) {
198
+ return { success: true };
199
+ }
200
+
201
+ const metric = performanceMetrics.get(metricId);
202
+ if (metric) {
203
+ metric.end = Date.now();
204
+ const duration = metric.end - metric.start;
205
+
206
+ console.log(`ā±ļø Tool ${context.tool?.name} took ${duration}ms`);
207
+
208
+ if (duration > 5000) {
209
+ console.warn(`āš ļø Slow tool execution detected: ${duration}ms`);
210
+ }
211
+ }
212
+
213
+ return { success: true };
214
+ },
215
+ HookPriority.Normal,
216
+ {
217
+ name: 'Performance: End Tool Tracking',
218
+ }
219
+ );
220
+
221
+ return { registry, executor, performanceMetrics };
222
+ }
223
+
224
+ // =============================================================================
225
+ // Example 4: File Validation Hooks
226
+ // =============================================================================
227
+
228
+ export function setupFileValidationHooks() {
229
+ const registry = createHookRegistry();
230
+ const eventBus = createEventBus();
231
+ const executor = createHookExecutor(registry, eventBus);
232
+
233
+ // Validate file paths
234
+ registry.register(
235
+ HookEvent.PreWrite,
236
+ async (context) => {
237
+ const filePath = context.file?.path;
238
+ if (!filePath) {
239
+ return { success: true };
240
+ }
241
+
242
+ // Check for dangerous paths
243
+ const dangerousPaths = ['../', '/etc/', '/sys/', 'C:\\Windows'];
244
+ if (dangerousPaths.some(path => filePath.includes(path))) {
245
+ return {
246
+ success: false,
247
+ abort: true,
248
+ error: new Error(`šŸ›”ļø Dangerous file path blocked: ${filePath}`),
249
+ };
250
+ }
251
+
252
+ // Check for sensitive files
253
+ const sensitivePatterns = ['.env', 'credentials', 'secrets', '.pem', '.key'];
254
+ if (sensitivePatterns.some(pattern => filePath.includes(pattern))) {
255
+ console.warn(`āš ļø Writing to sensitive file: ${filePath}`);
256
+ }
257
+
258
+ return { success: true };
259
+ },
260
+ HookPriority.Critical,
261
+ {
262
+ name: 'File: Validate Write Path',
263
+ }
264
+ );
265
+
266
+ // Check file size limits
267
+ registry.register(
268
+ HookEvent.PreWrite,
269
+ async (context) => {
270
+ const content = context.file?.content;
271
+ if (!content) {
272
+ return { success: true };
273
+ }
274
+
275
+ const maxSize = 10 * 1024 * 1024; // 10MB
276
+ const size = Buffer.byteLength(content, 'utf8');
277
+
278
+ if (size > maxSize) {
279
+ return {
280
+ success: false,
281
+ abort: true,
282
+ error: new Error(`File too large: ${size} bytes (max: ${maxSize})`),
283
+ };
284
+ }
285
+
286
+ return { success: true };
287
+ },
288
+ HookPriority.High,
289
+ {
290
+ name: 'File: Check Size Limit',
291
+ }
292
+ );
293
+
294
+ return { registry, executor };
295
+ }
296
+
297
+ // =============================================================================
298
+ // Example 5: Session Management Hooks
299
+ // =============================================================================
300
+
301
+ export function setupSessionHooks() {
302
+ const registry = createHookRegistry();
303
+ const eventBus = createEventBus();
304
+ const executor = createHookExecutor(registry, eventBus);
305
+
306
+ let activeSession: { id: string; startTime: Date } | null = null;
307
+
308
+ // Initialize session
309
+ registry.register(
310
+ HookEvent.SessionStart,
311
+ async (context) => {
312
+ const sessionId = context.session?.id || `session-${Date.now()}`;
313
+
314
+ activeSession = {
315
+ id: sessionId,
316
+ startTime: new Date(),
317
+ };
318
+
319
+ console.log(`šŸš€ Session started: ${sessionId}`);
320
+
321
+ return {
322
+ success: true,
323
+ data: {
324
+ session: {
325
+ id: sessionId,
326
+ startTime: activeSession.startTime,
327
+ },
328
+ },
329
+ };
330
+ },
331
+ HookPriority.Critical,
332
+ {
333
+ name: 'Session: Initialize',
334
+ }
335
+ );
336
+
337
+ // Cleanup session
338
+ registry.register(
339
+ HookEvent.SessionEnd,
340
+ async (context) => {
341
+ if (activeSession) {
342
+ const duration = Date.now() - activeSession.startTime.getTime();
343
+ console.log(`šŸ‘‹ Session ended: ${activeSession.id} (duration: ${duration}ms)`);
344
+
345
+ activeSession = null;
346
+ }
347
+
348
+ return { success: true };
349
+ },
350
+ HookPriority.Critical,
351
+ {
352
+ name: 'Session: Cleanup',
353
+ }
354
+ );
355
+
356
+ return { registry, executor };
357
+ }
358
+
359
+ // =============================================================================
360
+ // Example 6: Error Handling Hooks
361
+ // =============================================================================
362
+
363
+ export function setupErrorHooks() {
364
+ const registry = createHookRegistry();
365
+ const eventBus = createEventBus();
366
+ const executor = createHookExecutor(registry, eventBus);
367
+
368
+ const errorLog: Array<{ timestamp: Date; error: Error; context?: string }> = [];
369
+
370
+ // Log all errors
371
+ registry.register(
372
+ HookEvent.OnError,
373
+ async (context) => {
374
+ const error = context.error?.error;
375
+ if (!error) {
376
+ return { success: true };
377
+ }
378
+
379
+ errorLog.push({
380
+ timestamp: new Date(),
381
+ error,
382
+ context: context.error?.context,
383
+ });
384
+
385
+ console.error(`āŒ Error occurred:`, error.message);
386
+
387
+ return { success: true };
388
+ },
389
+ HookPriority.High,
390
+ {
391
+ name: 'Error: Log Errors',
392
+ }
393
+ );
394
+
395
+ // Attempt recovery for recoverable errors
396
+ registry.register(
397
+ HookEvent.OnError,
398
+ async (context) => {
399
+ const recoverable = context.error?.recoverable ?? false;
400
+
401
+ if (recoverable) {
402
+ console.log(`šŸ”„ Attempting error recovery...`);
403
+ // Implement recovery logic here
404
+ }
405
+
406
+ return { success: true };
407
+ },
408
+ HookPriority.Normal,
409
+ {
410
+ name: 'Error: Attempt Recovery',
411
+ }
412
+ );
413
+
414
+ return { registry, executor, errorLog };
415
+ }
416
+
417
+ // =============================================================================
418
+ // Demo: Run All Examples
419
+ // =============================================================================
420
+
421
+ export async function runDemo() {
422
+ console.log('='.repeat(60));
423
+ console.log('V3 Hooks System - Demo');
424
+ console.log('='.repeat(60));
425
+
426
+ // Example 1: Security Hooks
427
+ console.log('\nšŸ“‹ Example 1: Security Hooks');
428
+ const { executor: securityExecutor } = setupSecurityHooks();
429
+
430
+ const dangerousCommand: HookContext = {
431
+ event: HookEvent.PreCommand,
432
+ timestamp: new Date(),
433
+ command: {
434
+ command: 'rm -rf /',
435
+ isDestructive: true,
436
+ },
437
+ };
438
+
439
+ const securityResult = await securityExecutor.execute(
440
+ HookEvent.PreCommand,
441
+ dangerousCommand
442
+ );
443
+
444
+ console.log(`Security result: ${securityResult.success ? 'āœ… Passed' : 'āŒ Blocked'}`);
445
+
446
+ // Example 2: Learning Hooks
447
+ console.log('\nšŸ“‹ Example 2: Learning Hooks');
448
+ const { executor: learningExecutor } = setupLearningHooks();
449
+
450
+ const editContext: HookContext = {
451
+ event: HookEvent.PreEdit,
452
+ timestamp: new Date(),
453
+ file: {
454
+ path: '/workspaces/project/src/app.ts',
455
+ operation: 'edit',
456
+ },
457
+ };
458
+
459
+ await learningExecutor.execute(HookEvent.PreEdit, editContext);
460
+
461
+ // Example 3: Performance Monitoring
462
+ console.log('\nšŸ“‹ Example 3: Performance Monitoring');
463
+ const { executor: perfExecutor } = setupPerformanceHooks();
464
+
465
+ const toolContext: HookContext = {
466
+ event: HookEvent.PreToolUse,
467
+ timestamp: new Date(),
468
+ tool: {
469
+ name: 'Read',
470
+ parameters: { path: 'file.ts' },
471
+ category: 'file',
472
+ },
473
+ };
474
+
475
+ const preToolResult = await perfExecutor.execute(HookEvent.PreToolUse, toolContext);
476
+
477
+ // Brief delay representing tool execution time
478
+ await new Promise(resolve => setTimeout(resolve, 100));
479
+
480
+ await perfExecutor.execute(HookEvent.PostToolUse, {
481
+ ...toolContext,
482
+ event: HookEvent.PostToolUse,
483
+ metadata: preToolResult.finalContext?.metadata,
484
+ });
485
+
486
+ // Get statistics
487
+ console.log('\nšŸ“Š Hook Statistics');
488
+ const stats = perfExecutor.getRegistry().getStats();
489
+ console.log(`Total hooks: ${stats.totalHooks}`);
490
+ console.log(`Total executions: ${stats.totalExecutions}`);
491
+ console.log(`Average execution time: ${stats.avgExecutionTime.toFixed(2)}ms`);
492
+
493
+ console.log('\n' + '='.repeat(60));
494
+ }
495
+
496
+ // Run demo if executed directly
497
+ if (import.meta.url === `file://${process.argv[1]}`) {
498
+ runDemo().catch(console.error);
499
+ }