@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,604 @@
1
+ /**
2
+ * Plugin Registry
3
+ *
4
+ * Manages plugin lifecycle, dependency resolution, and extension point collection.
5
+ */
6
+
7
+ import { EventEmitter } from 'events';
8
+ import type {
9
+ PluginContext,
10
+ PluginConfig,
11
+ PluginMetadata,
12
+ IEventBus,
13
+ ILogger,
14
+ ServiceContainer,
15
+ AgentTypeDefinition,
16
+ TaskTypeDefinition,
17
+ MCPToolDefinition,
18
+ CLICommandDefinition,
19
+ MemoryBackendFactory,
20
+ HookDefinition,
21
+ WorkerDefinition,
22
+ LLMProviderDefinition,
23
+ HealthCheckResult,
24
+ } from '../types/index.js';
25
+ import type { IPlugin, PluginFactory } from '../core/plugin-interface.js';
26
+ import { validatePlugin, PLUGIN_EVENTS } from '../core/plugin-interface.js';
27
+
28
+ // ============================================================================
29
+ // Registry Types
30
+ // ============================================================================
31
+
32
+ export interface PluginRegistryConfig {
33
+ coreVersion: string;
34
+ dataDir: string;
35
+ logger?: ILogger;
36
+ eventBus?: IEventBus;
37
+ defaultConfig?: Partial<PluginConfig>;
38
+ maxPlugins?: number;
39
+ loadTimeout?: number;
40
+ }
41
+
42
+ export interface PluginEntry {
43
+ plugin: IPlugin;
44
+ config: PluginConfig;
45
+ loadTime: Date;
46
+ initTime?: Date;
47
+ error?: string;
48
+ }
49
+
50
+ export interface RegistryStats {
51
+ total: number;
52
+ initialized: number;
53
+ failed: number;
54
+ agentTypes: number;
55
+ taskTypes: number;
56
+ mcpTools: number;
57
+ cliCommands: number;
58
+ hooks: number;
59
+ workers: number;
60
+ providers: number;
61
+ }
62
+
63
+ // ============================================================================
64
+ // Default Implementations
65
+ // ============================================================================
66
+
67
+ class DefaultEventBus implements IEventBus {
68
+ private emitter = new EventEmitter();
69
+
70
+ emit(event: string, data?: unknown): void {
71
+ this.emitter.emit(event, data);
72
+ }
73
+
74
+ on(event: string, handler: (data?: unknown) => void | Promise<void>): () => void {
75
+ this.emitter.on(event, handler);
76
+ return () => this.off(event, handler);
77
+ }
78
+
79
+ off(event: string, handler: (data?: unknown) => void | Promise<void>): void {
80
+ this.emitter.off(event, handler);
81
+ }
82
+
83
+ once(event: string, handler: (data?: unknown) => void | Promise<void>): () => void {
84
+ this.emitter.once(event, handler);
85
+ return () => this.off(event, handler);
86
+ }
87
+ }
88
+
89
+ class DefaultLogger implements ILogger {
90
+ private context: Record<string, unknown> = {};
91
+
92
+ constructor(context?: Record<string, unknown>) {
93
+ if (context) this.context = context;
94
+ }
95
+
96
+ debug(message: string, ...args: unknown[]): void {
97
+ console.debug(`[DEBUG]`, message, ...args, this.context);
98
+ }
99
+
100
+ info(message: string, ...args: unknown[]): void {
101
+ console.info(`[INFO]`, message, ...args, this.context);
102
+ }
103
+
104
+ warn(message: string, ...args: unknown[]): void {
105
+ console.warn(`[WARN]`, message, ...args, this.context);
106
+ }
107
+
108
+ error(message: string, ...args: unknown[]): void {
109
+ console.error(`[ERROR]`, message, ...args, this.context);
110
+ }
111
+
112
+ child(context: Record<string, unknown>): ILogger {
113
+ return new DefaultLogger({ ...this.context, ...context });
114
+ }
115
+ }
116
+
117
+ class DefaultServiceContainer implements ServiceContainer {
118
+ private services = new Map<string, unknown>();
119
+
120
+ get<T>(key: string): T | undefined {
121
+ return this.services.get(key) as T | undefined;
122
+ }
123
+
124
+ set<T>(key: string, value: T): void {
125
+ this.services.set(key, value);
126
+ }
127
+
128
+ has(key: string): boolean {
129
+ return this.services.has(key);
130
+ }
131
+
132
+ delete(key: string): boolean {
133
+ return this.services.delete(key);
134
+ }
135
+ }
136
+
137
+ // ============================================================================
138
+ // Plugin Registry
139
+ // ============================================================================
140
+
141
+ /**
142
+ * Central registry for plugin management.
143
+ *
144
+ * Features:
145
+ * - Plugin loading and unloading
146
+ * - Dependency resolution
147
+ * - Extension point collection
148
+ * - Health monitoring
149
+ * - Lifecycle management
150
+ */
151
+ export class PluginRegistry extends EventEmitter {
152
+ // =========================================================================
153
+ // Properties
154
+ // =========================================================================
155
+
156
+ private readonly plugins = new Map<string, PluginEntry>();
157
+ private readonly config: PluginRegistryConfig;
158
+ private readonly logger: ILogger;
159
+ private readonly eventBus: IEventBus;
160
+ private readonly services: ServiceContainer;
161
+ private initialized = false;
162
+
163
+ // Extension point caches
164
+ private agentTypesCache: AgentTypeDefinition[] = [];
165
+ private taskTypesCache: TaskTypeDefinition[] = [];
166
+ private mcpToolsCache: MCPToolDefinition[] = [];
167
+ private cliCommandsCache: CLICommandDefinition[] = [];
168
+ private memoryBackendsCache: MemoryBackendFactory[] = [];
169
+ private hooksCache: HookDefinition[] = [];
170
+ private workersCache: WorkerDefinition[] = [];
171
+ private providersCache: LLMProviderDefinition[] = [];
172
+
173
+ // =========================================================================
174
+ // Constructor
175
+ // =========================================================================
176
+
177
+ constructor(config: PluginRegistryConfig) {
178
+ super();
179
+ this.config = config;
180
+ this.logger = config.logger ?? new DefaultLogger({ component: 'PluginRegistry' });
181
+ this.eventBus = config.eventBus ?? new DefaultEventBus();
182
+ this.services = new DefaultServiceContainer();
183
+
184
+ // Register self in services
185
+ this.services.set('pluginRegistry', this);
186
+ }
187
+
188
+ // =========================================================================
189
+ // Plugin Loading
190
+ // =========================================================================
191
+
192
+ /**
193
+ * Register a plugin.
194
+ */
195
+ async register(
196
+ plugin: IPlugin | PluginFactory,
197
+ config?: Partial<PluginConfig>
198
+ ): Promise<void> {
199
+ // Resolve factory if needed
200
+ const resolvedPlugin = typeof plugin === 'function' ? await plugin() : plugin;
201
+
202
+ // Validate plugin
203
+ if (!validatePlugin(resolvedPlugin)) {
204
+ throw new Error('Invalid plugin: does not implement IPlugin interface');
205
+ }
206
+
207
+ const name = resolvedPlugin.metadata.name;
208
+
209
+ // Check for duplicates
210
+ if (this.plugins.has(name)) {
211
+ throw new Error(`Plugin ${name} already registered`);
212
+ }
213
+
214
+ // Check max plugins
215
+ if (this.config.maxPlugins && this.plugins.size >= this.config.maxPlugins) {
216
+ throw new Error(`Maximum plugin limit (${this.config.maxPlugins}) reached`);
217
+ }
218
+
219
+ // Create config
220
+ const pluginConfig: PluginConfig = {
221
+ enabled: true,
222
+ priority: 50,
223
+ settings: {},
224
+ ...this.config.defaultConfig,
225
+ ...config,
226
+ };
227
+
228
+ // Store entry
229
+ const entry: PluginEntry = {
230
+ plugin: resolvedPlugin,
231
+ config: pluginConfig,
232
+ loadTime: new Date(),
233
+ };
234
+
235
+ this.plugins.set(name, entry);
236
+ this.eventBus.emit(PLUGIN_EVENTS.LOADED, { plugin: name });
237
+ this.logger.info(`Plugin registered: ${name} v${resolvedPlugin.metadata.version}`);
238
+ }
239
+
240
+ /**
241
+ * Unregister a plugin.
242
+ */
243
+ async unregister(name: string): Promise<void> {
244
+ const entry = this.plugins.get(name);
245
+ if (!entry) {
246
+ throw new Error(`Plugin ${name} not found`);
247
+ }
248
+
249
+ // Shutdown if initialized
250
+ if (entry.plugin.state === 'initialized') {
251
+ await entry.plugin.shutdown();
252
+ }
253
+
254
+ this.plugins.delete(name);
255
+ this.invalidateCaches();
256
+ this.logger.info(`Plugin unregistered: ${name}`);
257
+ }
258
+
259
+ // =========================================================================
260
+ // Initialization
261
+ // =========================================================================
262
+
263
+ /**
264
+ * Initialize all registered plugins.
265
+ */
266
+ async initialize(): Promise<void> {
267
+ if (this.initialized) {
268
+ throw new Error('Registry already initialized');
269
+ }
270
+
271
+ // Resolve dependencies and get load order
272
+ const loadOrder = this.resolveDependencies();
273
+
274
+ // Initialize plugins in order
275
+ for (const name of loadOrder) {
276
+ const entry = this.plugins.get(name)!;
277
+ if (!entry.config.enabled) {
278
+ this.logger.info(`Plugin ${name} is disabled, skipping initialization`);
279
+ continue;
280
+ }
281
+
282
+ try {
283
+ const context = this.createPluginContext(entry);
284
+ await this.initializeWithTimeout(entry.plugin, context);
285
+ entry.initTime = new Date();
286
+ this.collectExtensionPoints(entry.plugin);
287
+ this.logger.info(`Plugin initialized: ${name}`);
288
+ } catch (error) {
289
+ entry.error = error instanceof Error ? error.message : String(error);
290
+ this.logger.error(`Failed to initialize plugin ${name}: ${entry.error}`);
291
+ // Continue with other plugins
292
+ }
293
+ }
294
+
295
+ this.initialized = true;
296
+ this.logger.info(`Registry initialized with ${this.plugins.size} plugins`);
297
+ }
298
+
299
+ /**
300
+ * Shutdown all plugins.
301
+ */
302
+ async shutdown(): Promise<void> {
303
+ // Shutdown in reverse order
304
+ const names = Array.from(this.plugins.keys()).reverse();
305
+
306
+ for (const name of names) {
307
+ const entry = this.plugins.get(name)!;
308
+ if (entry.plugin.state === 'initialized') {
309
+ try {
310
+ await entry.plugin.shutdown();
311
+ this.logger.info(`Plugin shutdown: ${name}`);
312
+ } catch (error) {
313
+ this.logger.error(`Error shutting down plugin ${name}: ${error}`);
314
+ }
315
+ }
316
+ }
317
+
318
+ this.invalidateCaches();
319
+ this.initialized = false;
320
+ }
321
+
322
+ // =========================================================================
323
+ // Dependency Resolution
324
+ // =========================================================================
325
+
326
+ /**
327
+ * Resolve dependencies and return load order.
328
+ */
329
+ private resolveDependencies(): string[] {
330
+ const visited = new Set<string>();
331
+ const visiting = new Set<string>();
332
+ const order: string[] = [];
333
+
334
+ const visit = (name: string): void => {
335
+ if (visited.has(name)) return;
336
+ if (visiting.has(name)) {
337
+ throw new Error(`Circular dependency detected: ${name}`);
338
+ }
339
+
340
+ const entry = this.plugins.get(name);
341
+ if (!entry) {
342
+ throw new Error(`Missing dependency: ${name}`);
343
+ }
344
+
345
+ visiting.add(name);
346
+
347
+ const deps = entry.plugin.metadata.dependencies ?? [];
348
+ for (const dep of deps) {
349
+ visit(dep);
350
+ }
351
+
352
+ visiting.delete(name);
353
+ visited.add(name);
354
+ order.push(name);
355
+ };
356
+
357
+ for (const name of this.plugins.keys()) {
358
+ visit(name);
359
+ }
360
+
361
+ return order;
362
+ }
363
+
364
+ // =========================================================================
365
+ // Extension Points
366
+ // =========================================================================
367
+
368
+ /**
369
+ * Collect extension points from a plugin.
370
+ */
371
+ private collectExtensionPoints(plugin: IPlugin): void {
372
+ if (plugin.registerAgentTypes) {
373
+ const types = plugin.registerAgentTypes();
374
+ if (types) this.agentTypesCache.push(...types);
375
+ }
376
+
377
+ if (plugin.registerTaskTypes) {
378
+ const types = plugin.registerTaskTypes();
379
+ if (types) this.taskTypesCache.push(...types);
380
+ }
381
+
382
+ if (plugin.registerMCPTools) {
383
+ const tools = plugin.registerMCPTools();
384
+ if (tools) this.mcpToolsCache.push(...tools);
385
+ }
386
+
387
+ if (plugin.registerCLICommands) {
388
+ const commands = plugin.registerCLICommands();
389
+ if (commands) this.cliCommandsCache.push(...commands);
390
+ }
391
+
392
+ if (plugin.registerMemoryBackends) {
393
+ const backends = plugin.registerMemoryBackends();
394
+ if (backends) this.memoryBackendsCache.push(...backends);
395
+ }
396
+
397
+ if (plugin.registerHooks) {
398
+ const hooks = plugin.registerHooks();
399
+ if (hooks) this.hooksCache.push(...hooks);
400
+ }
401
+
402
+ if (plugin.registerWorkers) {
403
+ const workers = plugin.registerWorkers();
404
+ if (workers) this.workersCache.push(...workers);
405
+ }
406
+
407
+ if (plugin.registerProviders) {
408
+ const providers = plugin.registerProviders();
409
+ if (providers) this.providersCache.push(...providers);
410
+ }
411
+ }
412
+
413
+ /**
414
+ * Invalidate extension point caches.
415
+ */
416
+ private invalidateCaches(): void {
417
+ this.agentTypesCache = [];
418
+ this.taskTypesCache = [];
419
+ this.mcpToolsCache = [];
420
+ this.cliCommandsCache = [];
421
+ this.memoryBackendsCache = [];
422
+ this.hooksCache = [];
423
+ this.workersCache = [];
424
+ this.providersCache = [];
425
+
426
+ // Recollect from initialized plugins
427
+ for (const entry of this.plugins.values()) {
428
+ if (entry.plugin.state === 'initialized') {
429
+ this.collectExtensionPoints(entry.plugin);
430
+ }
431
+ }
432
+ }
433
+
434
+ // =========================================================================
435
+ // Getters
436
+ // =========================================================================
437
+
438
+ getAgentTypes(): AgentTypeDefinition[] {
439
+ return [...this.agentTypesCache];
440
+ }
441
+
442
+ getTaskTypes(): TaskTypeDefinition[] {
443
+ return [...this.taskTypesCache];
444
+ }
445
+
446
+ getMCPTools(): MCPToolDefinition[] {
447
+ return [...this.mcpToolsCache];
448
+ }
449
+
450
+ getCLICommands(): CLICommandDefinition[] {
451
+ return [...this.cliCommandsCache];
452
+ }
453
+
454
+ getMemoryBackends(): MemoryBackendFactory[] {
455
+ return [...this.memoryBackendsCache];
456
+ }
457
+
458
+ getHooks(): HookDefinition[] {
459
+ return [...this.hooksCache];
460
+ }
461
+
462
+ getWorkers(): WorkerDefinition[] {
463
+ return [...this.workersCache];
464
+ }
465
+
466
+ getProviders(): LLMProviderDefinition[] {
467
+ return [...this.providersCache];
468
+ }
469
+
470
+ getPlugin(name: string): IPlugin | undefined {
471
+ return this.plugins.get(name)?.plugin;
472
+ }
473
+
474
+ getPluginEntry(name: string): PluginEntry | undefined {
475
+ return this.plugins.get(name);
476
+ }
477
+
478
+ listPlugins(): PluginMetadata[] {
479
+ return Array.from(this.plugins.values()).map(e => e.plugin.metadata);
480
+ }
481
+
482
+ // =========================================================================
483
+ // Health Check
484
+ // =========================================================================
485
+
486
+ /**
487
+ * Run health checks on all plugins.
488
+ */
489
+ async healthCheck(): Promise<Map<string, HealthCheckResult>> {
490
+ const results = new Map<string, HealthCheckResult>();
491
+
492
+ for (const [name, entry] of this.plugins) {
493
+ if (entry.plugin.state !== 'initialized') {
494
+ results.set(name, {
495
+ healthy: false,
496
+ status: 'unhealthy',
497
+ message: `Plugin not initialized: ${entry.plugin.state}`,
498
+ checks: {},
499
+ timestamp: new Date(),
500
+ });
501
+ continue;
502
+ }
503
+
504
+ try {
505
+ if (entry.plugin.healthCheck) {
506
+ results.set(name, await entry.plugin.healthCheck());
507
+ } else {
508
+ results.set(name, {
509
+ healthy: true,
510
+ status: 'healthy',
511
+ checks: {},
512
+ timestamp: new Date(),
513
+ });
514
+ }
515
+ } catch (error) {
516
+ results.set(name, {
517
+ healthy: false,
518
+ status: 'unhealthy',
519
+ message: error instanceof Error ? error.message : String(error),
520
+ checks: {},
521
+ timestamp: new Date(),
522
+ });
523
+ }
524
+ }
525
+
526
+ return results;
527
+ }
528
+
529
+ // =========================================================================
530
+ // Stats
531
+ // =========================================================================
532
+
533
+ getStats(): RegistryStats {
534
+ let initialized = 0;
535
+ let failed = 0;
536
+
537
+ for (const entry of this.plugins.values()) {
538
+ if (entry.plugin.state === 'initialized') initialized++;
539
+ if (entry.plugin.state === 'error' || entry.error) failed++;
540
+ }
541
+
542
+ return {
543
+ total: this.plugins.size,
544
+ initialized,
545
+ failed,
546
+ agentTypes: this.agentTypesCache.length,
547
+ taskTypes: this.taskTypesCache.length,
548
+ mcpTools: this.mcpToolsCache.length,
549
+ cliCommands: this.cliCommandsCache.length,
550
+ hooks: this.hooksCache.length,
551
+ workers: this.workersCache.length,
552
+ providers: this.providersCache.length,
553
+ };
554
+ }
555
+
556
+ // =========================================================================
557
+ // Helpers
558
+ // =========================================================================
559
+
560
+ private createPluginContext(entry: PluginEntry): PluginContext {
561
+ return {
562
+ config: entry.config,
563
+ eventBus: this.eventBus,
564
+ logger: this.logger.child({ plugin: entry.plugin.metadata.name }),
565
+ services: this.services,
566
+ coreVersion: this.config.coreVersion,
567
+ dataDir: this.config.dataDir,
568
+ };
569
+ }
570
+
571
+ private async initializeWithTimeout(
572
+ plugin: IPlugin,
573
+ context: PluginContext
574
+ ): Promise<void> {
575
+ const timeout = this.config.loadTimeout ?? 30000;
576
+
577
+ await Promise.race([
578
+ plugin.initialize(context),
579
+ new Promise<never>((_, reject) =>
580
+ setTimeout(() => reject(new Error('Initialization timeout')), timeout)
581
+ ),
582
+ ]);
583
+ }
584
+ }
585
+
586
+ // ============================================================================
587
+ // Default Registry Instance
588
+ // ============================================================================
589
+
590
+ let defaultRegistry: PluginRegistry | null = null;
591
+
592
+ export function getDefaultRegistry(): PluginRegistry {
593
+ if (!defaultRegistry) {
594
+ defaultRegistry = new PluginRegistry({
595
+ coreVersion: '3.0.0',
596
+ dataDir: process.cwd(),
597
+ });
598
+ }
599
+ return defaultRegistry;
600
+ }
601
+
602
+ export function setDefaultRegistry(registry: PluginRegistry): void {
603
+ defaultRegistry = registry;
604
+ }