@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.
- package/README.md +323 -0
- package/__tests__/hooks/bash-safety.test.ts +289 -0
- package/__tests__/hooks/file-organization.test.ts +335 -0
- package/__tests__/hooks/git-commit.test.ts +336 -0
- package/__tests__/hooks/index.ts +23 -0
- package/__tests__/hooks/session-hooks.test.ts +357 -0
- package/__tests__/hooks/task-hooks.test.ts +193 -0
- package/docs/EVENTS_IMPLEMENTATION_SUMMARY.md +388 -0
- package/docs/EVENTS_QUICK_REFERENCE.md +470 -0
- package/docs/EVENTS_README.md +352 -0
- package/package.json +39 -0
- package/src/core/config/defaults.ts +207 -0
- package/src/core/config/index.ts +15 -0
- package/src/core/config/loader.ts +271 -0
- package/src/core/config/schema.ts +188 -0
- package/src/core/config/validator.ts +209 -0
- package/src/core/event-bus.ts +236 -0
- package/src/core/index.ts +22 -0
- package/src/core/interfaces/agent.interface.ts +251 -0
- package/src/core/interfaces/coordinator.interface.ts +363 -0
- package/src/core/interfaces/event.interface.ts +267 -0
- package/src/core/interfaces/index.ts +19 -0
- package/src/core/interfaces/memory.interface.ts +332 -0
- package/src/core/interfaces/task.interface.ts +223 -0
- package/src/core/orchestrator/event-coordinator.ts +122 -0
- package/src/core/orchestrator/health-monitor.ts +214 -0
- package/src/core/orchestrator/index.ts +89 -0
- package/src/core/orchestrator/lifecycle-manager.ts +263 -0
- package/src/core/orchestrator/session-manager.ts +279 -0
- package/src/core/orchestrator/task-manager.ts +317 -0
- package/src/events/domain-events.ts +584 -0
- package/src/events/event-store.test.ts +387 -0
- package/src/events/event-store.ts +588 -0
- package/src/events/example-usage.ts +293 -0
- package/src/events/index.ts +90 -0
- package/src/events/projections.ts +561 -0
- package/src/events/state-reconstructor.ts +349 -0
- package/src/events.ts +367 -0
- package/src/hooks/INTEGRATION.md +658 -0
- package/src/hooks/README.md +532 -0
- package/src/hooks/example-usage.ts +499 -0
- package/src/hooks/executor.ts +379 -0
- package/src/hooks/hooks.test.ts +421 -0
- package/src/hooks/index.ts +131 -0
- package/src/hooks/registry.ts +333 -0
- package/src/hooks/safety/bash-safety.ts +604 -0
- package/src/hooks/safety/file-organization.ts +473 -0
- package/src/hooks/safety/git-commit.ts +623 -0
- package/src/hooks/safety/index.ts +46 -0
- package/src/hooks/session-hooks.ts +559 -0
- package/src/hooks/task-hooks.ts +513 -0
- package/src/hooks/types.ts +357 -0
- package/src/hooks/verify-exports.test.ts +125 -0
- package/src/index.ts +195 -0
- package/src/mcp/connection-pool.ts +438 -0
- package/src/mcp/index.ts +183 -0
- package/src/mcp/server.ts +774 -0
- package/src/mcp/session-manager.ts +428 -0
- package/src/mcp/tool-registry.ts +566 -0
- package/src/mcp/transport/http.ts +557 -0
- package/src/mcp/transport/index.ts +294 -0
- package/src/mcp/transport/stdio.ts +324 -0
- package/src/mcp/transport/websocket.ts +484 -0
- package/src/mcp/types.ts +565 -0
- package/src/plugin-interface.ts +663 -0
- package/src/plugin-loader.ts +638 -0
- package/src/plugin-registry.ts +604 -0
- package/src/plugins/index.ts +34 -0
- package/src/plugins/official/hive-mind-plugin.ts +330 -0
- package/src/plugins/official/index.ts +24 -0
- package/src/plugins/official/maestro-plugin.ts +508 -0
- package/src/plugins/types.ts +108 -0
- package/src/resilience/bulkhead.ts +277 -0
- package/src/resilience/circuit-breaker.ts +326 -0
- package/src/resilience/index.ts +26 -0
- package/src/resilience/rate-limiter.ts +420 -0
- package/src/resilience/retry.ts +224 -0
- package/src/security/index.ts +39 -0
- package/src/security/input-validation.ts +265 -0
- package/src/security/secure-random.ts +159 -0
- package/src/services/index.ts +16 -0
- package/src/services/v3-progress.service.ts +505 -0
- package/src/types/agent.types.ts +144 -0
- package/src/types/index.ts +22 -0
- package/src/types/mcp.types.ts +300 -0
- package/src/types/memory.types.ts +263 -0
- package/src/types/swarm.types.ts +255 -0
- package/src/types/task.types.ts +205 -0
- package/src/types.ts +367 -0
- package/src/utils/secure-logger.d.ts +69 -0
- package/src/utils/secure-logger.d.ts.map +1 -0
- package/src/utils/secure-logger.js +208 -0
- package/src/utils/secure-logger.js.map +1 -0
- package/src/utils/secure-logger.ts +257 -0
- package/tmp.json +0 -0
- 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
|
+
}
|