@ruvector/edge-net 0.4.6 → 0.5.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ruvector/edge-net",
3
- "version": "0.4.6",
3
+ "version": "0.5.0",
4
4
  "type": "module",
5
5
  "description": "Distributed compute intelligence network with WASM cryptographic security - contribute browser compute, spawn distributed AI agents, earn credits. Features Ed25519 signing, PiKey identity, Time Crystal coordination, Neural DAG attention, P2P swarm intelligence, ONNX inference, WebRTC signaling, CRDT ledger, and multi-agent workflows.",
6
6
  "main": "ruvector_edge_net.js",
@@ -11,7 +11,8 @@
11
11
  "ruvector-edge": "./cli.js",
12
12
  "edge-net-join": "./join.js",
13
13
  "edge-net-genesis": "./genesis.js",
14
- "edge-net-firebase-setup": "./firebase-setup.js"
14
+ "edge-net-firebase-setup": "./firebase-setup.js",
15
+ "edge-net-plugins": "./plugins/cli.js"
15
16
  },
16
17
  "keywords": [
17
18
  "wasm",
@@ -105,6 +106,7 @@
105
106
  "secure-access.js",
106
107
  "credits.js",
107
108
  "task-execution-handler.js",
109
+ "plugins/",
108
110
  "README.md",
109
111
  "LICENSE"
110
112
  ],
@@ -178,6 +180,15 @@
178
180
  },
179
181
  "./task-execution": {
180
182
  "import": "./task-execution-handler.js"
183
+ },
184
+ "./plugins": {
185
+ "import": "./plugins/index.js"
186
+ },
187
+ "./plugins/sdk": {
188
+ "import": "./plugins/plugin-sdk.js"
189
+ },
190
+ "./plugins/catalog": {
191
+ "import": "./plugins/plugin-manifest.js"
181
192
  }
182
193
  },
183
194
  "sideEffects": [
package/plugins/cli.js ADDED
@@ -0,0 +1,395 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Edge-Net Plugin CLI
4
+ *
5
+ * Manage plugins from the command line.
6
+ *
7
+ * Commands:
8
+ * edge-net plugins list List available plugins
9
+ * edge-net plugins info <id> Show plugin details
10
+ * edge-net plugins enable <id> Enable a plugin
11
+ * edge-net plugins disable <id> Disable a plugin
12
+ * edge-net plugins bundles List plugin bundles
13
+ * edge-net plugins create <name> Create new plugin from template
14
+ * edge-net plugins validate <path> Validate a custom plugin
15
+ *
16
+ * @module @ruvector/edge-net/plugins/cli
17
+ */
18
+
19
+ import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs';
20
+ import { join, dirname } from 'path';
21
+ import { fileURLToPath } from 'url';
22
+ import {
23
+ PLUGIN_CATALOG,
24
+ PLUGIN_BUNDLES,
25
+ PluginCategory,
26
+ PluginTier,
27
+ } from './plugin-manifest.js';
28
+ import { PluginManager } from './plugin-loader.js';
29
+ import { generatePluginTemplate, validateManifest, getRegistry } from './plugin-sdk.js';
30
+
31
+ const __dirname = dirname(fileURLToPath(import.meta.url));
32
+
33
+ // ============================================
34
+ // CLI COMMANDS
35
+ // ============================================
36
+
37
+ const commands = {
38
+ /**
39
+ * List all available plugins
40
+ */
41
+ list: async (args) => {
42
+ const filter = args[0]; // Optional: category filter
43
+
44
+ console.log('\n╔════════════════════════════════════════════════════════════════╗');
45
+ console.log('║ EDGE-NET PLUGIN CATALOG ║');
46
+ console.log('╚════════════════════════════════════════════════════════════════╝\n');
47
+
48
+ const plugins = Object.values(PLUGIN_CATALOG);
49
+ const grouped = {};
50
+
51
+ for (const plugin of plugins) {
52
+ if (filter && plugin.category !== filter && plugin.tier !== filter) {
53
+ continue;
54
+ }
55
+ if (!grouped[plugin.category]) {
56
+ grouped[plugin.category] = [];
57
+ }
58
+ grouped[plugin.category].push(plugin);
59
+ }
60
+
61
+ for (const [category, categoryPlugins] of Object.entries(grouped)) {
62
+ console.log(`\n┌─ ${category.toUpperCase()} ─────────────────────────────────────────┐`);
63
+
64
+ for (const plugin of categoryPlugins) {
65
+ const tier = getTierBadge(plugin.tier);
66
+ const status = getStatusIcon(plugin);
67
+ console.log(`│ ${status} ${plugin.id.padEnd(30)} ${tier}`);
68
+ console.log(`│ ${plugin.description.slice(0, 55)}...`);
69
+ }
70
+
71
+ console.log('└────────────────────────────────────────────────────────┘');
72
+ }
73
+
74
+ console.log(`\n📦 Total: ${plugins.length} plugins in ${Object.keys(grouped).length} categories\n`);
75
+ console.log('Use: edge-net plugins info <id> for details');
76
+ console.log('Use: edge-net plugins enable <id> to enable a plugin\n');
77
+ },
78
+
79
+ /**
80
+ * Show plugin details
81
+ */
82
+ info: async (args) => {
83
+ const pluginId = args[0];
84
+ if (!pluginId) {
85
+ console.error('Usage: edge-net plugins info <plugin-id>');
86
+ process.exit(1);
87
+ }
88
+
89
+ const plugin = PLUGIN_CATALOG[pluginId];
90
+ if (!plugin) {
91
+ console.error(`Plugin not found: ${pluginId}`);
92
+ console.log('\nAvailable plugins:');
93
+ Object.keys(PLUGIN_CATALOG).forEach(id => console.log(` - ${id}`));
94
+ process.exit(1);
95
+ }
96
+
97
+ console.log('\n╔════════════════════════════════════════════════════════════════╗');
98
+ console.log(`║ ${plugin.name.padEnd(60)}║`);
99
+ console.log('╚════════════════════════════════════════════════════════════════╝\n');
100
+
101
+ console.log(` ID: ${plugin.id}`);
102
+ console.log(` Version: ${plugin.version}`);
103
+ console.log(` Category: ${plugin.category}`);
104
+ console.log(` Tier: ${getTierBadge(plugin.tier)}`);
105
+ console.log(` Description: ${plugin.description}`);
106
+
107
+ if (plugin.capabilities?.length > 0) {
108
+ console.log(`\n Capabilities Required:`);
109
+ plugin.capabilities.forEach(cap => console.log(` • ${cap}`));
110
+ }
111
+
112
+ if (plugin.dependencies?.length > 0) {
113
+ console.log(`\n Dependencies:`);
114
+ plugin.dependencies.forEach(dep => console.log(` → ${dep}`));
115
+ }
116
+
117
+ if (plugin.tags?.length > 0) {
118
+ console.log(`\n Tags: ${plugin.tags.join(', ')}`);
119
+ }
120
+
121
+ if (plugin.configSchema?.properties) {
122
+ console.log('\n Configuration Options:');
123
+ for (const [key, prop] of Object.entries(plugin.configSchema.properties)) {
124
+ const def = prop.default !== undefined ? ` (default: ${JSON.stringify(prop.default)})` : '';
125
+ console.log(` ${key}: ${prop.type}${def}`);
126
+ }
127
+ }
128
+
129
+ console.log('\n Usage:');
130
+ console.log(` const plugin = await plugins.load('${pluginId}');`);
131
+ console.log('');
132
+ },
133
+
134
+ /**
135
+ * List plugin bundles
136
+ */
137
+ bundles: async () => {
138
+ console.log('\n╔════════════════════════════════════════════════════════════════╗');
139
+ console.log('║ PLUGIN BUNDLES ║');
140
+ console.log('╚════════════════════════════════════════════════════════════════╝\n');
141
+
142
+ for (const [id, bundle] of Object.entries(PLUGIN_BUNDLES)) {
143
+ console.log(`┌─ ${bundle.name.toUpperCase()} ─────────────────────────────────────────┐`);
144
+ console.log(`│ ID: ${id}`);
145
+ console.log(`│ ${bundle.description}`);
146
+ console.log('│');
147
+ console.log('│ Plugins:');
148
+ if (bundle.plugins.length === 0) {
149
+ console.log('│ (none - minimal bundle)');
150
+ } else {
151
+ bundle.plugins.forEach(p => console.log(`│ • ${p}`));
152
+ }
153
+ console.log('└────────────────────────────────────────────────────────────┘\n');
154
+ }
155
+
156
+ console.log('Usage: await plugins.loadBundle("bundle-name")\n');
157
+ },
158
+
159
+ /**
160
+ * Create new plugin from template
161
+ */
162
+ create: async (args) => {
163
+ const name = args[0];
164
+ if (!name) {
165
+ console.error('Usage: edge-net plugins create <plugin-name>');
166
+ console.log('\nOptions:');
167
+ console.log(' --category <category> Plugin category (default: core)');
168
+ console.log(' --tier <tier> Plugin tier (default: experimental)');
169
+ console.log(' --output <dir> Output directory (default: ./plugins)');
170
+ process.exit(1);
171
+ }
172
+
173
+ // Parse options
174
+ const category = getArg(args, '--category') || 'core';
175
+ const tier = getArg(args, '--tier') || 'experimental';
176
+ const outputDir = getArg(args, '--output') || './plugins';
177
+
178
+ const id = `custom.${name.toLowerCase().replace(/\s+/g, '-')}`;
179
+ const pascalName = name.split(/[-\s]+/).map(s =>
180
+ s.charAt(0).toUpperCase() + s.slice(1)
181
+ ).join('');
182
+
183
+ console.log(`\n🔧 Creating plugin: ${name}\n`);
184
+
185
+ const template = generatePluginTemplate({
186
+ id,
187
+ name,
188
+ description: `Custom edge-net plugin: ${name}`,
189
+ category: PluginCategory[category.toUpperCase()] || PluginCategory.CORE,
190
+ tier: PluginTier[tier.toUpperCase()] || PluginTier.EXPERIMENTAL,
191
+ capabilities: [],
192
+ });
193
+
194
+ // Create output directory
195
+ const pluginDir = join(outputDir, name.toLowerCase().replace(/\s+/g, '-'));
196
+ if (!existsSync(pluginDir)) {
197
+ mkdirSync(pluginDir, { recursive: true });
198
+ }
199
+
200
+ // Write plugin file
201
+ const pluginFile = join(pluginDir, 'index.js');
202
+ writeFileSync(pluginFile, template);
203
+
204
+ // Write package.json
205
+ const packageJson = {
206
+ name: `@edge-net-plugin/${name.toLowerCase().replace(/\s+/g, '-')}`,
207
+ version: '1.0.0',
208
+ type: 'module',
209
+ main: 'index.js',
210
+ description: `Custom edge-net plugin: ${name}`,
211
+ keywords: ['edge-net', 'plugin', category],
212
+ peerDependencies: {
213
+ '@ruvector/edge-net': '^0.4.0',
214
+ },
215
+ };
216
+ writeFileSync(join(pluginDir, 'package.json'), JSON.stringify(packageJson, null, 2));
217
+
218
+ // Write README
219
+ const readme = `# ${name}
220
+
221
+ Custom edge-net plugin.
222
+
223
+ ## Installation
224
+
225
+ \`\`\`bash
226
+ npm install @edge-net-plugin/${name.toLowerCase().replace(/\s+/g, '-')}
227
+ \`\`\`
228
+
229
+ ## Usage
230
+
231
+ \`\`\`javascript
232
+ import { getRegistry } from '@ruvector/edge-net/plugins/sdk';
233
+ import { ${pascalName}Plugin } from './${name.toLowerCase().replace(/\s+/g, '-')}';
234
+
235
+ // Register plugin
236
+ getRegistry().register(${pascalName}Plugin);
237
+
238
+ // Use with plugin manager
239
+ const plugins = PluginManager.getInstance();
240
+ const myPlugin = await plugins.load('${id}');
241
+ \`\`\`
242
+
243
+ ## Configuration
244
+
245
+ See \`configSchema\` in the plugin manifest for available options.
246
+
247
+ ## License
248
+
249
+ MIT
250
+ `;
251
+ writeFileSync(join(pluginDir, 'README.md'), readme);
252
+
253
+ console.log(`✅ Created plugin at: ${pluginDir}`);
254
+ console.log('');
255
+ console.log('Files created:');
256
+ console.log(` 📄 ${pluginFile}`);
257
+ console.log(` 📄 ${join(pluginDir, 'package.json')}`);
258
+ console.log(` 📄 ${join(pluginDir, 'README.md')}`);
259
+ console.log('');
260
+ console.log('Next steps:');
261
+ console.log(` 1. Edit ${pluginFile} to add your logic`);
262
+ console.log(' 2. Register with: getRegistry().register(YourPlugin)');
263
+ console.log(' 3. Load with: plugins.load("' + id + '")');
264
+ console.log('');
265
+ },
266
+
267
+ /**
268
+ * Validate a plugin
269
+ */
270
+ validate: async (args) => {
271
+ const pluginPath = args[0];
272
+ if (!pluginPath) {
273
+ console.error('Usage: edge-net plugins validate <plugin-path>');
274
+ process.exit(1);
275
+ }
276
+
277
+ console.log(`\n🔍 Validating plugin: ${pluginPath}\n`);
278
+
279
+ try {
280
+ const plugin = await import(pluginPath);
281
+ const PluginClass = plugin.default || Object.values(plugin)[0];
282
+
283
+ if (!PluginClass) {
284
+ console.error('❌ No plugin class found in module');
285
+ process.exit(1);
286
+ }
287
+
288
+ // Validate manifest
289
+ if (!PluginClass.manifest) {
290
+ console.error('❌ Plugin missing static manifest property');
291
+ process.exit(1);
292
+ }
293
+
294
+ const validation = validateManifest(PluginClass.manifest);
295
+
296
+ if (validation.valid) {
297
+ console.log('✅ Plugin is valid!\n');
298
+ console.log('Manifest:');
299
+ console.log(JSON.stringify(PluginClass.manifest, null, 2));
300
+ } else {
301
+ console.log('❌ Plugin validation failed:\n');
302
+ validation.errors.forEach(err => console.log(` • ${err}`));
303
+ process.exit(1);
304
+ }
305
+ } catch (error) {
306
+ console.error(`❌ Error loading plugin: ${error.message}`);
307
+ process.exit(1);
308
+ }
309
+ },
310
+
311
+ /**
312
+ * Show help
313
+ */
314
+ help: async () => {
315
+ console.log(`
316
+ Edge-Net Plugin Management
317
+
318
+ Usage: edge-net plugins <command> [options]
319
+
320
+ Commands:
321
+ list [category] List available plugins (filter by category/tier)
322
+ info <id> Show detailed plugin information
323
+ bundles List plugin bundles
324
+ create <name> Create new plugin from template
325
+ validate <path> Validate a custom plugin file
326
+
327
+ Categories:
328
+ core, network, crypto, privacy, ai, economic, storage, exotic
329
+
330
+ Tiers:
331
+ stable, beta, experimental, research
332
+
333
+ Examples:
334
+ edge-net plugins list
335
+ edge-net plugins list privacy
336
+ edge-net plugins info crypto.zk-proofs
337
+ edge-net plugins bundles
338
+ edge-net plugins create my-plugin --category ai
339
+ edge-net plugins validate ./my-plugin/index.js
340
+ `);
341
+ },
342
+ };
343
+
344
+ // ============================================
345
+ // HELPERS
346
+ // ============================================
347
+
348
+ function getTierBadge(tier) {
349
+ const badges = {
350
+ stable: '🟢 STABLE',
351
+ beta: '🟡 BETA',
352
+ experimental: '🟠 EXPERIMENTAL',
353
+ research: '🔴 RESEARCH',
354
+ };
355
+ return badges[tier] || tier;
356
+ }
357
+
358
+ function getStatusIcon(plugin) {
359
+ // In real implementation, check if enabled
360
+ return '○';
361
+ }
362
+
363
+ function getArg(args, flag) {
364
+ const idx = args.indexOf(flag);
365
+ if (idx >= 0 && args[idx + 1]) {
366
+ return args[idx + 1];
367
+ }
368
+ return null;
369
+ }
370
+
371
+ // ============================================
372
+ // MAIN
373
+ // ============================================
374
+
375
+ async function main() {
376
+ const args = process.argv.slice(2);
377
+ const command = args[0] || 'help';
378
+ const commandArgs = args.slice(1);
379
+
380
+ if (commands[command]) {
381
+ await commands[command](commandArgs);
382
+ } else {
383
+ console.error(`Unknown command: ${command}`);
384
+ await commands.help();
385
+ process.exit(1);
386
+ }
387
+ }
388
+
389
+ // Run if executed directly
390
+ if (process.argv[1]?.includes('cli.js') || process.argv[1]?.includes('plugins')) {
391
+ main().catch(console.error);
392
+ }
393
+
394
+ export { commands };
395
+ export default main;
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Data Compression Plugin
3
+ *
4
+ * LZ4/Zstd compression for network payloads and storage.
5
+ * Uses WASM for high-performance compression.
6
+ *
7
+ * @module @ruvector/edge-net/plugins/compression
8
+ */
9
+
10
+ // Simple LZ4-like compression (for demo - use actual WASM in production)
11
+ export class CompressionPlugin {
12
+ constructor(config = {}) {
13
+ this.config = {
14
+ algorithm: config.algorithm || 'lz4',
15
+ level: config.level || 3,
16
+ threshold: config.threshold || 1024,
17
+ };
18
+ this.stats = {
19
+ compressed: 0,
20
+ decompressed: 0,
21
+ bytesIn: 0,
22
+ bytesOut: 0,
23
+ ratio: 0,
24
+ };
25
+ }
26
+
27
+ /**
28
+ * Compress data if above threshold
29
+ */
30
+ compress(data) {
31
+ const input = typeof data === 'string' ? Buffer.from(data) : data;
32
+
33
+ if (input.length < this.config.threshold) {
34
+ return { compressed: false, data: input };
35
+ }
36
+
37
+ // Simple RLE-based compression (demo)
38
+ const compressed = this._rleCompress(input);
39
+
40
+ this.stats.compressed++;
41
+ this.stats.bytesIn += input.length;
42
+ this.stats.bytesOut += compressed.length;
43
+ this.stats.ratio = this.stats.bytesOut / this.stats.bytesIn;
44
+
45
+ return {
46
+ compressed: true,
47
+ data: compressed,
48
+ originalSize: input.length,
49
+ compressedSize: compressed.length,
50
+ ratio: compressed.length / input.length,
51
+ };
52
+ }
53
+
54
+ /**
55
+ * Decompress data
56
+ */
57
+ decompress(data, wasCompressed = true) {
58
+ if (!wasCompressed) {
59
+ return data;
60
+ }
61
+
62
+ const decompressed = this._rleDecompress(data);
63
+ this.stats.decompressed++;
64
+
65
+ return decompressed;
66
+ }
67
+
68
+ /**
69
+ * Simple RLE compression (for demo)
70
+ */
71
+ _rleCompress(input) {
72
+ const output = [];
73
+ let i = 0;
74
+
75
+ while (i < input.length) {
76
+ const byte = input[i];
77
+ let count = 1;
78
+
79
+ while (i + count < input.length &&
80
+ input[i + count] === byte &&
81
+ count < 255) {
82
+ count++;
83
+ }
84
+
85
+ if (count >= 4) {
86
+ output.push(0xFF, count, byte);
87
+ } else {
88
+ for (let j = 0; j < count; j++) {
89
+ if (byte === 0xFF) {
90
+ output.push(0xFF, 1, byte);
91
+ } else {
92
+ output.push(byte);
93
+ }
94
+ }
95
+ }
96
+
97
+ i += count;
98
+ }
99
+
100
+ return Buffer.from(output);
101
+ }
102
+
103
+ /**
104
+ * Simple RLE decompression
105
+ */
106
+ _rleDecompress(input) {
107
+ const output = [];
108
+ let i = 0;
109
+
110
+ while (i < input.length) {
111
+ if (input[i] === 0xFF && i + 2 < input.length) {
112
+ const count = input[i + 1];
113
+ const byte = input[i + 2];
114
+ for (let j = 0; j < count; j++) {
115
+ output.push(byte);
116
+ }
117
+ i += 3;
118
+ } else {
119
+ output.push(input[i]);
120
+ i++;
121
+ }
122
+ }
123
+
124
+ return Buffer.from(output);
125
+ }
126
+
127
+ getStats() {
128
+ return this.stats;
129
+ }
130
+ }
131
+
132
+ export default CompressionPlugin;