@sparkleideas/plugins 3.0.0-alpha.10

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 (80) hide show
  1. package/README.md +401 -0
  2. package/__tests__/collection-manager.test.ts +332 -0
  3. package/__tests__/dependency-graph.test.ts +434 -0
  4. package/__tests__/enhanced-plugin-registry.test.ts +488 -0
  5. package/__tests__/plugin-registry.test.ts +368 -0
  6. package/__tests__/ruvector-bridge.test.ts +2429 -0
  7. package/__tests__/ruvector-integration.test.ts +1602 -0
  8. package/__tests__/ruvector-migrations.test.ts +1099 -0
  9. package/__tests__/ruvector-quantization.test.ts +846 -0
  10. package/__tests__/ruvector-streaming.test.ts +1088 -0
  11. package/__tests__/sdk.test.ts +325 -0
  12. package/__tests__/security.test.ts +348 -0
  13. package/__tests__/utils/ruvector-test-utils.ts +860 -0
  14. package/examples/plugin-creator/index.ts +636 -0
  15. package/examples/plugin-creator/plugin-creator.test.ts +312 -0
  16. package/examples/ruvector/README.md +288 -0
  17. package/examples/ruvector/attention-patterns.ts +394 -0
  18. package/examples/ruvector/basic-usage.ts +288 -0
  19. package/examples/ruvector/docker-compose.yml +75 -0
  20. package/examples/ruvector/gnn-analysis.ts +501 -0
  21. package/examples/ruvector/hyperbolic-hierarchies.ts +557 -0
  22. package/examples/ruvector/init-db.sql +119 -0
  23. package/examples/ruvector/quantization.ts +680 -0
  24. package/examples/ruvector/self-learning.ts +447 -0
  25. package/examples/ruvector/semantic-search.ts +576 -0
  26. package/examples/ruvector/streaming-large-data.ts +507 -0
  27. package/examples/ruvector/transactions.ts +594 -0
  28. package/examples/ruvector-plugins/hook-pattern-library.ts +486 -0
  29. package/examples/ruvector-plugins/index.ts +79 -0
  30. package/examples/ruvector-plugins/intent-router.ts +354 -0
  31. package/examples/ruvector-plugins/mcp-tool-optimizer.ts +424 -0
  32. package/examples/ruvector-plugins/reasoning-bank.ts +657 -0
  33. package/examples/ruvector-plugins/ruvector-plugins.test.ts +518 -0
  34. package/examples/ruvector-plugins/semantic-code-search.ts +498 -0
  35. package/examples/ruvector-plugins/shared/index.ts +20 -0
  36. package/examples/ruvector-plugins/shared/vector-utils.ts +257 -0
  37. package/examples/ruvector-plugins/sona-learning.ts +445 -0
  38. package/package.json +97 -0
  39. package/src/collections/collection-manager.ts +661 -0
  40. package/src/collections/index.ts +56 -0
  41. package/src/collections/official/index.ts +1040 -0
  42. package/src/core/base-plugin.ts +416 -0
  43. package/src/core/plugin-interface.ts +215 -0
  44. package/src/hooks/index.ts +685 -0
  45. package/src/index.ts +378 -0
  46. package/src/integrations/agentic-flow.ts +743 -0
  47. package/src/integrations/index.ts +88 -0
  48. package/src/integrations/ruvector/ARCHITECTURE.md +1245 -0
  49. package/src/integrations/ruvector/attention-advanced.ts +1040 -0
  50. package/src/integrations/ruvector/attention-executor.ts +782 -0
  51. package/src/integrations/ruvector/attention-mechanisms.ts +757 -0
  52. package/src/integrations/ruvector/attention.ts +1063 -0
  53. package/src/integrations/ruvector/gnn.ts +3050 -0
  54. package/src/integrations/ruvector/hyperbolic.ts +1948 -0
  55. package/src/integrations/ruvector/index.ts +394 -0
  56. package/src/integrations/ruvector/migrations/001_create_extension.sql +135 -0
  57. package/src/integrations/ruvector/migrations/002_create_vector_tables.sql +259 -0
  58. package/src/integrations/ruvector/migrations/003_create_indices.sql +328 -0
  59. package/src/integrations/ruvector/migrations/004_create_functions.sql +598 -0
  60. package/src/integrations/ruvector/migrations/005_create_attention_functions.sql +654 -0
  61. package/src/integrations/ruvector/migrations/006_create_gnn_functions.sql +728 -0
  62. package/src/integrations/ruvector/migrations/007_create_hyperbolic_functions.sql +762 -0
  63. package/src/integrations/ruvector/migrations/index.ts +35 -0
  64. package/src/integrations/ruvector/migrations/migrations.ts +647 -0
  65. package/src/integrations/ruvector/quantization.ts +2036 -0
  66. package/src/integrations/ruvector/ruvector-bridge.ts +2000 -0
  67. package/src/integrations/ruvector/self-learning.ts +2376 -0
  68. package/src/integrations/ruvector/streaming.ts +1737 -0
  69. package/src/integrations/ruvector/types.ts +1945 -0
  70. package/src/providers/index.ts +643 -0
  71. package/src/registry/dependency-graph.ts +568 -0
  72. package/src/registry/enhanced-plugin-registry.ts +994 -0
  73. package/src/registry/plugin-registry.ts +604 -0
  74. package/src/sdk/index.ts +563 -0
  75. package/src/security/index.ts +594 -0
  76. package/src/types/index.ts +446 -0
  77. package/src/workers/index.ts +700 -0
  78. package/tmp.json +0 -0
  79. package/tsconfig.json +25 -0
  80. package/vitest.config.ts +23 -0
@@ -0,0 +1,486 @@
1
+ /**
2
+ * Hook Pattern Library Plugin
3
+ *
4
+ * Learn which hooks work best for which file types/operations.
5
+ * Uses @ruvector/wasm for pattern storage and @ruvector/learning-wasm for optimization.
6
+ *
7
+ * Features:
8
+ * - Track hook effectiveness by file type
9
+ * - Learn optimal hook configurations
10
+ * - Recommend hooks for new operations
11
+ * - A/B test hook variations
12
+ * - Auto-tune hook priorities
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * import { hookPatternLibraryPlugin } from '@sparkleideas/plugins/examples/ruvector-plugins';
17
+ * await getDefaultRegistry().register(hookPatternLibraryPlugin);
18
+ * ```
19
+ */
20
+
21
+ import {
22
+ PluginBuilder,
23
+ MCPToolBuilder,
24
+ HookBuilder,
25
+ HookEvent,
26
+ HookPriority,
27
+ Security,
28
+ } from '../../src/index.js';
29
+
30
+ // Import shared vector utilities (consolidated from all plugins)
31
+ import {
32
+ IVectorDB,
33
+ createVectorDB,
34
+ generateHashEmbedding,
35
+ } from './shared/vector-utils.js';
36
+
37
+ // ============================================================================
38
+ // Types
39
+ // ============================================================================
40
+
41
+ export interface HookPattern {
42
+ id: string;
43
+ hookName: string;
44
+ event: HookEvent;
45
+ fileTypes: string[];
46
+ operations: string[];
47
+ effectiveness: number;
48
+ executionTime: number;
49
+ usageCount: number;
50
+ successCount: number;
51
+ failureCount: number;
52
+ embedding?: Float32Array;
53
+ metadata: {
54
+ createdAt: Date;
55
+ updatedAt: Date;
56
+ lastUsed: Date;
57
+ priority: number;
58
+ };
59
+ }
60
+
61
+ export interface PatternMatch {
62
+ pattern: HookPattern;
63
+ similarity: number;
64
+ confidence: number;
65
+ }
66
+
67
+ export interface HookRecommendation {
68
+ hookName: string;
69
+ event: HookEvent;
70
+ priority: number;
71
+ reason: string;
72
+ expectedEffectiveness: number;
73
+ confidence: number;
74
+ }
75
+
76
+ // ============================================================================
77
+ // Hook Pattern Library Core
78
+ // ============================================================================
79
+
80
+ export class HookPatternLibrary {
81
+ private vectorDb: IVectorDB | null = null;
82
+ private patterns = new Map<string, HookPattern>();
83
+ private dimensions = 512;
84
+ private nextId = 1;
85
+ private initPromise: Promise<void> | null = null;
86
+
87
+ // Known effective hook patterns
88
+ private defaultPatterns: Array<Omit<HookPattern, 'id' | 'embedding'>> = [
89
+ { hookName: 'format-on-save', event: HookEvent.PreFileWrite, fileTypes: ['ts', 'tsx', 'js', 'jsx'], operations: ['write', 'edit'], effectiveness: 0.9, executionTime: 50, usageCount: 100, successCount: 95, failureCount: 5, metadata: { createdAt: new Date(), updatedAt: new Date(), lastUsed: new Date(), priority: HookPriority.Normal } },
90
+ { hookName: 'lint-check', event: HookEvent.PreFileWrite, fileTypes: ['ts', 'tsx', 'js', 'jsx'], operations: ['write'], effectiveness: 0.85, executionTime: 100, usageCount: 80, successCount: 75, failureCount: 5, metadata: { createdAt: new Date(), updatedAt: new Date(), lastUsed: new Date(), priority: HookPriority.High } },
91
+ { hookName: 'type-check', event: HookEvent.PreFileWrite, fileTypes: ['ts', 'tsx'], operations: ['write', 'edit'], effectiveness: 0.88, executionTime: 200, usageCount: 90, successCount: 85, failureCount: 5, metadata: { createdAt: new Date(), updatedAt: new Date(), lastUsed: new Date(), priority: HookPriority.High } },
92
+ { hookName: 'auto-import', event: HookEvent.PostFileWrite, fileTypes: ['ts', 'tsx', 'js', 'jsx'], operations: ['write'], effectiveness: 0.75, executionTime: 30, usageCount: 50, successCount: 40, failureCount: 10, metadata: { createdAt: new Date(), updatedAt: new Date(), lastUsed: new Date(), priority: HookPriority.Low } },
93
+ { hookName: 'test-runner', event: HookEvent.PostTaskComplete, fileTypes: ['test.ts', 'spec.ts', 'test.js'], operations: ['complete'], effectiveness: 0.92, executionTime: 500, usageCount: 60, successCount: 58, failureCount: 2, metadata: { createdAt: new Date(), updatedAt: new Date(), lastUsed: new Date(), priority: HookPriority.Normal } },
94
+ { hookName: 'git-stage', event: HookEvent.PostFileWrite, fileTypes: ['*'], operations: ['write', 'edit'], effectiveness: 0.7, executionTime: 20, usageCount: 40, successCount: 35, failureCount: 5, metadata: { createdAt: new Date(), updatedAt: new Date(), lastUsed: new Date(), priority: HookPriority.Deferred } },
95
+ { hookName: 'backup-create', event: HookEvent.PreFileWrite, fileTypes: ['*'], operations: ['write'], effectiveness: 0.95, executionTime: 10, usageCount: 30, successCount: 30, failureCount: 0, metadata: { createdAt: new Date(), updatedAt: new Date(), lastUsed: new Date(), priority: HookPriority.Critical } },
96
+ { hookName: 'security-scan', event: HookEvent.PreCommand, fileTypes: ['*'], operations: ['command'], effectiveness: 0.98, executionTime: 50, usageCount: 100, successCount: 98, failureCount: 2, metadata: { createdAt: new Date(), updatedAt: new Date(), lastUsed: new Date(), priority: HookPriority.Critical } },
97
+ ];
98
+
99
+ async initialize(): Promise<void> {
100
+ if (this.vectorDb) return;
101
+ if (this.initPromise) return this.initPromise;
102
+
103
+ this.initPromise = (async () => {
104
+ this.vectorDb = await createVectorDB(this.dimensions);
105
+ await this.loadDefaultPatterns();
106
+ })();
107
+
108
+ return this.initPromise;
109
+ }
110
+
111
+ private async ensureInitialized(): Promise<IVectorDB> {
112
+ await this.initialize();
113
+ return this.vectorDb!;
114
+ }
115
+
116
+ private async loadDefaultPatterns(): Promise<void> {
117
+ for (const pattern of this.defaultPatterns) {
118
+ await this.recordPattern(pattern);
119
+ }
120
+ }
121
+
122
+ /**
123
+ * Record a hook pattern.
124
+ */
125
+ async recordPattern(pattern: Omit<HookPattern, 'id' | 'embedding'>): Promise<HookPattern> {
126
+ const db = await this.ensureInitialized();
127
+
128
+ const id = `pattern-${this.nextId++}`;
129
+ const embedding = this.generateEmbedding(pattern.hookName, pattern.event, pattern.fileTypes, pattern.operations);
130
+
131
+ const fullPattern: HookPattern = { ...pattern, id, embedding };
132
+
133
+ db.insert(embedding, id, {
134
+ hookName: pattern.hookName,
135
+ event: pattern.event,
136
+ fileTypes: pattern.fileTypes.join(','),
137
+ effectiveness: pattern.effectiveness,
138
+ });
139
+
140
+ this.patterns.set(id, fullPattern);
141
+ return fullPattern;
142
+ }
143
+
144
+ /**
145
+ * Record a hook execution for learning.
146
+ */
147
+ async recordExecution(
148
+ hookName: string,
149
+ event: HookEvent,
150
+ fileType: string,
151
+ operation: string,
152
+ success: boolean,
153
+ executionTime: number
154
+ ): Promise<void> {
155
+ const db = await this.ensureInitialized();
156
+
157
+ const safeHookName = Security.validateString(hookName, { maxLength: 100 });
158
+ const safeFileType = Security.validateString(fileType, { maxLength: 50 });
159
+ const safeOperation = Security.validateString(operation, { maxLength: 50 });
160
+
161
+ // Find existing pattern or create new
162
+ let pattern = Array.from(this.patterns.values()).find(
163
+ p => p.hookName === safeHookName && p.event === event
164
+ );
165
+
166
+ if (pattern) {
167
+ pattern.usageCount++;
168
+ if (success) pattern.successCount++;
169
+ else pattern.failureCount++;
170
+
171
+ pattern.executionTime = (pattern.executionTime * (pattern.usageCount - 1) + executionTime) / pattern.usageCount;
172
+ pattern.effectiveness = pattern.successCount / pattern.usageCount;
173
+ pattern.metadata.updatedAt = new Date();
174
+ pattern.metadata.lastUsed = new Date();
175
+
176
+ if (!pattern.fileTypes.includes(safeFileType)) {
177
+ pattern.fileTypes.push(safeFileType);
178
+ }
179
+ if (!pattern.operations.includes(safeOperation)) {
180
+ pattern.operations.push(safeOperation);
181
+ }
182
+
183
+ // Update embedding
184
+ const embedding = this.generateEmbedding(pattern.hookName, pattern.event, pattern.fileTypes, pattern.operations);
185
+ pattern.embedding = embedding;
186
+
187
+ db.delete(pattern.id);
188
+ db.insert(embedding, pattern.id, {
189
+ hookName: pattern.hookName,
190
+ event: pattern.event,
191
+ fileTypes: pattern.fileTypes.join(','),
192
+ effectiveness: pattern.effectiveness,
193
+ });
194
+ } else {
195
+ await this.recordPattern({
196
+ hookName: safeHookName,
197
+ event,
198
+ fileTypes: [safeFileType],
199
+ operations: [safeOperation],
200
+ effectiveness: success ? 1 : 0,
201
+ executionTime,
202
+ usageCount: 1,
203
+ successCount: success ? 1 : 0,
204
+ failureCount: success ? 0 : 1,
205
+ metadata: {
206
+ createdAt: new Date(),
207
+ updatedAt: new Date(),
208
+ lastUsed: new Date(),
209
+ priority: HookPriority.Normal,
210
+ },
211
+ });
212
+ }
213
+ }
214
+
215
+ /**
216
+ * Find patterns matching a context.
217
+ */
218
+ async findPatterns(fileType: string, operation: string, k: number = 5): Promise<PatternMatch[]> {
219
+ const db = await this.ensureInitialized();
220
+
221
+ const safeFileType = Security.validateString(fileType, { maxLength: 50 });
222
+ const safeOperation = Security.validateString(operation, { maxLength: 50 });
223
+
224
+ const queryEmbedding = this.generateEmbedding('', HookEvent.PreFileWrite, [safeFileType], [safeOperation]);
225
+ const searchResults = db.search(queryEmbedding, k * 2);
226
+
227
+ const results: PatternMatch[] = [];
228
+ for (const result of searchResults) {
229
+ const pattern = this.patterns.get(result.id);
230
+ if (!pattern) continue;
231
+
232
+ // Check if file type matches
233
+ const typeMatches = pattern.fileTypes.includes('*') || pattern.fileTypes.includes(safeFileType) ||
234
+ pattern.fileTypes.some(t => safeFileType.endsWith(t));
235
+
236
+ if (!typeMatches) continue;
237
+
238
+ results.push({
239
+ pattern,
240
+ similarity: result.score,
241
+ confidence: pattern.effectiveness * result.score,
242
+ });
243
+
244
+ if (results.length >= k) break;
245
+ }
246
+
247
+ return results.sort((a, b) => b.confidence - a.confidence);
248
+ }
249
+
250
+ /**
251
+ * Get recommendations for a file type and operation.
252
+ */
253
+ async recommend(fileType: string, operation: string): Promise<HookRecommendation[]> {
254
+ const matches = await this.findPatterns(fileType, operation, 10);
255
+
256
+ const recommendations: HookRecommendation[] = [];
257
+
258
+ for (const match of matches) {
259
+ if (match.pattern.effectiveness < 0.5) continue;
260
+
261
+ recommendations.push({
262
+ hookName: match.pattern.hookName,
263
+ event: match.pattern.event,
264
+ priority: match.pattern.metadata.priority,
265
+ reason: `${(match.pattern.effectiveness * 100).toFixed(0)}% effective for ${match.pattern.fileTypes.join(', ')}`,
266
+ expectedEffectiveness: match.pattern.effectiveness,
267
+ confidence: match.confidence,
268
+ });
269
+ }
270
+
271
+ return recommendations.sort((a, b) => b.expectedEffectiveness - a.expectedEffectiveness);
272
+ }
273
+
274
+ /**
275
+ * Get library statistics.
276
+ */
277
+ getStats(): {
278
+ totalPatterns: number;
279
+ byEvent: Record<string, number>;
280
+ byFileType: Record<string, number>;
281
+ topHooks: Array<{ name: string; effectiveness: number; usageCount: number }>;
282
+ avgEffectiveness: number;
283
+ } {
284
+ const byEvent: Record<string, number> = {};
285
+ const byFileType: Record<string, number> = {};
286
+ let totalEffectiveness = 0;
287
+
288
+ for (const pattern of this.patterns.values()) {
289
+ byEvent[pattern.event] = (byEvent[pattern.event] ?? 0) + 1;
290
+ for (const ft of pattern.fileTypes) {
291
+ byFileType[ft] = (byFileType[ft] ?? 0) + 1;
292
+ }
293
+ totalEffectiveness += pattern.effectiveness;
294
+ }
295
+
296
+ const topHooks = Array.from(this.patterns.values())
297
+ .sort((a, b) => b.effectiveness * b.usageCount - a.effectiveness * a.usageCount)
298
+ .slice(0, 5)
299
+ .map(p => ({ name: p.hookName, effectiveness: p.effectiveness, usageCount: p.usageCount }));
300
+
301
+ return {
302
+ totalPatterns: this.patterns.size,
303
+ byEvent,
304
+ byFileType,
305
+ topHooks,
306
+ avgEffectiveness: this.patterns.size > 0 ? totalEffectiveness / this.patterns.size : 0,
307
+ };
308
+ }
309
+
310
+ // =========================================================================
311
+ // Private Helpers
312
+ // =========================================================================
313
+
314
+ private generateEmbedding(hookName: string, event: HookEvent, fileTypes: string[], operations: string[]): Float32Array {
315
+ const text = `${hookName} ${event} ${fileTypes.join(' ')} ${operations.join(' ')}`.toLowerCase();
316
+ const embedding = new Float32Array(this.dimensions);
317
+ let hash = 0;
318
+ for (let i = 0; i < text.length; i++) { hash = ((hash << 5) - hash) + text.charCodeAt(i); hash = hash & hash; }
319
+ for (let i = 0; i < this.dimensions; i++) { embedding[i] = Math.sin(hash * (i + 1) * 0.001) * 0.5 + 0.5; }
320
+ let norm = 0;
321
+ for (let i = 0; i < this.dimensions; i++) norm += embedding[i] * embedding[i];
322
+ norm = Math.sqrt(norm);
323
+ for (let i = 0; i < this.dimensions; i++) embedding[i] /= norm;
324
+ return embedding;
325
+ }
326
+ }
327
+
328
+ // ============================================================================
329
+ // Plugin Definition
330
+ // ============================================================================
331
+
332
+ let libraryInstance: HookPatternLibrary | null = null;
333
+
334
+ async function getLibrary(): Promise<HookPatternLibrary> {
335
+ if (!libraryInstance) {
336
+ libraryInstance = new HookPatternLibrary();
337
+ await libraryInstance.initialize();
338
+ }
339
+ return libraryInstance;
340
+ }
341
+
342
+ export const hookPatternLibraryPlugin = new PluginBuilder('hook-pattern-library', '1.0.0')
343
+ .withDescription('Learn optimal hook patterns for file types using @ruvector/wasm')
344
+ .withAuthor('Claude Flow Team')
345
+ .withTags(['hooks', 'patterns', 'learning', 'ruvector', 'optimization'])
346
+ .withMCPTools([
347
+ new MCPToolBuilder('hook-recommend')
348
+ .withDescription('Get hook recommendations for a file type')
349
+ .addStringParam('fileType', 'File extension (ts, js, py, etc.)', { required: true })
350
+ .addStringParam('operation', 'Operation (write, edit, read, command)', { required: true })
351
+ .withHandler(async (params) => {
352
+ try {
353
+ const library = await getLibrary();
354
+ const recommendations = await library.recommend(params.fileType as string, params.operation as string);
355
+
356
+ if (recommendations.length === 0) {
357
+ return { content: [{ type: 'text', text: '🔍 No hook recommendations found.' }] };
358
+ }
359
+
360
+ const output = recommendations.map((r, i) =>
361
+ `**${i + 1}. ${r.hookName}** [${r.event}]\n` +
362
+ ` Priority: ${r.priority} | Effectiveness: ${(r.expectedEffectiveness * 100).toFixed(0)}%\n` +
363
+ ` ${r.reason}`
364
+ ).join('\n\n');
365
+
366
+ return {
367
+ content: [{ type: 'text', text: `🎣 **Hook Recommendations for .${params.fileType}:**\n\n${output}` }],
368
+ };
369
+ } catch (error) {
370
+ return {
371
+ content: [{ type: 'text', text: `❌ Error: ${error instanceof Error ? error.message : String(error)}` }],
372
+ isError: true,
373
+ };
374
+ }
375
+ })
376
+ .build(),
377
+
378
+ new MCPToolBuilder('hook-record')
379
+ .withDescription('Record a hook execution for learning')
380
+ .addStringParam('hookName', 'Hook name', { required: true })
381
+ .addStringParam('event', 'Hook event', { required: true })
382
+ .addStringParam('fileType', 'File type', { required: true })
383
+ .addStringParam('operation', 'Operation', { required: true })
384
+ .addBooleanParam('success', 'Was successful?', { required: true })
385
+ .addNumberParam('executionTime', 'Execution time in ms', { required: true })
386
+ .withHandler(async (params) => {
387
+ try {
388
+ const library = await getLibrary();
389
+ await library.recordExecution(
390
+ params.hookName as string,
391
+ params.event as HookEvent,
392
+ params.fileType as string,
393
+ params.operation as string,
394
+ params.success as boolean,
395
+ params.executionTime as number
396
+ );
397
+
398
+ return {
399
+ content: [{
400
+ type: 'text',
401
+ text: `✅ Recorded: ${params.hookName} (${params.success ? 'success' : 'failure'}, ${params.executionTime}ms)`,
402
+ }],
403
+ };
404
+ } catch (error) {
405
+ return {
406
+ content: [{ type: 'text', text: `❌ Error: ${error instanceof Error ? error.message : String(error)}` }],
407
+ isError: true,
408
+ };
409
+ }
410
+ })
411
+ .build(),
412
+
413
+ new MCPToolBuilder('hook-stats')
414
+ .withDescription('Get hook pattern library statistics')
415
+ .withHandler(async () => {
416
+ const library = await getLibrary();
417
+ const stats = library.getStats();
418
+
419
+ const topHooksOutput = stats.topHooks
420
+ .map((h, i) => ` ${i + 1}. ${h.name}: ${(h.effectiveness * 100).toFixed(0)}% (${h.usageCount} uses)`)
421
+ .join('\n');
422
+
423
+ const eventOutput = Object.entries(stats.byEvent)
424
+ .map(([e, c]) => ` • ${e}: ${c}`)
425
+ .join('\n');
426
+
427
+ return {
428
+ content: [{
429
+ type: 'text',
430
+ text: `📊 **Hook Pattern Library:**\n\n` +
431
+ `**Total Patterns:** ${stats.totalPatterns}\n` +
432
+ `**Avg Effectiveness:** ${(stats.avgEffectiveness * 100).toFixed(1)}%\n` +
433
+ `**Backend:** @ruvector/wasm HNSW\n\n` +
434
+ `**By Event:**\n${eventOutput || ' None'}\n\n` +
435
+ `**Top Hooks:**\n${topHooksOutput || ' None'}`,
436
+ }],
437
+ };
438
+ })
439
+ .build(),
440
+ ])
441
+ .withHooks([
442
+ new HookBuilder(HookEvent.PostToolCall)
443
+ .withName('hook-auto-record')
444
+ .withDescription('Auto-record hook executions')
445
+ .withPriority(HookPriority.Deferred)
446
+ .when((ctx) => {
447
+ const data = ctx.data as { hookExecution?: boolean } | undefined;
448
+ return data?.hookExecution === true;
449
+ })
450
+ .handle(async (ctx) => {
451
+ const data = ctx.data as {
452
+ hookName: string;
453
+ event: HookEvent;
454
+ fileType: string;
455
+ operation: string;
456
+ success: boolean;
457
+ executionTime: number;
458
+ };
459
+
460
+ try {
461
+ const library = await getLibrary();
462
+ await library.recordExecution(
463
+ data.hookName,
464
+ data.event,
465
+ data.fileType,
466
+ data.operation,
467
+ data.success,
468
+ data.executionTime
469
+ );
470
+ } catch {
471
+ // Silent fail
472
+ }
473
+
474
+ return { success: true };
475
+ })
476
+ .build(),
477
+ ])
478
+ .onInitialize(async (ctx) => {
479
+ ctx.logger.info('Hook Pattern Library initializing with @ruvector/wasm...');
480
+ const library = await getLibrary();
481
+ const stats = library.getStats();
482
+ ctx.logger.info(`Hook Pattern Library ready - ${stats.totalPatterns} patterns loaded`);
483
+ })
484
+ .build();
485
+
486
+ export default hookPatternLibraryPlugin;
@@ -0,0 +1,79 @@
1
+ /**
2
+ * RuVector Plugin Collection
3
+ *
4
+ * High-value plugins using @ruvector WASM packages for Claude Flow.
5
+ *
6
+ * @packageDocumentation
7
+ */
8
+
9
+ // Core plugins
10
+ export { reasoningBankPlugin, ReasoningBank } from './reasoning-bank.js';
11
+ export { semanticCodeSearchPlugin, SemanticCodeSearch } from './semantic-code-search.js';
12
+ export { sonaLearningPlugin, SONALearning } from './sona-learning.js';
13
+ export { intentRouterPlugin, IntentRouter } from './intent-router.js';
14
+ export { mcpToolOptimizerPlugin, MCPToolOptimizer } from './mcp-tool-optimizer.js';
15
+ export { hookPatternLibraryPlugin, HookPatternLibrary } from './hook-pattern-library.js';
16
+
17
+ // Types
18
+ export type {
19
+ ReasoningTrajectory,
20
+ ReasoningStep,
21
+ RetrievalResult,
22
+ VerdictJudgment,
23
+ } from './reasoning-bank.js';
24
+
25
+ export type {
26
+ CodeChunk,
27
+ CodeSearchResult,
28
+ CodeSearchOptions,
29
+ } from './semantic-code-search.js';
30
+
31
+ export type {
32
+ LearningPattern,
33
+ AdaptationResult,
34
+ SONAConfig,
35
+ } from './sona-learning.js';
36
+
37
+ export type {
38
+ Intent,
39
+ IntentHandler,
40
+ RouteResult,
41
+ RouterConfig,
42
+ } from './intent-router.js';
43
+
44
+ export type {
45
+ ToolUsagePattern,
46
+ ToolSequence,
47
+ OptimizationSuggestion,
48
+ } from './mcp-tool-optimizer.js';
49
+
50
+ export type {
51
+ HookPattern,
52
+ PatternMatch,
53
+ HookRecommendation,
54
+ } from './hook-pattern-library.js';
55
+
56
+ // Re-export classes for direct usage
57
+ export { ReasoningBank } from './reasoning-bank.js';
58
+ export { SemanticCodeSearch } from './semantic-code-search.js';
59
+ export { SONALearning } from './sona-learning.js';
60
+ export { IntentRouter } from './intent-router.js';
61
+ export { MCPToolOptimizer } from './mcp-tool-optimizer.js';
62
+ export { HookPatternLibrary } from './hook-pattern-library.js';
63
+
64
+ /**
65
+ * Register all RuVector plugins with the default registry.
66
+ */
67
+ export async function registerAllRuVectorPlugins(): Promise<void> {
68
+ const { getDefaultRegistry } = await import('../../src/index.js');
69
+ const registry = getDefaultRegistry();
70
+
71
+ await Promise.all([
72
+ import('./reasoning-bank.js').then(m => registry.register(m.reasoningBankPlugin)),
73
+ import('./semantic-code-search.js').then(m => registry.register(m.semanticCodeSearchPlugin)),
74
+ import('./sona-learning.js').then(m => registry.register(m.sonaLearningPlugin)),
75
+ import('./intent-router.js').then(m => registry.register(m.intentRouterPlugin)),
76
+ import('./mcp-tool-optimizer.js').then(m => registry.register(m.mcpToolOptimizerPlugin)),
77
+ import('./hook-pattern-library.js').then(m => registry.register(m.hookPatternLibraryPlugin)),
78
+ ]);
79
+ }