@sparkleideas/plugins 3.0.0-alpha.8

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,416 @@
1
+ /**
2
+ * Base Plugin Implementation
3
+ *
4
+ * Abstract base class that provides common plugin functionality.
5
+ * Plugins should extend this class for easier implementation.
6
+ */
7
+
8
+ import { EventEmitter } from 'events';
9
+ import type {
10
+ PluginMetadata,
11
+ PluginContext,
12
+ PluginLifecycleState,
13
+ PluginConfig,
14
+ ILogger,
15
+ IEventBus,
16
+ ServiceContainer,
17
+ AgentTypeDefinition,
18
+ TaskTypeDefinition,
19
+ MCPToolDefinition,
20
+ CLICommandDefinition,
21
+ MemoryBackendFactory,
22
+ HookDefinition,
23
+ WorkerDefinition,
24
+ LLMProviderDefinition,
25
+ HealthCheckResult,
26
+ } from '../types/index.js';
27
+ import type { IPlugin } from './plugin-interface.js';
28
+ import { PLUGIN_EVENTS } from './plugin-interface.js';
29
+
30
+ // ============================================================================
31
+ // Base Plugin
32
+ // ============================================================================
33
+
34
+ /**
35
+ * Abstract base class for plugins.
36
+ *
37
+ * Provides:
38
+ * - Lifecycle management
39
+ * - Logging and event emission
40
+ * - Configuration access
41
+ * - Service container access
42
+ * - Default implementations for optional methods
43
+ *
44
+ * @example
45
+ * ```typescript
46
+ * class MyPlugin extends BasePlugin {
47
+ * constructor() {
48
+ * super({
49
+ * name: 'my-plugin',
50
+ * version: '1.0.0',
51
+ * description: 'My custom plugin'
52
+ * });
53
+ * }
54
+ *
55
+ * protected async onInitialize(): Promise<void> {
56
+ * this.logger.info('Plugin initialized');
57
+ * }
58
+ *
59
+ * registerMCPTools(): MCPToolDefinition[] {
60
+ * return [{
61
+ * name: 'my-tool',
62
+ * description: 'My custom tool',
63
+ * inputSchema: { type: 'object', properties: {} },
64
+ * handler: async (input) => ({
65
+ * content: [{ type: 'text', text: 'Hello!' }]
66
+ * })
67
+ * }];
68
+ * }
69
+ * }
70
+ * ```
71
+ */
72
+ export abstract class BasePlugin extends EventEmitter implements IPlugin {
73
+ // =========================================================================
74
+ // Properties
75
+ // =========================================================================
76
+
77
+ public readonly metadata: PluginMetadata;
78
+ private _state: PluginLifecycleState = 'uninitialized';
79
+ private _context: PluginContext | null = null;
80
+ private _initTime: Date | null = null;
81
+
82
+ // =========================================================================
83
+ // Constructor
84
+ // =========================================================================
85
+
86
+ constructor(metadata: PluginMetadata) {
87
+ super();
88
+ this.metadata = Object.freeze(metadata);
89
+ }
90
+
91
+ // =========================================================================
92
+ // State Management
93
+ // =========================================================================
94
+
95
+ get state(): PluginLifecycleState {
96
+ return this._state;
97
+ }
98
+
99
+ protected setState(state: PluginLifecycleState): void {
100
+ const previousState = this._state;
101
+ this._state = state;
102
+ this.emit('stateChange', { previousState, currentState: state });
103
+ }
104
+
105
+ // =========================================================================
106
+ // Context Accessors
107
+ // =========================================================================
108
+
109
+ protected get context(): PluginContext {
110
+ if (!this._context) {
111
+ throw new Error(`Plugin ${this.metadata.name} not initialized`);
112
+ }
113
+ return this._context;
114
+ }
115
+
116
+ protected get config(): PluginConfig {
117
+ return this.context.config;
118
+ }
119
+
120
+ protected get logger(): ILogger {
121
+ return this.context.logger;
122
+ }
123
+
124
+ protected get eventBus(): IEventBus {
125
+ return this.context.eventBus;
126
+ }
127
+
128
+ protected get services(): ServiceContainer {
129
+ return this.context.services;
130
+ }
131
+
132
+ protected get settings(): Record<string, unknown> {
133
+ return this.config.settings;
134
+ }
135
+
136
+ // =========================================================================
137
+ // Lifecycle Implementation
138
+ // =========================================================================
139
+
140
+ /**
141
+ * Initialize the plugin.
142
+ * Subclasses should override onInitialize() instead of this method.
143
+ */
144
+ async initialize(context: PluginContext): Promise<void> {
145
+ if (this._state !== 'uninitialized') {
146
+ throw new Error(`Plugin ${this.metadata.name} already initialized`);
147
+ }
148
+
149
+ this.setState('initializing');
150
+ this._context = context;
151
+ this._initTime = new Date();
152
+
153
+ try {
154
+ // Validate dependencies
155
+ await this.validateDependencies();
156
+
157
+ // Validate configuration
158
+ await this.validateConfig();
159
+
160
+ // Call subclass initialization
161
+ await this.onInitialize();
162
+
163
+ this.setState('initialized');
164
+ this.eventBus.emit(PLUGIN_EVENTS.INITIALIZED, { plugin: this.metadata.name });
165
+ } catch (error) {
166
+ this.setState('error');
167
+ this.eventBus.emit(PLUGIN_EVENTS.ERROR, {
168
+ plugin: this.metadata.name,
169
+ error: error instanceof Error ? error.message : String(error),
170
+ });
171
+ throw error;
172
+ }
173
+ }
174
+
175
+ /**
176
+ * Shutdown the plugin.
177
+ * Subclasses should override onShutdown() instead of this method.
178
+ */
179
+ async shutdown(): Promise<void> {
180
+ if (this._state !== 'initialized' && this._state !== 'error') {
181
+ return; // Already shutdown or never initialized
182
+ }
183
+
184
+ this.setState('shutting-down');
185
+
186
+ try {
187
+ await this.onShutdown();
188
+ this.setState('shutdown');
189
+ this.eventBus.emit(PLUGIN_EVENTS.SHUTDOWN, { plugin: this.metadata.name });
190
+ } catch (error) {
191
+ this.setState('error');
192
+ throw error;
193
+ } finally {
194
+ this._context = null;
195
+ }
196
+ }
197
+
198
+ /**
199
+ * Health check implementation.
200
+ * Subclasses can override onHealthCheck() for custom checks.
201
+ */
202
+ async healthCheck(): Promise<HealthCheckResult> {
203
+ const checks: Record<string, { healthy: boolean; message?: string; latencyMs?: number }> = {};
204
+
205
+ // Check state
206
+ const stateHealthy = this._state === 'initialized';
207
+ checks['state'] = {
208
+ healthy: stateHealthy,
209
+ message: stateHealthy ? 'Plugin initialized' : `State: ${this._state}`,
210
+ };
211
+
212
+ // Run custom health checks
213
+ const startTime = Date.now();
214
+ try {
215
+ const customChecks = await this.onHealthCheck();
216
+ Object.assign(checks, customChecks);
217
+ } catch (error) {
218
+ checks['custom'] = {
219
+ healthy: false,
220
+ message: error instanceof Error ? error.message : 'Health check failed',
221
+ latencyMs: Date.now() - startTime,
222
+ };
223
+ }
224
+
225
+ const allHealthy = Object.values(checks).every(c => c.healthy);
226
+
227
+ return {
228
+ healthy: allHealthy,
229
+ status: allHealthy ? 'healthy' : 'unhealthy',
230
+ checks,
231
+ timestamp: new Date(),
232
+ };
233
+ }
234
+
235
+ // =========================================================================
236
+ // Lifecycle Hooks (Override in subclasses)
237
+ // =========================================================================
238
+
239
+ /**
240
+ * Called during initialization.
241
+ * Override this in subclasses to add initialization logic.
242
+ */
243
+ protected async onInitialize(): Promise<void> {
244
+ // Default: no-op
245
+ }
246
+
247
+ /**
248
+ * Called during shutdown.
249
+ * Override this in subclasses to add cleanup logic.
250
+ */
251
+ protected async onShutdown(): Promise<void> {
252
+ // Default: no-op
253
+ }
254
+
255
+ /**
256
+ * Called during health check.
257
+ * Override this in subclasses to add custom health checks.
258
+ */
259
+ protected async onHealthCheck(): Promise<Record<string, { healthy: boolean; message?: string }>> {
260
+ return {};
261
+ }
262
+
263
+ // =========================================================================
264
+ // Validation
265
+ // =========================================================================
266
+
267
+ /**
268
+ * Validate plugin dependencies are available.
269
+ */
270
+ protected async validateDependencies(): Promise<void> {
271
+ const deps = this.metadata.dependencies ?? [];
272
+ for (const dep of deps) {
273
+ // Dependencies are validated by the PluginManager
274
+ // This hook allows plugins to do additional checks
275
+ this.logger.debug(`Dependency validated: ${dep}`);
276
+ }
277
+ }
278
+
279
+ /**
280
+ * Validate plugin configuration.
281
+ * Override this in subclasses to add config validation.
282
+ */
283
+ protected async validateConfig(): Promise<void> {
284
+ // Default: no-op
285
+ }
286
+
287
+ // =========================================================================
288
+ // Extension Points (Override in subclasses as needed)
289
+ // =========================================================================
290
+
291
+ registerAgentTypes?(): AgentTypeDefinition[];
292
+ registerTaskTypes?(): TaskTypeDefinition[];
293
+ registerMCPTools?(): MCPToolDefinition[];
294
+ registerCLICommands?(): CLICommandDefinition[];
295
+ registerMemoryBackends?(): MemoryBackendFactory[];
296
+ registerHooks?(): HookDefinition[];
297
+ registerWorkers?(): WorkerDefinition[];
298
+ registerProviders?(): LLMProviderDefinition[];
299
+
300
+ // =========================================================================
301
+ // Utility Methods
302
+ // =========================================================================
303
+
304
+ /**
305
+ * Get setting value with type safety.
306
+ */
307
+ protected getSetting<T>(key: string, defaultValue?: T): T | undefined {
308
+ const value = this.settings[key];
309
+ if (value === undefined) return defaultValue;
310
+ return value as T;
311
+ }
312
+
313
+ /**
314
+ * Get uptime in milliseconds.
315
+ */
316
+ protected getUptime(): number {
317
+ if (!this._initTime) return 0;
318
+ return Date.now() - this._initTime.getTime();
319
+ }
320
+
321
+ /**
322
+ * Create a child logger with context.
323
+ */
324
+ protected createChildLogger(context: Record<string, unknown>): ILogger {
325
+ return this.logger.child({ plugin: this.metadata.name, ...context });
326
+ }
327
+ }
328
+
329
+ // ============================================================================
330
+ // Simple Plugin (for quick one-off plugins)
331
+ // ============================================================================
332
+
333
+ /**
334
+ * Configuration for creating a simple plugin.
335
+ */
336
+ export interface SimplePluginConfig {
337
+ metadata: PluginMetadata;
338
+ onInitialize?: (context: PluginContext) => Promise<void>;
339
+ onShutdown?: () => Promise<void>;
340
+ agentTypes?: AgentTypeDefinition[];
341
+ taskTypes?: TaskTypeDefinition[];
342
+ mcpTools?: MCPToolDefinition[];
343
+ cliCommands?: CLICommandDefinition[];
344
+ hooks?: HookDefinition[];
345
+ workers?: WorkerDefinition[];
346
+ providers?: LLMProviderDefinition[];
347
+ }
348
+
349
+ /**
350
+ * Create a simple plugin from configuration.
351
+ *
352
+ * @example
353
+ * ```typescript
354
+ * const myPlugin = createSimplePlugin({
355
+ * metadata: { name: 'my-plugin', version: '1.0.0' },
356
+ * mcpTools: [{
357
+ * name: 'hello',
358
+ * description: 'Say hello',
359
+ * inputSchema: { type: 'object', properties: {} },
360
+ * handler: async () => ({ content: [{ type: 'text', text: 'Hello!' }] })
361
+ * }]
362
+ * });
363
+ * ```
364
+ */
365
+ export function createSimplePlugin(config: SimplePluginConfig): IPlugin {
366
+ return new SimplePlugin(config) as IPlugin;
367
+ }
368
+
369
+ class SimplePlugin extends BasePlugin {
370
+ private readonly _config: SimplePluginConfig;
371
+
372
+ constructor(config: SimplePluginConfig) {
373
+ super(config.metadata);
374
+ this._config = config;
375
+ }
376
+
377
+ protected async onInitialize(): Promise<void> {
378
+ if (this._config.onInitialize) {
379
+ await this._config.onInitialize(this.context);
380
+ }
381
+ }
382
+
383
+ protected async onShutdown(): Promise<void> {
384
+ if (this._config.onShutdown) {
385
+ await this._config.onShutdown();
386
+ }
387
+ }
388
+
389
+ override registerAgentTypes(): AgentTypeDefinition[] {
390
+ return this._config.agentTypes ?? [];
391
+ }
392
+
393
+ override registerTaskTypes(): TaskTypeDefinition[] {
394
+ return this._config.taskTypes ?? [];
395
+ }
396
+
397
+ override registerMCPTools(): MCPToolDefinition[] {
398
+ return this._config.mcpTools ?? [];
399
+ }
400
+
401
+ override registerCLICommands(): CLICommandDefinition[] {
402
+ return this._config.cliCommands ?? [];
403
+ }
404
+
405
+ override registerHooks(): HookDefinition[] {
406
+ return this._config.hooks ?? [];
407
+ }
408
+
409
+ override registerWorkers(): WorkerDefinition[] {
410
+ return this._config.workers ?? [];
411
+ }
412
+
413
+ override registerProviders(): LLMProviderDefinition[] {
414
+ return this._config.providers ?? [];
415
+ }
416
+ }
@@ -0,0 +1,215 @@
1
+ /**
2
+ * Core Plugin Interface
3
+ *
4
+ * Defines the contract that all plugins must implement.
5
+ */
6
+
7
+ import type {
8
+ PluginMetadata,
9
+ PluginContext,
10
+ PluginLifecycleState,
11
+ AgentTypeDefinition,
12
+ TaskTypeDefinition,
13
+ MCPToolDefinition,
14
+ CLICommandDefinition,
15
+ MemoryBackendFactory,
16
+ HookDefinition,
17
+ WorkerDefinition,
18
+ LLMProviderDefinition,
19
+ HealthCheckResult,
20
+ } from '../types/index.js';
21
+
22
+ // ============================================================================
23
+ // Plugin Interface
24
+ // ============================================================================
25
+
26
+ /**
27
+ * Core plugin interface that all plugins must implement.
28
+ *
29
+ * Plugins provide extensibility across multiple domains:
30
+ * - Agent types and task definitions
31
+ * - MCP tools for Claude interaction
32
+ * - CLI commands for terminal interface
33
+ * - Memory backends for storage
34
+ * - Hooks for lifecycle events
35
+ * - Workers for parallel execution
36
+ * - LLM providers for model access
37
+ */
38
+ export interface IPlugin {
39
+ /** Plugin metadata (name, version, etc.) */
40
+ readonly metadata: PluginMetadata;
41
+
42
+ /** Current lifecycle state */
43
+ readonly state: PluginLifecycleState;
44
+
45
+ // =========================================================================
46
+ // Lifecycle Methods
47
+ // =========================================================================
48
+
49
+ /**
50
+ * Initialize the plugin with context.
51
+ * Called once when the plugin is loaded.
52
+ */
53
+ initialize(context: PluginContext): Promise<void>;
54
+
55
+ /**
56
+ * Shutdown the plugin gracefully.
57
+ * Called when the plugin is being unloaded.
58
+ */
59
+ shutdown(): Promise<void>;
60
+
61
+ /**
62
+ * Check plugin health.
63
+ * Called periodically for monitoring.
64
+ */
65
+ healthCheck?(): Promise<HealthCheckResult>;
66
+
67
+ // =========================================================================
68
+ // Extension Point Registration
69
+ // =========================================================================
70
+
71
+ /**
72
+ * Register agent type definitions.
73
+ * Called during initialization to collect agent types.
74
+ */
75
+ registerAgentTypes?(): AgentTypeDefinition[];
76
+
77
+ /**
78
+ * Register task type definitions.
79
+ * Called during initialization to collect task types.
80
+ */
81
+ registerTaskTypes?(): TaskTypeDefinition[];
82
+
83
+ /**
84
+ * Register MCP tool definitions.
85
+ * Called during initialization to expose tools to Claude.
86
+ */
87
+ registerMCPTools?(): MCPToolDefinition[];
88
+
89
+ /**
90
+ * Register CLI command definitions.
91
+ * Called during initialization to extend the CLI.
92
+ */
93
+ registerCLICommands?(): CLICommandDefinition[];
94
+
95
+ /**
96
+ * Register memory backend factories.
97
+ * Called during initialization to add storage options.
98
+ */
99
+ registerMemoryBackends?(): MemoryBackendFactory[];
100
+
101
+ /**
102
+ * Register hook definitions.
103
+ * Called during initialization to add lifecycle hooks.
104
+ */
105
+ registerHooks?(): HookDefinition[];
106
+
107
+ /**
108
+ * Register worker definitions.
109
+ * Called during initialization to add worker types.
110
+ */
111
+ registerWorkers?(): WorkerDefinition[];
112
+
113
+ /**
114
+ * Register LLM provider definitions.
115
+ * Called during initialization to add model providers.
116
+ */
117
+ registerProviders?(): LLMProviderDefinition[];
118
+ }
119
+
120
+ // ============================================================================
121
+ // Plugin Factory
122
+ // ============================================================================
123
+
124
+ /**
125
+ * Factory function type for creating plugin instances.
126
+ */
127
+ export type PluginFactory = () => IPlugin | Promise<IPlugin>;
128
+
129
+ /**
130
+ * Plugin module export interface.
131
+ * Plugins should export a default factory or plugin instance.
132
+ */
133
+ export interface PluginModule {
134
+ default: IPlugin | PluginFactory;
135
+ metadata?: PluginMetadata;
136
+ }
137
+
138
+ // ============================================================================
139
+ // Plugin Events
140
+ // ============================================================================
141
+
142
+ export const PLUGIN_EVENTS = {
143
+ LOADING: 'plugin:loading',
144
+ LOADED: 'plugin:loaded',
145
+ INITIALIZING: 'plugin:initializing',
146
+ INITIALIZED: 'plugin:initialized',
147
+ SHUTTING_DOWN: 'plugin:shutting-down',
148
+ SHUTDOWN: 'plugin:shutdown',
149
+ ERROR: 'plugin:error',
150
+ HEALTH_CHECK: 'plugin:health-check',
151
+ } as const;
152
+
153
+ export type PluginEvent = typeof PLUGIN_EVENTS[keyof typeof PLUGIN_EVENTS];
154
+
155
+ // ============================================================================
156
+ // Plugin Validation
157
+ // ============================================================================
158
+
159
+ /**
160
+ * Validate plugin metadata.
161
+ */
162
+ export function validatePluginMetadata(metadata: unknown): metadata is PluginMetadata {
163
+ if (!metadata || typeof metadata !== 'object') return false;
164
+
165
+ const m = metadata as Record<string, unknown>;
166
+
167
+ if (typeof m.name !== 'string' || m.name.length === 0) return false;
168
+ if (typeof m.version !== 'string' || !/^\d+\.\d+\.\d+/.test(m.version)) return false;
169
+
170
+ if (m.description !== undefined && typeof m.description !== 'string') return false;
171
+ if (m.author !== undefined && typeof m.author !== 'string') return false;
172
+
173
+ if (m.dependencies !== undefined) {
174
+ if (!Array.isArray(m.dependencies)) return false;
175
+ if (!m.dependencies.every(d => typeof d === 'string')) return false;
176
+ }
177
+
178
+ return true;
179
+ }
180
+
181
+ /**
182
+ * Validate plugin interface.
183
+ */
184
+ export function validatePlugin(plugin: unknown): plugin is IPlugin {
185
+ if (!plugin || typeof plugin !== 'object') return false;
186
+
187
+ const p = plugin as Record<string, unknown>;
188
+
189
+ // Check required properties
190
+ if (!validatePluginMetadata(p.metadata)) return false;
191
+ if (typeof p.state !== 'string') return false;
192
+ if (typeof p.initialize !== 'function') return false;
193
+ if (typeof p.shutdown !== 'function') return false;
194
+
195
+ // Check optional methods are functions if present
196
+ const optionalMethods = [
197
+ 'healthCheck',
198
+ 'registerAgentTypes',
199
+ 'registerTaskTypes',
200
+ 'registerMCPTools',
201
+ 'registerCLICommands',
202
+ 'registerMemoryBackends',
203
+ 'registerHooks',
204
+ 'registerWorkers',
205
+ 'registerProviders',
206
+ ];
207
+
208
+ for (const method of optionalMethods) {
209
+ if (p[method] !== undefined && typeof p[method] !== 'function') {
210
+ return false;
211
+ }
212
+ }
213
+
214
+ return true;
215
+ }