@ruvector/edge-net 0.3.0 → 0.4.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/cli.js +113 -0
- package/firebase-setup.js +435 -0
- package/firebase-signaling.js +788 -0
- package/p2p.js +129 -4
- package/package.json +28 -4
package/p2p.js
CHANGED
|
@@ -20,6 +20,7 @@ import { SignalingClient } from './signaling.js';
|
|
|
20
20
|
import { SyncManager } from './sync.js';
|
|
21
21
|
import { QDAG } from './qdag.js';
|
|
22
22
|
import { Ledger } from './ledger.js';
|
|
23
|
+
import { HybridBootstrap, FirebaseLedgerSync } from './firebase-signaling.js';
|
|
23
24
|
|
|
24
25
|
// ============================================
|
|
25
26
|
// P2P NETWORK CONFIGURATION
|
|
@@ -32,7 +33,10 @@ export const P2P_CONFIG = {
|
|
|
32
33
|
webrtc: true,
|
|
33
34
|
dht: true,
|
|
34
35
|
sync: true,
|
|
36
|
+
firebase: true, // Use Firebase for bootstrap
|
|
35
37
|
},
|
|
38
|
+
// Bootstrap strategy: 'firebase' | 'local' | 'dht-only'
|
|
39
|
+
bootstrapStrategy: 'firebase',
|
|
36
40
|
// Connection settings
|
|
37
41
|
maxPeers: 50,
|
|
38
42
|
minPeers: 3,
|
|
@@ -43,6 +47,18 @@ export const P2P_CONFIG = {
|
|
|
43
47
|
dhtAnnounceInterval: 60000,
|
|
44
48
|
// Sync settings
|
|
45
49
|
syncInterval: 30000,
|
|
50
|
+
// Firebase settings (optional override)
|
|
51
|
+
firebase: {
|
|
52
|
+
// Default uses public edge-net Firebase
|
|
53
|
+
// Override with your own project for production
|
|
54
|
+
projectId: null,
|
|
55
|
+
apiKey: null,
|
|
56
|
+
},
|
|
57
|
+
// Migration thresholds
|
|
58
|
+
migration: {
|
|
59
|
+
dhtPeerThreshold: 5, // Peers needed before reducing Firebase dependency
|
|
60
|
+
p2pPeerThreshold: 10, // Peers needed for full P2P mode
|
|
61
|
+
},
|
|
46
62
|
};
|
|
47
63
|
|
|
48
64
|
// ============================================
|
|
@@ -75,6 +91,10 @@ export class P2PNetwork extends EventEmitter {
|
|
|
75
91
|
this.qdag = null;
|
|
76
92
|
this.ledger = null;
|
|
77
93
|
|
|
94
|
+
// Firebase bootstrap (Google Cloud)
|
|
95
|
+
this.hybridBootstrap = null;
|
|
96
|
+
this.firebaseLedgerSync = null;
|
|
97
|
+
|
|
78
98
|
// State
|
|
79
99
|
this.state = 'stopped';
|
|
80
100
|
this.peers = new Map();
|
|
@@ -107,8 +127,12 @@ export class P2PNetwork extends EventEmitter {
|
|
|
107
127
|
this.ledger = new Ledger({ nodeId: this.nodeId });
|
|
108
128
|
console.log(' ✅ Ledger initialized');
|
|
109
129
|
|
|
110
|
-
//
|
|
111
|
-
if (this.options.autoStart.
|
|
130
|
+
// Start Firebase bootstrap (Google Cloud) - Primary path
|
|
131
|
+
if (this.options.autoStart.firebase && this.options.bootstrapStrategy === 'firebase') {
|
|
132
|
+
await this.startFirebaseBootstrap();
|
|
133
|
+
}
|
|
134
|
+
// Fallback: Try local signaling server
|
|
135
|
+
else if (this.options.autoStart.signaling) {
|
|
112
136
|
await this.startSignaling();
|
|
113
137
|
}
|
|
114
138
|
|
|
@@ -127,6 +151,14 @@ export class P2PNetwork extends EventEmitter {
|
|
|
127
151
|
await this.startSync();
|
|
128
152
|
}
|
|
129
153
|
|
|
154
|
+
// Start Firebase hybrid bootstrap after WebRTC/DHT are ready
|
|
155
|
+
if (this.hybridBootstrap && this.webrtc) {
|
|
156
|
+
await this.hybridBootstrap.start(this.webrtc, this.dht);
|
|
157
|
+
|
|
158
|
+
// Also start Firebase ledger sync
|
|
159
|
+
await this.startFirebaseLedgerSync();
|
|
160
|
+
}
|
|
161
|
+
|
|
130
162
|
// Wire up event handlers
|
|
131
163
|
this.setupEventHandlers();
|
|
132
164
|
|
|
@@ -159,6 +191,11 @@ export class P2PNetwork extends EventEmitter {
|
|
|
159
191
|
|
|
160
192
|
this.state = 'stopping';
|
|
161
193
|
|
|
194
|
+
// Stop Firebase components
|
|
195
|
+
if (this.hybridBootstrap) await this.hybridBootstrap.stop();
|
|
196
|
+
if (this.firebaseLedgerSync) this.firebaseLedgerSync.stop();
|
|
197
|
+
|
|
198
|
+
// Stop P2P components
|
|
162
199
|
if (this.syncManager) this.syncManager.stop();
|
|
163
200
|
if (this.dht) this.dht.stop();
|
|
164
201
|
if (this.webrtc) this.webrtc.close();
|
|
@@ -171,7 +208,69 @@ export class P2PNetwork extends EventEmitter {
|
|
|
171
208
|
}
|
|
172
209
|
|
|
173
210
|
/**
|
|
174
|
-
* Start
|
|
211
|
+
* Start Firebase hybrid bootstrap (Google Cloud)
|
|
212
|
+
* Primary bootstrap path - uses Firebase for discovery, migrates to P2P
|
|
213
|
+
*/
|
|
214
|
+
async startFirebaseBootstrap() {
|
|
215
|
+
try {
|
|
216
|
+
this.hybridBootstrap = new HybridBootstrap({
|
|
217
|
+
peerId: this.nodeId,
|
|
218
|
+
firebaseConfig: this.options.firebase?.projectId ? {
|
|
219
|
+
apiKey: this.options.firebase.apiKey,
|
|
220
|
+
projectId: this.options.firebase.projectId,
|
|
221
|
+
authDomain: `${this.options.firebase.projectId}.firebaseapp.com`,
|
|
222
|
+
databaseURL: `https://${this.options.firebase.projectId}-default-rtdb.firebaseio.com`,
|
|
223
|
+
} : undefined,
|
|
224
|
+
dhtPeerThreshold: this.options.migration?.dhtPeerThreshold,
|
|
225
|
+
p2pPeerThreshold: this.options.migration?.p2pPeerThreshold,
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
// Wire up bootstrap events
|
|
229
|
+
this.hybridBootstrap.on('peer-discovered', ({ peerId, source }) => {
|
|
230
|
+
console.log(` 🔍 Discovered peer via ${source}: ${peerId.slice(0, 8)}...`);
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
this.hybridBootstrap.on('mode-changed', ({ from, to }) => {
|
|
234
|
+
console.log(` 🔄 Bootstrap mode: ${from} → ${to}`);
|
|
235
|
+
this.emit('bootstrap-mode-changed', { from, to });
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
// Start will be called after WebRTC/DHT init
|
|
239
|
+
console.log(' ✅ Firebase bootstrap initialized');
|
|
240
|
+
|
|
241
|
+
} catch (err) {
|
|
242
|
+
console.log(' ⚠️ Firebase bootstrap failed:', err.message);
|
|
243
|
+
// Fall back to local signaling
|
|
244
|
+
await this.startSignaling();
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Start Firebase ledger sync
|
|
250
|
+
*/
|
|
251
|
+
async startFirebaseLedgerSync() {
|
|
252
|
+
if (!this.ledger) return;
|
|
253
|
+
|
|
254
|
+
try {
|
|
255
|
+
this.firebaseLedgerSync = new FirebaseLedgerSync(this.ledger, {
|
|
256
|
+
peerId: this.nodeId,
|
|
257
|
+
firebaseConfig: this.options.firebase?.projectId ? {
|
|
258
|
+
apiKey: this.options.firebase.apiKey,
|
|
259
|
+
projectId: this.options.firebase.projectId,
|
|
260
|
+
} : undefined,
|
|
261
|
+
syncInterval: this.options.syncInterval,
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
await this.firebaseLedgerSync.start();
|
|
265
|
+
console.log(' ✅ Firebase ledger sync started');
|
|
266
|
+
|
|
267
|
+
} catch (err) {
|
|
268
|
+
console.log(' ⚠️ Firebase ledger sync failed:', err.message);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Start signaling client (fallback for local development)
|
|
175
274
|
*/
|
|
176
275
|
async startSignaling() {
|
|
177
276
|
try {
|
|
@@ -182,7 +281,7 @@ export class P2PNetwork extends EventEmitter {
|
|
|
182
281
|
|
|
183
282
|
const connected = await this.signaling.connect();
|
|
184
283
|
if (connected) {
|
|
185
|
-
console.log(' ✅ Signaling connected');
|
|
284
|
+
console.log(' ✅ Signaling connected (local)');
|
|
186
285
|
} else {
|
|
187
286
|
console.log(' ⚠️ Signaling unavailable (will use DHT)');
|
|
188
287
|
}
|
|
@@ -520,8 +619,18 @@ export class P2PNetwork extends EventEmitter {
|
|
|
520
619
|
|
|
521
620
|
/**
|
|
522
621
|
* Get connection mode
|
|
622
|
+
* Returns the current bootstrap/connectivity mode
|
|
523
623
|
*/
|
|
524
624
|
getMode() {
|
|
625
|
+
// Check Firebase hybrid bootstrap mode first
|
|
626
|
+
if (this.hybridBootstrap) {
|
|
627
|
+
const bootstrapMode = this.hybridBootstrap.mode;
|
|
628
|
+
if (bootstrapMode === 'p2p') return 'full-p2p';
|
|
629
|
+
if (bootstrapMode === 'hybrid') return 'firebase-hybrid';
|
|
630
|
+
if (bootstrapMode === 'firebase') return 'firebase-bootstrap';
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
// Legacy mode detection
|
|
525
634
|
if (this.webrtc?.mode === 'webrtc' && this.signaling?.isConnected) {
|
|
526
635
|
return 'full-p2p';
|
|
527
636
|
}
|
|
@@ -534,16 +643,32 @@ export class P2PNetwork extends EventEmitter {
|
|
|
534
643
|
return 'local';
|
|
535
644
|
}
|
|
536
645
|
|
|
646
|
+
/**
|
|
647
|
+
* Get bootstrap mode (firebase/hybrid/p2p)
|
|
648
|
+
*/
|
|
649
|
+
getBootstrapMode() {
|
|
650
|
+
return this.hybridBootstrap?.mode || 'none';
|
|
651
|
+
}
|
|
652
|
+
|
|
537
653
|
/**
|
|
538
654
|
* Get network statistics
|
|
539
655
|
*/
|
|
540
656
|
getStats() {
|
|
657
|
+
const bootstrapStats = this.hybridBootstrap?.getStats() || {};
|
|
658
|
+
|
|
541
659
|
return {
|
|
542
660
|
...this.stats,
|
|
543
661
|
nodeId: this.nodeId,
|
|
544
662
|
state: this.state,
|
|
545
663
|
mode: this.getMode(),
|
|
664
|
+
bootstrapMode: this.getBootstrapMode(),
|
|
546
665
|
peers: this.peers.size,
|
|
666
|
+
// Firebase stats
|
|
667
|
+
firebaseConnected: bootstrapStats.firebaseConnected || false,
|
|
668
|
+
firebasePeers: bootstrapStats.firebasePeers || 0,
|
|
669
|
+
firebaseSignals: bootstrapStats.firebaseSignals || 0,
|
|
670
|
+
p2pSignals: bootstrapStats.p2pSignals || 0,
|
|
671
|
+
// Legacy signaling
|
|
547
672
|
signalingConnected: this.signaling?.isConnected || false,
|
|
548
673
|
webrtcMode: this.webrtc?.mode || 'none',
|
|
549
674
|
dhtPeers: this.dht?.getPeers().length || 0,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ruvector/edge-net",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Distributed compute intelligence network with AI agents and workers - contribute browser compute, spawn distributed AI agents, earn credits. Features 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",
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
"edge-net": "./cli.js",
|
|
11
11
|
"ruvector-edge": "./cli.js",
|
|
12
12
|
"edge-net-join": "./join.js",
|
|
13
|
-
"edge-net-genesis": "./genesis.js"
|
|
13
|
+
"edge-net-genesis": "./genesis.js",
|
|
14
|
+
"edge-net-firebase-setup": "./firebase-setup.js"
|
|
14
15
|
},
|
|
15
16
|
"keywords": [
|
|
16
17
|
"wasm",
|
|
@@ -49,7 +50,12 @@
|
|
|
49
50
|
"kademlia",
|
|
50
51
|
"genesis-node",
|
|
51
52
|
"turn-server",
|
|
52
|
-
"nat-traversal"
|
|
53
|
+
"nat-traversal",
|
|
54
|
+
"google-cloud",
|
|
55
|
+
"firebase",
|
|
56
|
+
"gcloud",
|
|
57
|
+
"firestore",
|
|
58
|
+
"realtime-database"
|
|
53
59
|
],
|
|
54
60
|
"author": "RuVector Team <team@ruvector.dev>",
|
|
55
61
|
"license": "MIT",
|
|
@@ -88,6 +94,8 @@
|
|
|
88
94
|
"dht.js",
|
|
89
95
|
"genesis.js",
|
|
90
96
|
"p2p.js",
|
|
97
|
+
"firebase-signaling.js",
|
|
98
|
+
"firebase-setup.js",
|
|
91
99
|
"README.md",
|
|
92
100
|
"LICENSE"
|
|
93
101
|
],
|
|
@@ -146,6 +154,12 @@
|
|
|
146
154
|
},
|
|
147
155
|
"./p2p": {
|
|
148
156
|
"import": "./p2p.js"
|
|
157
|
+
},
|
|
158
|
+
"./firebase-signaling": {
|
|
159
|
+
"import": "./firebase-signaling.js"
|
|
160
|
+
},
|
|
161
|
+
"./firebase-setup": {
|
|
162
|
+
"import": "./firebase-setup.js"
|
|
149
163
|
}
|
|
150
164
|
},
|
|
151
165
|
"sideEffects": [
|
|
@@ -168,11 +182,21 @@
|
|
|
168
182
|
"genesis": "node genesis.js",
|
|
169
183
|
"genesis:start": "node genesis.js --port 8787",
|
|
170
184
|
"p2p": "node -e \"import('./p2p.js').then(m => m.createP2PNetwork({ nodeId: 'test' }))\"",
|
|
171
|
-
"monitor": "node -e \"import('./monitor.js').then(m => { const mon = new m.Monitor(); mon.start(); setInterval(() => console.log(JSON.stringify(mon.generateReport(), null, 2)), 5000); })\""
|
|
185
|
+
"monitor": "node -e \"import('./monitor.js').then(m => { const mon = new m.Monitor(); mon.start(); setInterval(() => console.log(JSON.stringify(mon.generateReport(), null, 2)), 5000); })\"",
|
|
186
|
+
"firebase:setup": "node firebase-setup.js",
|
|
187
|
+
"firebase:check": "node firebase-setup.js --check"
|
|
172
188
|
},
|
|
173
189
|
"dependencies": {
|
|
174
190
|
"@ruvector/ruvllm": "^0.2.3",
|
|
175
191
|
"@xenova/transformers": "^2.17.2",
|
|
176
192
|
"ws": "^8.18.3"
|
|
193
|
+
},
|
|
194
|
+
"peerDependencies": {
|
|
195
|
+
"firebase": "^10.0.0"
|
|
196
|
+
},
|
|
197
|
+
"peerDependenciesMeta": {
|
|
198
|
+
"firebase": {
|
|
199
|
+
"optional": true
|
|
200
|
+
}
|
|
177
201
|
}
|
|
178
202
|
}
|