@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,568 @@
1
+ /**
2
+ * Dependency Graph
3
+ *
4
+ * Manages plugin dependencies with version constraint checking,
5
+ * safe unload detection, and topological sorting.
6
+ */
7
+
8
+ // ============================================================================
9
+ // Types
10
+ // ============================================================================
11
+
12
+ export interface PluginDependency {
13
+ name: string;
14
+ version: string; // Semver range: "^3.0.0", ">=2.1.0 <3.0.0", "*"
15
+ optional?: boolean; // Don't fail if missing
16
+ peerDependency?: boolean;
17
+ }
18
+
19
+ export interface DependencyNode {
20
+ name: string;
21
+ version: string;
22
+ dependencies: PluginDependency[];
23
+ }
24
+
25
+ export interface DependencyError {
26
+ type: 'missing' | 'version_mismatch' | 'circular';
27
+ plugin: string;
28
+ dependency?: string;
29
+ required?: string;
30
+ actual?: string;
31
+ message: string;
32
+ }
33
+
34
+ // ============================================================================
35
+ // Semver Utilities
36
+ // ============================================================================
37
+
38
+ /**
39
+ * Parse a semver version string.
40
+ */
41
+ export function parseVersion(version: string): { major: number; minor: number; patch: number } | null {
42
+ const match = version.match(/^(\d+)\.(\d+)\.(\d+)/);
43
+ if (!match) return null;
44
+ return {
45
+ major: parseInt(match[1], 10),
46
+ minor: parseInt(match[2], 10),
47
+ patch: parseInt(match[3], 10),
48
+ };
49
+ }
50
+
51
+ /**
52
+ * Compare two semver versions.
53
+ * Returns: -1 if a < b, 0 if a == b, 1 if a > b
54
+ */
55
+ export function compareVersions(a: string, b: string): number {
56
+ const va = parseVersion(a);
57
+ const vb = parseVersion(b);
58
+
59
+ if (!va || !vb) return 0;
60
+
61
+ if (va.major !== vb.major) return va.major < vb.major ? -1 : 1;
62
+ if (va.minor !== vb.minor) return va.minor < vb.minor ? -1 : 1;
63
+ if (va.patch !== vb.patch) return va.patch < vb.patch ? -1 : 1;
64
+
65
+ return 0;
66
+ }
67
+
68
+ /**
69
+ * Check if a version satisfies a semver range.
70
+ *
71
+ * Supported formats:
72
+ * - "*" - any version
73
+ * - "3.0.0" - exact version
74
+ * - "^3.0.0" - compatible with 3.x.x (major must match)
75
+ * - "~3.1.0" - approximately 3.1.x (major.minor must match)
76
+ * - ">=3.0.0" - greater than or equal
77
+ * - "<=3.0.0" - less than or equal
78
+ * - ">3.0.0" - greater than
79
+ * - "<3.0.0" - less than
80
+ * - ">=2.0.0 <3.0.0" - range (space-separated)
81
+ */
82
+ export function satisfiesVersion(range: string, version: string): boolean {
83
+ const trimmed = range.trim();
84
+
85
+ // Wildcard
86
+ if (trimmed === '*' || trimmed === '') return true;
87
+
88
+ // Parse actual version
89
+ const actual = parseVersion(version);
90
+ if (!actual) return false;
91
+
92
+ // Handle space-separated ranges (AND logic)
93
+ if (trimmed.includes(' ')) {
94
+ const parts = trimmed.split(/\s+/);
95
+ return parts.every(part => satisfiesVersion(part, version));
96
+ }
97
+
98
+ // Caret range: ^3.0.0 means >=3.0.0 <4.0.0
99
+ if (trimmed.startsWith('^')) {
100
+ const required = parseVersion(trimmed.slice(1));
101
+ if (!required) return false;
102
+
103
+ return (
104
+ actual.major === required.major &&
105
+ (actual.minor > required.minor ||
106
+ (actual.minor === required.minor && actual.patch >= required.patch))
107
+ );
108
+ }
109
+
110
+ // Tilde range: ~3.1.0 means >=3.1.0 <3.2.0
111
+ if (trimmed.startsWith('~')) {
112
+ const required = parseVersion(trimmed.slice(1));
113
+ if (!required) return false;
114
+
115
+ return (
116
+ actual.major === required.major &&
117
+ actual.minor === required.minor &&
118
+ actual.patch >= required.patch
119
+ );
120
+ }
121
+
122
+ // Greater than or equal: >=3.0.0
123
+ if (trimmed.startsWith('>=')) {
124
+ const required = parseVersion(trimmed.slice(2));
125
+ if (!required) return false;
126
+ return compareVersions(version, trimmed.slice(2)) >= 0;
127
+ }
128
+
129
+ // Less than or equal: <=3.0.0
130
+ if (trimmed.startsWith('<=')) {
131
+ const required = parseVersion(trimmed.slice(2));
132
+ if (!required) return false;
133
+ return compareVersions(version, trimmed.slice(2)) <= 0;
134
+ }
135
+
136
+ // Greater than: >3.0.0
137
+ if (trimmed.startsWith('>')) {
138
+ const required = parseVersion(trimmed.slice(1));
139
+ if (!required) return false;
140
+ return compareVersions(version, trimmed.slice(1)) > 0;
141
+ }
142
+
143
+ // Less than: <3.0.0
144
+ if (trimmed.startsWith('<')) {
145
+ const required = parseVersion(trimmed.slice(1));
146
+ if (!required) return false;
147
+ return compareVersions(version, trimmed.slice(1)) < 0;
148
+ }
149
+
150
+ // Exact match
151
+ const required = parseVersion(trimmed);
152
+ if (!required) return false;
153
+ return compareVersions(version, trimmed) === 0;
154
+ }
155
+
156
+ // ============================================================================
157
+ // Dependency Graph
158
+ // ============================================================================
159
+
160
+ /**
161
+ * Dependency graph for plugin management.
162
+ *
163
+ * Features:
164
+ * - Version constraint validation
165
+ * - Circular dependency detection
166
+ * - Safe unload checking (no dependents)
167
+ * - Topological sort for load order
168
+ * - Depth-level grouping for parallel initialization
169
+ */
170
+ export class DependencyGraph {
171
+ // Plugin name -> node data
172
+ private nodes = new Map<string, DependencyNode>();
173
+
174
+ // Forward edges: plugin -> plugins it depends on
175
+ private dependencies = new Map<string, Set<string>>();
176
+
177
+ // Reverse edges: plugin -> plugins that depend on it
178
+ private dependents = new Map<string, Set<string>>();
179
+
180
+ // =========================================================================
181
+ // Node Management
182
+ // =========================================================================
183
+
184
+ /**
185
+ * Add a plugin to the graph.
186
+ */
187
+ addPlugin(name: string, version: string, dependencies: PluginDependency[] = []): void {
188
+ // Store node data
189
+ this.nodes.set(name, { name, version, dependencies });
190
+
191
+ // Initialize edge sets
192
+ if (!this.dependencies.has(name)) {
193
+ this.dependencies.set(name, new Set());
194
+ }
195
+ if (!this.dependents.has(name)) {
196
+ this.dependents.set(name, new Set());
197
+ }
198
+
199
+ // Add edges
200
+ for (const dep of dependencies) {
201
+ this.dependencies.get(name)!.add(dep.name);
202
+
203
+ // Ensure dependent set exists
204
+ if (!this.dependents.has(dep.name)) {
205
+ this.dependents.set(dep.name, new Set());
206
+ }
207
+ this.dependents.get(dep.name)!.add(name);
208
+ }
209
+ }
210
+
211
+ /**
212
+ * Remove a plugin from the graph.
213
+ */
214
+ removePlugin(name: string): void {
215
+ const node = this.nodes.get(name);
216
+ if (!node) return;
217
+
218
+ // Remove forward edges
219
+ const deps = this.dependencies.get(name) ?? new Set();
220
+ for (const dep of deps) {
221
+ this.dependents.get(dep)?.delete(name);
222
+ }
223
+ this.dependencies.delete(name);
224
+
225
+ // Remove reverse edges
226
+ const dependers = this.dependents.get(name) ?? new Set();
227
+ for (const depender of dependers) {
228
+ this.dependencies.get(depender)?.delete(name);
229
+ }
230
+ this.dependents.delete(name);
231
+
232
+ // Remove node
233
+ this.nodes.delete(name);
234
+ }
235
+
236
+ /**
237
+ * Check if a plugin exists in the graph.
238
+ */
239
+ hasPlugin(name: string): boolean {
240
+ return this.nodes.has(name);
241
+ }
242
+
243
+ /**
244
+ * Get plugin version.
245
+ */
246
+ getVersion(name: string): string | undefined {
247
+ return this.nodes.get(name)?.version;
248
+ }
249
+
250
+ // =========================================================================
251
+ // Dependency Queries
252
+ // =========================================================================
253
+
254
+ /**
255
+ * Get direct dependencies of a plugin.
256
+ */
257
+ getDependencies(name: string): string[] {
258
+ return Array.from(this.dependencies.get(name) ?? []);
259
+ }
260
+
261
+ /**
262
+ * Get direct dependents of a plugin (plugins that depend on it).
263
+ */
264
+ getDependents(name: string): string[] {
265
+ return Array.from(this.dependents.get(name) ?? []);
266
+ }
267
+
268
+ /**
269
+ * Get all transitive dependencies of a plugin.
270
+ */
271
+ getAllDependencies(name: string): string[] {
272
+ const visited = new Set<string>();
273
+ const result: string[] = [];
274
+
275
+ const visit = (current: string): void => {
276
+ if (visited.has(current)) return;
277
+ visited.add(current);
278
+
279
+ const deps = this.dependencies.get(current) ?? new Set();
280
+ for (const dep of deps) {
281
+ visit(dep);
282
+ if (!result.includes(dep)) {
283
+ result.push(dep);
284
+ }
285
+ }
286
+ };
287
+
288
+ visit(name);
289
+ return result;
290
+ }
291
+
292
+ /**
293
+ * Get all transitive dependents of a plugin.
294
+ */
295
+ getAllDependents(name: string): string[] {
296
+ const visited = new Set<string>();
297
+ const result: string[] = [];
298
+
299
+ const visit = (current: string): void => {
300
+ if (visited.has(current)) return;
301
+ visited.add(current);
302
+
303
+ const deps = this.dependents.get(current) ?? new Set();
304
+ for (const dep of deps) {
305
+ visit(dep);
306
+ if (!result.includes(dep)) {
307
+ result.push(dep);
308
+ }
309
+ }
310
+ };
311
+
312
+ visit(name);
313
+ return result;
314
+ }
315
+
316
+ // =========================================================================
317
+ // Safe Operations
318
+ // =========================================================================
319
+
320
+ /**
321
+ * Check if a plugin can be safely removed (no dependents).
322
+ */
323
+ canSafelyRemove(name: string): boolean {
324
+ const dependents = this.getDependents(name);
325
+ return dependents.length === 0;
326
+ }
327
+
328
+ /**
329
+ * Get the order to remove plugins for cascade unload.
330
+ * Returns plugins in reverse dependency order (dependents first).
331
+ */
332
+ getRemovalOrder(name: string): string[] {
333
+ const allDependents = this.getAllDependents(name);
334
+
335
+ // Sort by reverse topological order
336
+ // Plugins that depend on others should be removed first
337
+ const sorted: string[] = [];
338
+ const visited = new Set<string>();
339
+
340
+ const visit = (current: string): void => {
341
+ if (visited.has(current)) return;
342
+ visited.add(current);
343
+
344
+ // Visit dependents first (reverse order)
345
+ const deps = this.dependents.get(current) ?? new Set();
346
+ for (const dep of deps) {
347
+ if (allDependents.includes(dep)) {
348
+ visit(dep);
349
+ }
350
+ }
351
+
352
+ sorted.push(current);
353
+ };
354
+
355
+ visit(name);
356
+ return sorted;
357
+ }
358
+
359
+ // =========================================================================
360
+ // Validation
361
+ // =========================================================================
362
+
363
+ /**
364
+ * Validate all dependencies and return errors.
365
+ */
366
+ validate(): DependencyError[] {
367
+ const errors: DependencyError[] = [];
368
+
369
+ for (const [name, node] of this.nodes) {
370
+ for (const dep of node.dependencies) {
371
+ // Check if dependency exists
372
+ const depNode = this.nodes.get(dep.name);
373
+
374
+ if (!depNode) {
375
+ if (!dep.optional) {
376
+ errors.push({
377
+ type: 'missing',
378
+ plugin: name,
379
+ dependency: dep.name,
380
+ required: dep.version,
381
+ message: `Plugin ${name} requires ${dep.name}@${dep.version} but it is not installed`,
382
+ });
383
+ }
384
+ continue;
385
+ }
386
+
387
+ // Check version constraint
388
+ if (!satisfiesVersion(dep.version, depNode.version)) {
389
+ errors.push({
390
+ type: 'version_mismatch',
391
+ plugin: name,
392
+ dependency: dep.name,
393
+ required: dep.version,
394
+ actual: depNode.version,
395
+ message: `Plugin ${name} requires ${dep.name}@${dep.version} but found ${depNode.version}`,
396
+ });
397
+ }
398
+ }
399
+ }
400
+
401
+ // Check for circular dependencies
402
+ const circular = this.detectCircular();
403
+ for (const cycle of circular) {
404
+ errors.push({
405
+ type: 'circular',
406
+ plugin: cycle[0],
407
+ message: `Circular dependency detected: ${cycle.join(' -> ')}`,
408
+ });
409
+ }
410
+
411
+ return errors;
412
+ }
413
+
414
+ /**
415
+ * Detect circular dependencies.
416
+ * Returns array of cycles (each cycle is an array of plugin names).
417
+ */
418
+ detectCircular(): string[][] {
419
+ const cycles: string[][] = [];
420
+ const visited = new Set<string>();
421
+ const recursionStack = new Set<string>();
422
+ const path: string[] = [];
423
+
424
+ const dfs = (name: string): void => {
425
+ visited.add(name);
426
+ recursionStack.add(name);
427
+ path.push(name);
428
+
429
+ const deps = this.dependencies.get(name) ?? new Set();
430
+ for (const dep of deps) {
431
+ if (!visited.has(dep)) {
432
+ dfs(dep);
433
+ } else if (recursionStack.has(dep)) {
434
+ // Found a cycle
435
+ const cycleStart = path.indexOf(dep);
436
+ const cycle = [...path.slice(cycleStart), dep];
437
+ cycles.push(cycle);
438
+ }
439
+ }
440
+
441
+ path.pop();
442
+ recursionStack.delete(name);
443
+ };
444
+
445
+ for (const name of this.nodes.keys()) {
446
+ if (!visited.has(name)) {
447
+ dfs(name);
448
+ }
449
+ }
450
+
451
+ return cycles;
452
+ }
453
+
454
+ // =========================================================================
455
+ // Load Order
456
+ // =========================================================================
457
+
458
+ /**
459
+ * Get topological sort order for loading plugins.
460
+ * Dependencies come before dependents.
461
+ */
462
+ getLoadOrder(): string[] {
463
+ const visited = new Set<string>();
464
+ const order: string[] = [];
465
+
466
+ const visit = (name: string): void => {
467
+ if (visited.has(name)) return;
468
+ visited.add(name);
469
+
470
+ // Visit dependencies first
471
+ const deps = this.dependencies.get(name) ?? new Set();
472
+ for (const dep of deps) {
473
+ if (this.nodes.has(dep)) {
474
+ visit(dep);
475
+ }
476
+ }
477
+
478
+ order.push(name);
479
+ };
480
+
481
+ for (const name of this.nodes.keys()) {
482
+ visit(name);
483
+ }
484
+
485
+ return order;
486
+ }
487
+
488
+ /**
489
+ * Get plugins grouped by dependency depth.
490
+ * Level 0 = no dependencies, Level 1 = depends only on level 0, etc.
491
+ *
492
+ * Useful for parallel initialization: init all level N before starting level N+1.
493
+ */
494
+ getDepthLevels(): string[][] {
495
+ const depths = new Map<string, number>();
496
+ const order = this.getLoadOrder();
497
+
498
+ // Calculate depth for each plugin
499
+ for (const name of order) {
500
+ const deps = this.dependencies.get(name) ?? new Set();
501
+ let maxDepth = -1;
502
+
503
+ for (const dep of deps) {
504
+ const depDepth = depths.get(dep);
505
+ if (depDepth !== undefined && depDepth > maxDepth) {
506
+ maxDepth = depDepth;
507
+ }
508
+ }
509
+
510
+ depths.set(name, maxDepth + 1);
511
+ }
512
+
513
+ // Group by depth
514
+ const levels: string[][] = [];
515
+ for (const [name, depth] of depths) {
516
+ while (levels.length <= depth) {
517
+ levels.push([]);
518
+ }
519
+ levels[depth].push(name);
520
+ }
521
+
522
+ return levels;
523
+ }
524
+
525
+ // =========================================================================
526
+ // Utilities
527
+ // =========================================================================
528
+
529
+ /**
530
+ * Get all plugin names.
531
+ */
532
+ getPluginNames(): string[] {
533
+ return Array.from(this.nodes.keys());
534
+ }
535
+
536
+ /**
537
+ * Get plugin count.
538
+ */
539
+ size(): number {
540
+ return this.nodes.size;
541
+ }
542
+
543
+ /**
544
+ * Clear the graph.
545
+ */
546
+ clear(): void {
547
+ this.nodes.clear();
548
+ this.dependencies.clear();
549
+ this.dependents.clear();
550
+ }
551
+
552
+ /**
553
+ * Export graph state for debugging.
554
+ */
555
+ toJSON(): object {
556
+ return {
557
+ nodes: Array.from(this.nodes.entries()).map(([name, node]) => ({
558
+ name,
559
+ version: node.version,
560
+ dependencies: node.dependencies,
561
+ })),
562
+ edges: Array.from(this.dependencies.entries()).map(([from, tos]) => ({
563
+ from,
564
+ to: Array.from(tos),
565
+ })),
566
+ };
567
+ }
568
+ }