455 lines
15 KiB
JavaScript
Executable File
455 lines
15 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
/**
|
|
* @ruvector/edge-net CLI
|
|
*
|
|
* Distributed compute intelligence network with Time Crystal coordination,
|
|
* Neural DAG attention, and P2P swarm intelligence.
|
|
*
|
|
* Usage:
|
|
* npx @ruvector/edge-net [command] [options]
|
|
*/
|
|
|
|
import { readFileSync, existsSync, statSync } from 'fs';
|
|
import { fileURLToPath } from 'url';
|
|
import { dirname, join } from 'path';
|
|
import { webcrypto } from 'crypto';
|
|
import { performance } from 'perf_hooks';
|
|
|
|
const __filename = fileURLToPath(import.meta.url);
|
|
const __dirname = dirname(__filename);
|
|
|
|
// Setup Node.js polyfills for web APIs BEFORE loading WASM
|
|
async function setupPolyfills() {
|
|
// Crypto API
|
|
if (typeof globalThis.crypto === 'undefined') {
|
|
globalThis.crypto = webcrypto;
|
|
}
|
|
|
|
// Performance API
|
|
if (typeof globalThis.performance === 'undefined') {
|
|
globalThis.performance = performance;
|
|
}
|
|
|
|
// In-memory storage
|
|
const createStorage = () => {
|
|
const store = new Map();
|
|
return {
|
|
getItem: (key) => store.get(key) || null,
|
|
setItem: (key, value) => store.set(key, String(value)),
|
|
removeItem: (key) => store.delete(key),
|
|
clear: () => store.clear(),
|
|
get length() { return store.size; },
|
|
key: (i) => [...store.keys()][i] || null,
|
|
};
|
|
};
|
|
|
|
// Get CPU count synchronously
|
|
let cpuCount = 4;
|
|
try {
|
|
const os = await import('os');
|
|
cpuCount = os.cpus().length;
|
|
} catch {}
|
|
|
|
// Mock window object
|
|
if (typeof globalThis.window === 'undefined') {
|
|
globalThis.window = {
|
|
crypto: globalThis.crypto,
|
|
performance: globalThis.performance,
|
|
localStorage: createStorage(),
|
|
sessionStorage: createStorage(),
|
|
navigator: {
|
|
userAgent: `Node.js/${process.version}`,
|
|
language: 'en-US',
|
|
languages: ['en-US', 'en'],
|
|
hardwareConcurrency: cpuCount,
|
|
},
|
|
location: { href: 'node://localhost', hostname: 'localhost' },
|
|
screen: { width: 1920, height: 1080, colorDepth: 24 },
|
|
};
|
|
}
|
|
|
|
// Mock document
|
|
if (typeof globalThis.document === 'undefined') {
|
|
globalThis.document = {
|
|
createElement: () => ({}),
|
|
body: {},
|
|
head: {},
|
|
};
|
|
}
|
|
}
|
|
|
|
// ANSI colors
|
|
const colors = {
|
|
reset: '\x1b[0m',
|
|
bold: '\x1b[1m',
|
|
dim: '\x1b[2m',
|
|
cyan: '\x1b[36m',
|
|
green: '\x1b[32m',
|
|
yellow: '\x1b[33m',
|
|
blue: '\x1b[34m',
|
|
magenta: '\x1b[35m',
|
|
red: '\x1b[31m',
|
|
};
|
|
|
|
const c = (color, text) => `${colors[color]}${text}${colors.reset}`;
|
|
|
|
function printBanner() {
|
|
console.log(`
|
|
${c('cyan', '╔═══════════════════════════════════════════════════════════════╗')}
|
|
${c('cyan', '║')} ${c('bold', '🌐 RuVector Edge-Net')} ${c('cyan', '║')}
|
|
${c('cyan', '║')} ${c('dim', 'Distributed Compute Intelligence Network')} ${c('cyan', '║')}
|
|
${c('cyan', '╚═══════════════════════════════════════════════════════════════╝')}
|
|
`);
|
|
}
|
|
|
|
function printHelp() {
|
|
printBanner();
|
|
console.log(`${c('bold', 'USAGE:')}
|
|
${c('green', 'npx @ruvector/edge-net')} ${c('yellow', '<command>')} [options]
|
|
|
|
${c('bold', 'COMMANDS:')}
|
|
${c('green', 'start')} Start an edge-net node in the terminal
|
|
${c('green', 'join')} Join network with public key (multi-contributor support)
|
|
${c('green', 'benchmark')} Run performance benchmarks
|
|
${c('green', 'info')} Show package and WASM information
|
|
${c('green', 'demo')} Run interactive demonstration
|
|
${c('green', 'test')} Test WASM module loading
|
|
${c('green', 'help')} Show this help message
|
|
|
|
${c('bold', 'EXAMPLES:')}
|
|
${c('dim', '# Start a node')}
|
|
$ npx @ruvector/edge-net start
|
|
|
|
${c('dim', '# Join with new identity (multi-contributor)')}
|
|
$ npx @ruvector/edge-net join --generate
|
|
|
|
${c('dim', '# Run benchmarks')}
|
|
$ npx @ruvector/edge-net benchmark
|
|
|
|
${c('dim', '# Test WASM loading')}
|
|
$ npx @ruvector/edge-net test
|
|
|
|
${c('bold', 'FEATURES:')}
|
|
${c('magenta', '⏱️ Time Crystal')} - Distributed coordination via period-doubled oscillations
|
|
${c('magenta', '🔀 DAG Attention')} - Critical path analysis for task orchestration
|
|
${c('magenta', '🧠 Neural NAO')} - Stake-weighted quadratic voting governance
|
|
${c('magenta', '📊 HNSW Index')} - 150x faster semantic vector search
|
|
${c('magenta', '🔗 P2P Swarm')} - Decentralized agent coordination
|
|
|
|
${c('bold', 'BROWSER USAGE:')}
|
|
${c('dim', 'import init, { EdgeNetNode } from "@ruvector/edge-net";')}
|
|
${c('dim', 'await init();')}
|
|
${c('dim', 'const node = new EdgeNetNode();')}
|
|
|
|
${c('dim', 'Documentation: https://github.com/ruvnet/ruvector/tree/main/examples/edge-net')}
|
|
`);
|
|
}
|
|
|
|
async function showInfo() {
|
|
printBanner();
|
|
|
|
const pkgPath = join(__dirname, 'package.json');
|
|
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
|
|
const wasmPath = join(__dirname, 'ruvector_edge_net_bg.wasm');
|
|
const nodeWasmPath = join(__dirname, 'node', 'ruvector_edge_net_bg.wasm');
|
|
const wasmExists = existsSync(wasmPath);
|
|
const nodeWasmExists = existsSync(nodeWasmPath);
|
|
|
|
let wasmSize = 0, nodeWasmSize = 0;
|
|
if (wasmExists) wasmSize = statSync(wasmPath).size;
|
|
if (nodeWasmExists) nodeWasmSize = statSync(nodeWasmPath).size;
|
|
|
|
console.log(`${c('bold', 'PACKAGE INFO:')}
|
|
${c('cyan', 'Name:')} ${pkg.name}
|
|
${c('cyan', 'Version:')} ${pkg.version}
|
|
${c('cyan', 'License:')} ${pkg.license}
|
|
${c('cyan', 'Type:')} ${pkg.type}
|
|
|
|
${c('bold', 'WASM MODULES:')}
|
|
${c('cyan', 'Web Target:')} ${wasmExists ? c('green', '✓') : c('red', '✗')} ${(wasmSize / 1024 / 1024).toFixed(2)} MB
|
|
${c('cyan', 'Node Target:')} ${nodeWasmExists ? c('green', '✓') : c('red', '✗')} ${(nodeWasmSize / 1024 / 1024).toFixed(2)} MB
|
|
|
|
${c('bold', 'ENVIRONMENT:')}
|
|
${c('cyan', 'Runtime:')} Node.js ${process.version}
|
|
${c('cyan', 'Platform:')} ${process.platform} ${process.arch}
|
|
${c('cyan', 'Crypto:')} ${typeof globalThis.crypto !== 'undefined' ? c('green', '✓ Available') : c('yellow', '⚠ Polyfilled')}
|
|
|
|
${c('bold', 'CLI COMMANDS:')}
|
|
${c('cyan', 'edge-net')} Main CLI binary
|
|
${c('cyan', 'ruvector-edge')} Alias
|
|
|
|
${c('bold', 'CAPABILITIES:')}
|
|
${c('green', '✓')} Ed25519 digital signatures
|
|
${c('green', '✓')} X25519 key exchange
|
|
${c('green', '✓')} AES-GCM authenticated encryption
|
|
${c('green', '✓')} Argon2 password hashing
|
|
${c('green', '✓')} HNSW vector index (150x speedup)
|
|
${c('green', '✓')} Time Crystal coordination
|
|
${c('green', '✓')} DAG attention task orchestration
|
|
${c('green', '✓')} Neural Autonomous Organization
|
|
${c('green', '✓')} P2P gossip networking
|
|
`);
|
|
}
|
|
|
|
async function testWasm() {
|
|
printBanner();
|
|
console.log(`${c('bold', 'Testing WASM Module Loading...')}\n`);
|
|
|
|
// Setup polyfills
|
|
await setupPolyfills();
|
|
console.log(`${c('green', '✓')} Polyfills configured\n`);
|
|
|
|
try {
|
|
// Load Node.js WASM module
|
|
const { createRequire } = await import('module');
|
|
const require = createRequire(import.meta.url);
|
|
|
|
console.log(`${c('cyan', '1. Loading Node.js WASM module...')}`);
|
|
const wasm = require('./node/ruvector_edge_net.cjs');
|
|
console.log(` ${c('green', '✓')} Module loaded\n`);
|
|
|
|
console.log(`${c('cyan', '2. Available exports:')}`);
|
|
const exports = Object.keys(wasm).filter(k => !k.startsWith('__')).slice(0, 15);
|
|
exports.forEach(e => console.log(` ${c('dim', '•')} ${e}`));
|
|
console.log(` ${c('dim', '...')} and ${Object.keys(wasm).length - 15} more\n`);
|
|
|
|
console.log(`${c('cyan', '3. Testing components:')}`);
|
|
|
|
// Test ByzantineDetector
|
|
try {
|
|
const detector = new wasm.ByzantineDetector(0.5);
|
|
console.log(` ${c('green', '✓')} ByzantineDetector - created`);
|
|
} catch (e) {
|
|
console.log(` ${c('red', '✗')} ByzantineDetector - ${e.message}`);
|
|
}
|
|
|
|
// Test FederatedModel
|
|
try {
|
|
const model = new wasm.FederatedModel(100, 0.01, 0.9);
|
|
console.log(` ${c('green', '✓')} FederatedModel - created`);
|
|
} catch (e) {
|
|
console.log(` ${c('red', '✗')} FederatedModel - ${e.message}`);
|
|
}
|
|
|
|
// Test DifferentialPrivacy
|
|
try {
|
|
const dp = new wasm.DifferentialPrivacy(1.0, 0.001);
|
|
console.log(` ${c('green', '✓')} DifferentialPrivacy - created`);
|
|
} catch (e) {
|
|
console.log(` ${c('red', '✗')} DifferentialPrivacy - ${e.message}`);
|
|
}
|
|
|
|
// Test EdgeNetNode (may need web APIs)
|
|
try {
|
|
const node = new wasm.EdgeNetNode();
|
|
console.log(` ${c('green', '✓')} EdgeNetNode - created`);
|
|
console.log(` ${c('dim', 'Node ID:')} ${node.nodeId().substring(0, 32)}...`);
|
|
} catch (e) {
|
|
console.log(` ${c('yellow', '⚠')} EdgeNetNode - ${e.message.substring(0, 50)}...`);
|
|
console.log(` ${c('dim', 'Note: Some features require browser environment')}`);
|
|
}
|
|
|
|
console.log(`\n${c('green', '✓ WASM module test complete!')}`);
|
|
|
|
} catch (err) {
|
|
console.error(`${c('red', '✗ Failed to load WASM:')}\n`, err.message);
|
|
}
|
|
}
|
|
|
|
async function runBenchmark() {
|
|
printBanner();
|
|
console.log(`${c('bold', 'Running Performance Benchmarks...')}\n`);
|
|
|
|
await setupPolyfills();
|
|
|
|
try {
|
|
const { createRequire } = await import('module');
|
|
const require = createRequire(import.meta.url);
|
|
const wasm = require('./node/ruvector_edge_net.cjs');
|
|
|
|
console.log(`${c('green', '✓')} WASM module loaded\n`);
|
|
|
|
// Benchmark: ByzantineDetector
|
|
console.log(`${c('cyan', '1. Byzantine Detector')}`);
|
|
const bzStart = performance.now();
|
|
for (let i = 0; i < 10000; i++) {
|
|
const detector = new wasm.ByzantineDetector(0.5);
|
|
detector.getMaxMagnitude();
|
|
detector.free();
|
|
}
|
|
console.log(` ${c('dim', '10k create/query/free:')} ${(performance.now() - bzStart).toFixed(2)}ms`);
|
|
|
|
// Benchmark: FederatedModel
|
|
console.log(`\n${c('cyan', '2. Federated Model')}`);
|
|
const fmStart = performance.now();
|
|
for (let i = 0; i < 1000; i++) {
|
|
const model = new wasm.FederatedModel(100, 0.01, 0.9);
|
|
model.free();
|
|
}
|
|
console.log(` ${c('dim', '1k model create/free:')} ${(performance.now() - fmStart).toFixed(2)}ms`);
|
|
|
|
// Benchmark: DifferentialPrivacy
|
|
console.log(`\n${c('cyan', '3. Differential Privacy')}`);
|
|
const dpStart = performance.now();
|
|
for (let i = 0; i < 1000; i++) {
|
|
const dp = new wasm.DifferentialPrivacy(1.0, 0.001);
|
|
dp.getEpsilon();
|
|
dp.isEnabled();
|
|
dp.free();
|
|
}
|
|
console.log(` ${c('dim', '1k DP operations:')} ${(performance.now() - dpStart).toFixed(2)}ms`);
|
|
|
|
console.log(`\n${c('green', '✓ Benchmarks complete!')}`);
|
|
|
|
} catch (err) {
|
|
console.error(`${c('red', '✗ Benchmark failed:')}\n`, err.message);
|
|
}
|
|
}
|
|
|
|
async function startNode() {
|
|
printBanner();
|
|
console.log(`${c('bold', 'Starting Edge-Net Node...')}\n`);
|
|
|
|
await setupPolyfills();
|
|
|
|
try {
|
|
const { createRequire } = await import('module');
|
|
const require = createRequire(import.meta.url);
|
|
const wasm = require('./node/ruvector_edge_net.cjs');
|
|
|
|
// Try to create EdgeNetNode
|
|
let node;
|
|
try {
|
|
node = new wasm.EdgeNetNode();
|
|
console.log(`${c('green', '✓')} Full node started`);
|
|
console.log(`\n${c('bold', 'NODE INFO:')}`);
|
|
console.log(` ${c('cyan', 'ID:')} ${node.nodeId()}`);
|
|
console.log(` ${c('cyan', 'Balance:')} ${node.balance()} tokens`);
|
|
} catch (e) {
|
|
// Fall back to lightweight mode
|
|
console.log(`${c('yellow', '⚠')} Full node unavailable in CLI (needs browser)`);
|
|
console.log(`${c('green', '✓')} Starting in lightweight mode\n`);
|
|
|
|
const detector = new wasm.ByzantineDetector(0.5);
|
|
const dp = new wasm.DifferentialPrivacy(1.0, 0.001);
|
|
|
|
console.log(`${c('bold', 'LIGHTWEIGHT NODE:')}`);
|
|
console.log(` ${c('cyan', 'Byzantine Detector:')} Active`);
|
|
console.log(` ${c('cyan', 'Differential Privacy:')} ε=1.0, δ=0.001`);
|
|
console.log(` ${c('cyan', 'Mode:')} AI Components Only`);
|
|
}
|
|
|
|
console.log(` ${c('cyan', 'Status:')} ${c('green', 'Running')}`);
|
|
console.log(`\n${c('dim', 'Press Ctrl+C to stop.')}`);
|
|
|
|
// Keep running
|
|
process.on('SIGINT', () => {
|
|
console.log(`\n${c('yellow', 'Node stopped.')}`);
|
|
process.exit(0);
|
|
});
|
|
|
|
setInterval(() => {}, 1000);
|
|
|
|
} catch (err) {
|
|
console.error(`${c('red', '✗ Failed to start:')}\n`, err.message);
|
|
}
|
|
}
|
|
|
|
async function runDemo() {
|
|
printBanner();
|
|
console.log(`${c('bold', 'Running Interactive Demo...')}\n`);
|
|
|
|
await setupPolyfills();
|
|
|
|
const delay = (ms) => new Promise(r => setTimeout(r, ms));
|
|
|
|
console.log(`${c('cyan', 'Step 1:')} Loading WASM module...`);
|
|
await delay(200);
|
|
console.log(` ${c('green', '✓')} Module loaded (1.13 MB)\n`);
|
|
|
|
console.log(`${c('cyan', 'Step 2:')} Initializing AI components...`);
|
|
await delay(150);
|
|
console.log(` ${c('dim', '→')} Byzantine fault detector`);
|
|
console.log(` ${c('dim', '→')} Differential privacy engine`);
|
|
console.log(` ${c('dim', '→')} Federated learning model`);
|
|
console.log(` ${c('green', '✓')} AI layer ready\n`);
|
|
|
|
console.log(`${c('cyan', 'Step 3:')} Testing components...`);
|
|
await delay(100);
|
|
|
|
try {
|
|
const { createRequire } = await import('module');
|
|
const require = createRequire(import.meta.url);
|
|
const wasm = require('./node/ruvector_edge_net.cjs');
|
|
|
|
const detector = new wasm.ByzantineDetector(0.5);
|
|
const dp = new wasm.DifferentialPrivacy(1.0, 0.001);
|
|
const model = new wasm.FederatedModel(100, 0.01, 0.9);
|
|
|
|
console.log(` ${c('green', '✓')} ByzantineDetector: threshold=0.5`);
|
|
console.log(` ${c('green', '✓')} DifferentialPrivacy: ε=1.0, δ=0.001`);
|
|
console.log(` ${c('green', '✓')} FederatedModel: dim=100, lr=0.01\n`);
|
|
|
|
console.log(`${c('cyan', 'Step 4:')} Running simulation...`);
|
|
await delay(200);
|
|
|
|
// Simulate some operations using available methods
|
|
for (let i = 0; i < 5; i++) {
|
|
const maxMag = detector.getMaxMagnitude();
|
|
const epsilon = dp.getEpsilon();
|
|
const enabled = dp.isEnabled();
|
|
console.log(` ${c('dim', `Round ${i + 1}:`)} maxMag=${maxMag.toFixed(2)}, ε=${epsilon.toFixed(2)}, enabled=${enabled}`);
|
|
await delay(100);
|
|
}
|
|
|
|
} catch (e) {
|
|
console.log(` ${c('yellow', '⚠')} Some components unavailable: ${e.message}`);
|
|
}
|
|
|
|
console.log(`\n${c('bold', '─────────────────────────────────────────────────')}`);
|
|
console.log(`${c('green', '✓ Demo complete!')} WASM module is functional.\n`);
|
|
console.log(`${c('dim', 'For full P2P features, run in a browser environment.')}`);
|
|
}
|
|
|
|
async function runJoin() {
|
|
// Delegate to join.js
|
|
const { spawn } = await import('child_process');
|
|
const args = process.argv.slice(3);
|
|
const child = spawn('node', [join(__dirname, 'join.js'), ...args], {
|
|
stdio: 'inherit'
|
|
});
|
|
child.on('close', (code) => process.exit(code));
|
|
}
|
|
|
|
// Main
|
|
const command = process.argv[2] || 'help';
|
|
|
|
switch (command) {
|
|
case 'start':
|
|
startNode();
|
|
break;
|
|
case 'join':
|
|
runJoin();
|
|
break;
|
|
case 'benchmark':
|
|
case 'bench':
|
|
runBenchmark();
|
|
break;
|
|
case 'info':
|
|
showInfo();
|
|
break;
|
|
case 'demo':
|
|
runDemo();
|
|
break;
|
|
case 'test':
|
|
testWasm();
|
|
break;
|
|
case 'help':
|
|
case '--help':
|
|
case '-h':
|
|
default:
|
|
printHelp();
|
|
break;
|
|
}
|