@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.
- package/README.md +401 -0
- package/__tests__/collection-manager.test.ts +332 -0
- package/__tests__/dependency-graph.test.ts +434 -0
- package/__tests__/enhanced-plugin-registry.test.ts +488 -0
- package/__tests__/plugin-registry.test.ts +368 -0
- package/__tests__/ruvector-bridge.test.ts +2429 -0
- package/__tests__/ruvector-integration.test.ts +1602 -0
- package/__tests__/ruvector-migrations.test.ts +1099 -0
- package/__tests__/ruvector-quantization.test.ts +846 -0
- package/__tests__/ruvector-streaming.test.ts +1088 -0
- package/__tests__/sdk.test.ts +325 -0
- package/__tests__/security.test.ts +348 -0
- package/__tests__/utils/ruvector-test-utils.ts +860 -0
- package/examples/plugin-creator/index.ts +636 -0
- package/examples/plugin-creator/plugin-creator.test.ts +312 -0
- package/examples/ruvector/README.md +288 -0
- package/examples/ruvector/attention-patterns.ts +394 -0
- package/examples/ruvector/basic-usage.ts +288 -0
- package/examples/ruvector/docker-compose.yml +75 -0
- package/examples/ruvector/gnn-analysis.ts +501 -0
- package/examples/ruvector/hyperbolic-hierarchies.ts +557 -0
- package/examples/ruvector/init-db.sql +119 -0
- package/examples/ruvector/quantization.ts +680 -0
- package/examples/ruvector/self-learning.ts +447 -0
- package/examples/ruvector/semantic-search.ts +576 -0
- package/examples/ruvector/streaming-large-data.ts +507 -0
- package/examples/ruvector/transactions.ts +594 -0
- package/examples/ruvector-plugins/hook-pattern-library.ts +486 -0
- package/examples/ruvector-plugins/index.ts +79 -0
- package/examples/ruvector-plugins/intent-router.ts +354 -0
- package/examples/ruvector-plugins/mcp-tool-optimizer.ts +424 -0
- package/examples/ruvector-plugins/reasoning-bank.ts +657 -0
- package/examples/ruvector-plugins/ruvector-plugins.test.ts +518 -0
- package/examples/ruvector-plugins/semantic-code-search.ts +498 -0
- package/examples/ruvector-plugins/shared/index.ts +20 -0
- package/examples/ruvector-plugins/shared/vector-utils.ts +257 -0
- package/examples/ruvector-plugins/sona-learning.ts +445 -0
- package/package.json +97 -0
- package/src/collections/collection-manager.ts +661 -0
- package/src/collections/index.ts +56 -0
- package/src/collections/official/index.ts +1040 -0
- package/src/core/base-plugin.ts +416 -0
- package/src/core/plugin-interface.ts +215 -0
- package/src/hooks/index.ts +685 -0
- package/src/index.ts +378 -0
- package/src/integrations/agentic-flow.ts +743 -0
- package/src/integrations/index.ts +88 -0
- package/src/integrations/ruvector/ARCHITECTURE.md +1245 -0
- package/src/integrations/ruvector/attention-advanced.ts +1040 -0
- package/src/integrations/ruvector/attention-executor.ts +782 -0
- package/src/integrations/ruvector/attention-mechanisms.ts +757 -0
- package/src/integrations/ruvector/attention.ts +1063 -0
- package/src/integrations/ruvector/gnn.ts +3050 -0
- package/src/integrations/ruvector/hyperbolic.ts +1948 -0
- package/src/integrations/ruvector/index.ts +394 -0
- package/src/integrations/ruvector/migrations/001_create_extension.sql +135 -0
- package/src/integrations/ruvector/migrations/002_create_vector_tables.sql +259 -0
- package/src/integrations/ruvector/migrations/003_create_indices.sql +328 -0
- package/src/integrations/ruvector/migrations/004_create_functions.sql +598 -0
- package/src/integrations/ruvector/migrations/005_create_attention_functions.sql +654 -0
- package/src/integrations/ruvector/migrations/006_create_gnn_functions.sql +728 -0
- package/src/integrations/ruvector/migrations/007_create_hyperbolic_functions.sql +762 -0
- package/src/integrations/ruvector/migrations/index.ts +35 -0
- package/src/integrations/ruvector/migrations/migrations.ts +647 -0
- package/src/integrations/ruvector/quantization.ts +2036 -0
- package/src/integrations/ruvector/ruvector-bridge.ts +2000 -0
- package/src/integrations/ruvector/self-learning.ts +2376 -0
- package/src/integrations/ruvector/streaming.ts +1737 -0
- package/src/integrations/ruvector/types.ts +1945 -0
- package/src/providers/index.ts +643 -0
- package/src/registry/dependency-graph.ts +568 -0
- package/src/registry/enhanced-plugin-registry.ts +994 -0
- package/src/registry/plugin-registry.ts +604 -0
- package/src/sdk/index.ts +563 -0
- package/src/security/index.ts +594 -0
- package/src/types/index.ts +446 -0
- package/src/workers/index.ts +700 -0
- package/tmp.json +0 -0
- package/tsconfig.json +25 -0
- package/vitest.config.ts +23 -0
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collection Manager Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests for plugin collection management, activation/deactivation,
|
|
5
|
+
* and state persistence.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
9
|
+
import {
|
|
10
|
+
PluginCollectionManager,
|
|
11
|
+
type PluginCollection,
|
|
12
|
+
type PluginCollectionEntry,
|
|
13
|
+
type CollectionManagerState,
|
|
14
|
+
} from '../src/collections/collection-manager.js';
|
|
15
|
+
import { PluginBuilder } from '../src/sdk/index.js';
|
|
16
|
+
import { EnhancedPluginRegistry } from '../src/registry/enhanced-plugin-registry.js';
|
|
17
|
+
|
|
18
|
+
// ============================================================================
|
|
19
|
+
// Test Helpers
|
|
20
|
+
// ============================================================================
|
|
21
|
+
|
|
22
|
+
function createTestPlugin(name: string, version = '1.0.0') {
|
|
23
|
+
return new PluginBuilder(name, version)
|
|
24
|
+
.withDescription(`Test plugin: ${name}`)
|
|
25
|
+
.build();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function createTestCollection(
|
|
29
|
+
id: string,
|
|
30
|
+
plugins: Array<{ name: string; defaultEnabled: boolean }>
|
|
31
|
+
): PluginCollection {
|
|
32
|
+
return {
|
|
33
|
+
id,
|
|
34
|
+
name: `Test Collection: ${id}`,
|
|
35
|
+
version: '1.0.0',
|
|
36
|
+
plugins: plugins.map(p => ({
|
|
37
|
+
plugin: createTestPlugin(p.name),
|
|
38
|
+
defaultEnabled: p.defaultEnabled,
|
|
39
|
+
category: 'utility' as const,
|
|
40
|
+
tags: ['test'],
|
|
41
|
+
})),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// ============================================================================
|
|
46
|
+
// Tests
|
|
47
|
+
// ============================================================================
|
|
48
|
+
|
|
49
|
+
describe('PluginCollectionManager', () => {
|
|
50
|
+
let registry: EnhancedPluginRegistry;
|
|
51
|
+
let manager: PluginCollectionManager;
|
|
52
|
+
|
|
53
|
+
beforeEach(() => {
|
|
54
|
+
registry = new EnhancedPluginRegistry({
|
|
55
|
+
coreVersion: '3.0.0',
|
|
56
|
+
dataDir: '/tmp/test',
|
|
57
|
+
});
|
|
58
|
+
manager = new PluginCollectionManager({
|
|
59
|
+
registry,
|
|
60
|
+
autoInitialize: false, // Don't auto-init for tests
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
describe('loadCollection', () => {
|
|
65
|
+
it('should load a collection', async () => {
|
|
66
|
+
const collection = createTestCollection('test-collection', [
|
|
67
|
+
{ name: 'plugin-a', defaultEnabled: true },
|
|
68
|
+
{ name: 'plugin-b', defaultEnabled: false },
|
|
69
|
+
]);
|
|
70
|
+
|
|
71
|
+
await manager.loadCollection(collection);
|
|
72
|
+
|
|
73
|
+
expect(manager.getCollection('test-collection')).toBeDefined();
|
|
74
|
+
expect(manager.listCollections()).toHaveLength(1);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('should register enabled plugins', async () => {
|
|
78
|
+
const collection = createTestCollection('test-collection', [
|
|
79
|
+
{ name: 'plugin-a', defaultEnabled: true },
|
|
80
|
+
{ name: 'plugin-b', defaultEnabled: false },
|
|
81
|
+
]);
|
|
82
|
+
|
|
83
|
+
await manager.loadCollection(collection);
|
|
84
|
+
|
|
85
|
+
expect(registry.getPlugin('plugin-a')).toBeDefined();
|
|
86
|
+
expect(registry.getPlugin('plugin-b')).toBeUndefined();
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('should reject duplicate collection IDs', async () => {
|
|
90
|
+
const collection = createTestCollection('test-collection', []);
|
|
91
|
+
|
|
92
|
+
await manager.loadCollection(collection);
|
|
93
|
+
|
|
94
|
+
await expect(manager.loadCollection(collection))
|
|
95
|
+
.rejects.toThrow('already loaded');
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
describe('unloadCollection', () => {
|
|
100
|
+
it('should unload a collection and its plugins', async () => {
|
|
101
|
+
const collection = createTestCollection('test-collection', [
|
|
102
|
+
{ name: 'plugin-a', defaultEnabled: true },
|
|
103
|
+
]);
|
|
104
|
+
|
|
105
|
+
await manager.loadCollection(collection);
|
|
106
|
+
await manager.unloadCollection('test-collection');
|
|
107
|
+
|
|
108
|
+
expect(manager.getCollection('test-collection')).toBeUndefined();
|
|
109
|
+
expect(registry.getPlugin('plugin-a')).toBeUndefined();
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('should throw for non-existent collection', async () => {
|
|
113
|
+
await expect(manager.unloadCollection('non-existent'))
|
|
114
|
+
.rejects.toThrow('not found');
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
describe('enablePlugin', () => {
|
|
119
|
+
it('should enable a disabled plugin', async () => {
|
|
120
|
+
const collection = createTestCollection('test-collection', [
|
|
121
|
+
{ name: 'plugin-a', defaultEnabled: false },
|
|
122
|
+
]);
|
|
123
|
+
|
|
124
|
+
await manager.loadCollection(collection);
|
|
125
|
+
await manager.enablePlugin('test-collection', 'plugin-a');
|
|
126
|
+
|
|
127
|
+
expect(await manager.isEnabled('test-collection', 'plugin-a')).toBe(true);
|
|
128
|
+
expect(registry.getPlugin('plugin-a')).toBeDefined();
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it('should throw for non-existent plugin', async () => {
|
|
132
|
+
const collection = createTestCollection('test-collection', []);
|
|
133
|
+
|
|
134
|
+
await manager.loadCollection(collection);
|
|
135
|
+
|
|
136
|
+
await expect(manager.enablePlugin('test-collection', 'non-existent'))
|
|
137
|
+
.rejects.toThrow('not found');
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
describe('disablePlugin', () => {
|
|
142
|
+
it('should disable an enabled plugin', async () => {
|
|
143
|
+
const collection = createTestCollection('test-collection', [
|
|
144
|
+
{ name: 'plugin-a', defaultEnabled: true },
|
|
145
|
+
]);
|
|
146
|
+
|
|
147
|
+
await manager.loadCollection(collection);
|
|
148
|
+
await manager.disablePlugin('test-collection', 'plugin-a');
|
|
149
|
+
|
|
150
|
+
expect(await manager.isEnabled('test-collection', 'plugin-a')).toBe(false);
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
describe('togglePlugin', () => {
|
|
155
|
+
it('should toggle plugin state', async () => {
|
|
156
|
+
const collection = createTestCollection('test-collection', [
|
|
157
|
+
{ name: 'plugin-a', defaultEnabled: true },
|
|
158
|
+
]);
|
|
159
|
+
|
|
160
|
+
await manager.loadCollection(collection);
|
|
161
|
+
|
|
162
|
+
const newState1 = await manager.togglePlugin('test-collection', 'plugin-a');
|
|
163
|
+
expect(newState1).toBe(false);
|
|
164
|
+
|
|
165
|
+
const newState2 = await manager.togglePlugin('test-collection', 'plugin-a');
|
|
166
|
+
expect(newState2).toBe(true);
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
describe('bulk operations', () => {
|
|
171
|
+
it('should enable all plugins', async () => {
|
|
172
|
+
const collection = createTestCollection('test-collection', [
|
|
173
|
+
{ name: 'plugin-a', defaultEnabled: false },
|
|
174
|
+
{ name: 'plugin-b', defaultEnabled: false },
|
|
175
|
+
]);
|
|
176
|
+
|
|
177
|
+
await manager.loadCollection(collection);
|
|
178
|
+
await manager.enableAll('test-collection');
|
|
179
|
+
|
|
180
|
+
expect(await manager.isEnabled('test-collection', 'plugin-a')).toBe(true);
|
|
181
|
+
expect(await manager.isEnabled('test-collection', 'plugin-b')).toBe(true);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it('should disable all plugins', async () => {
|
|
185
|
+
const collection = createTestCollection('test-collection', [
|
|
186
|
+
{ name: 'plugin-a', defaultEnabled: true },
|
|
187
|
+
{ name: 'plugin-b', defaultEnabled: true },
|
|
188
|
+
]);
|
|
189
|
+
|
|
190
|
+
await manager.loadCollection(collection);
|
|
191
|
+
await manager.disableAll('test-collection');
|
|
192
|
+
|
|
193
|
+
expect(await manager.isEnabled('test-collection', 'plugin-a')).toBe(false);
|
|
194
|
+
expect(await manager.isEnabled('test-collection', 'plugin-b')).toBe(false);
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
describe('filtering', () => {
|
|
199
|
+
it('should get plugins by category', async () => {
|
|
200
|
+
const collection: PluginCollection = {
|
|
201
|
+
id: 'test-collection',
|
|
202
|
+
name: 'Test',
|
|
203
|
+
version: '1.0.0',
|
|
204
|
+
plugins: [
|
|
205
|
+
{ plugin: createTestPlugin('tool-1'), defaultEnabled: true, category: 'tool', tags: [] },
|
|
206
|
+
{ plugin: createTestPlugin('agent-1'), defaultEnabled: true, category: 'agent', tags: [] },
|
|
207
|
+
{ plugin: createTestPlugin('tool-2'), defaultEnabled: true, category: 'tool', tags: [] },
|
|
208
|
+
],
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
await manager.loadCollection(collection);
|
|
212
|
+
|
|
213
|
+
const tools = manager.getPluginsByCategory('tool');
|
|
214
|
+
expect(tools).toHaveLength(2);
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it('should get plugins by tag', async () => {
|
|
218
|
+
const collection: PluginCollection = {
|
|
219
|
+
id: 'test-collection',
|
|
220
|
+
name: 'Test',
|
|
221
|
+
version: '1.0.0',
|
|
222
|
+
plugins: [
|
|
223
|
+
{ plugin: createTestPlugin('plugin-1'), defaultEnabled: true, category: 'utility', tags: ['core'] },
|
|
224
|
+
{ plugin: createTestPlugin('plugin-2'), defaultEnabled: true, category: 'utility', tags: ['optional'] },
|
|
225
|
+
{ plugin: createTestPlugin('plugin-3'), defaultEnabled: true, category: 'utility', tags: ['core', 'important'] },
|
|
226
|
+
],
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
await manager.loadCollection(collection);
|
|
230
|
+
|
|
231
|
+
const corePlugins = manager.getPluginsByTag('core');
|
|
232
|
+
expect(corePlugins).toHaveLength(2);
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
it('should search plugins by name', async () => {
|
|
236
|
+
const collection = createTestCollection('test-collection', [
|
|
237
|
+
{ name: 'auth-plugin', defaultEnabled: true },
|
|
238
|
+
{ name: 'cache-plugin', defaultEnabled: true },
|
|
239
|
+
{ name: 'auth-helper', defaultEnabled: true },
|
|
240
|
+
]);
|
|
241
|
+
|
|
242
|
+
await manager.loadCollection(collection);
|
|
243
|
+
|
|
244
|
+
const results = await manager.searchPlugins('auth');
|
|
245
|
+
expect(results.length).toBeGreaterThanOrEqual(2);
|
|
246
|
+
expect(results[0].pluginName).toContain('auth');
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
describe('settings', () => {
|
|
251
|
+
it('should get and set plugin settings', () => {
|
|
252
|
+
manager.setPluginSettings('plugin-a', { debug: true, maxRetries: 3 });
|
|
253
|
+
|
|
254
|
+
const settings = manager.getPluginSettings('plugin-a');
|
|
255
|
+
expect(settings).toEqual({ debug: true, maxRetries: 3 });
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
it('should update plugin settings', () => {
|
|
259
|
+
manager.setPluginSettings('plugin-a', { debug: true, maxRetries: 3 });
|
|
260
|
+
manager.updatePluginSettings('plugin-a', { maxRetries: 5, timeout: 1000 });
|
|
261
|
+
|
|
262
|
+
const settings = manager.getPluginSettings('plugin-a');
|
|
263
|
+
expect(settings).toEqual({ debug: true, maxRetries: 5, timeout: 1000 });
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
it('should return empty object for unknown plugin', () => {
|
|
267
|
+
const settings = manager.getPluginSettings('unknown');
|
|
268
|
+
expect(settings).toEqual({});
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
describe('state persistence', () => {
|
|
273
|
+
it('should export state', async () => {
|
|
274
|
+
const collection = createTestCollection('test-collection', [
|
|
275
|
+
{ name: 'plugin-a', defaultEnabled: true },
|
|
276
|
+
{ name: 'plugin-b', defaultEnabled: false },
|
|
277
|
+
]);
|
|
278
|
+
|
|
279
|
+
await manager.loadCollection(collection);
|
|
280
|
+
await manager.disablePlugin('test-collection', 'plugin-a');
|
|
281
|
+
manager.setPluginSettings('plugin-a', { custom: true });
|
|
282
|
+
|
|
283
|
+
const state = manager.exportState();
|
|
284
|
+
|
|
285
|
+
expect(state.version).toBe('1.0.0');
|
|
286
|
+
expect(state.collections).toContain('test-collection');
|
|
287
|
+
expect(state.disabledPlugins['test-collection']).toContain('plugin-a');
|
|
288
|
+
expect(state.pluginSettings['plugin-a']).toEqual({ custom: true });
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
it('should import state', async () => {
|
|
292
|
+
const state: CollectionManagerState = {
|
|
293
|
+
version: '1.0.0',
|
|
294
|
+
collections: ['test-collection'],
|
|
295
|
+
enabledPlugins: { 'test-collection': ['plugin-b'] },
|
|
296
|
+
disabledPlugins: { 'test-collection': ['plugin-a'] },
|
|
297
|
+
pluginSettings: { 'plugin-a': { imported: true } },
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
manager.importState(state);
|
|
301
|
+
|
|
302
|
+
expect(manager.getPluginSettings('plugin-a')).toEqual({ imported: true });
|
|
303
|
+
});
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
describe('statistics', () => {
|
|
307
|
+
it('should return correct stats', async () => {
|
|
308
|
+
const collection: PluginCollection = {
|
|
309
|
+
id: 'test-collection',
|
|
310
|
+
name: 'Test',
|
|
311
|
+
version: '1.0.0',
|
|
312
|
+
plugins: [
|
|
313
|
+
{ plugin: createTestPlugin('tool-1'), defaultEnabled: true, category: 'tool', tags: [] },
|
|
314
|
+
{ plugin: createTestPlugin('agent-1'), defaultEnabled: false, category: 'agent', tags: [] },
|
|
315
|
+
{ plugin: createTestPlugin('hook-1'), defaultEnabled: true, category: 'hook', tags: [] },
|
|
316
|
+
],
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
await manager.loadCollection(collection);
|
|
320
|
+
|
|
321
|
+
const stats = await manager.getStats();
|
|
322
|
+
|
|
323
|
+
expect(stats.totalCollections).toBe(1);
|
|
324
|
+
expect(stats.totalPlugins).toBe(3);
|
|
325
|
+
expect(stats.enabledPlugins).toBe(2);
|
|
326
|
+
expect(stats.disabledPlugins).toBe(1);
|
|
327
|
+
expect(stats.byCategory.tool).toBe(1);
|
|
328
|
+
expect(stats.byCategory.agent).toBe(1);
|
|
329
|
+
expect(stats.byCategory.hook).toBe(1);
|
|
330
|
+
});
|
|
331
|
+
});
|
|
332
|
+
});
|