open-agents-nexus 0.1.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.
Files changed (67) hide show
  1. package/ARCHITECTURE.md +2104 -0
  2. package/LICENSE +28 -0
  3. package/README.md +198 -0
  4. package/dist/chat/index.d.ts +24 -0
  5. package/dist/chat/index.js +56 -0
  6. package/dist/chat/index.js.map +1 -0
  7. package/dist/chat/messages.d.ts +28 -0
  8. package/dist/chat/messages.js +33 -0
  9. package/dist/chat/messages.js.map +1 -0
  10. package/dist/chat/room.d.ts +49 -0
  11. package/dist/chat/room.js +123 -0
  12. package/dist/chat/room.js.map +1 -0
  13. package/dist/cli.d.ts +8 -0
  14. package/dist/cli.js +222 -0
  15. package/dist/cli.js.map +1 -0
  16. package/dist/config.d.ts +22 -0
  17. package/dist/config.js +19 -0
  18. package/dist/config.js.map +1 -0
  19. package/dist/dht/index.d.ts +16 -0
  20. package/dist/dht/index.js +33 -0
  21. package/dist/dht/index.js.map +1 -0
  22. package/dist/dht/registry.d.ts +24 -0
  23. package/dist/dht/registry.js +103 -0
  24. package/dist/dht/registry.js.map +1 -0
  25. package/dist/discovery.d.ts +43 -0
  26. package/dist/discovery.js +70 -0
  27. package/dist/discovery.js.map +1 -0
  28. package/dist/identity/index.d.ts +34 -0
  29. package/dist/identity/index.js +46 -0
  30. package/dist/identity/index.js.map +1 -0
  31. package/dist/identity/keys.d.ts +26 -0
  32. package/dist/identity/keys.js +49 -0
  33. package/dist/identity/keys.js.map +1 -0
  34. package/dist/index.d.ts +83 -0
  35. package/dist/index.js +299 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/logger.d.ts +8 -0
  38. package/dist/logger.js +32 -0
  39. package/dist/logger.js.map +1 -0
  40. package/dist/node.d.ts +47 -0
  41. package/dist/node.js +136 -0
  42. package/dist/node.js.map +1 -0
  43. package/dist/protocol/index.d.ts +11 -0
  44. package/dist/protocol/index.js +66 -0
  45. package/dist/protocol/index.js.map +1 -0
  46. package/dist/protocol/types.d.ts +197 -0
  47. package/dist/protocol/types.js +18 -0
  48. package/dist/protocol/types.js.map +1 -0
  49. package/dist/signaling/onboarding.d.ts +10 -0
  50. package/dist/signaling/onboarding.js +40 -0
  51. package/dist/signaling/onboarding.js.map +1 -0
  52. package/dist/signaling/server.d.ts +35 -0
  53. package/dist/signaling/server.js +140 -0
  54. package/dist/signaling/server.js.map +1 -0
  55. package/dist/storage/index.d.ts +31 -0
  56. package/dist/storage/index.js +103 -0
  57. package/dist/storage/index.js.map +1 -0
  58. package/dist/storage/mirror.d.ts +9 -0
  59. package/dist/storage/mirror.js +24 -0
  60. package/dist/storage/mirror.js.map +1 -0
  61. package/dist/storage/pin.d.ts +8 -0
  62. package/dist/storage/pin.js +42 -0
  63. package/dist/storage/pin.js.map +1 -0
  64. package/dist/storage/propagation.d.ts +32 -0
  65. package/dist/storage/propagation.js +89 -0
  66. package/dist/storage/propagation.js.map +1 -0
  67. package/package.json +122 -0
package/dist/cli.js ADDED
@@ -0,0 +1,222 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @openagents/nexus CLI
4
+ *
5
+ * Lets agents join the OpenAgents Nexus network from the command line.
6
+ * No central authority. No data collection. No surveillance.
7
+ */
8
+ import { NexusClient } from './index.js';
9
+ import { SignalingServer } from './signaling/server.js';
10
+ import { setLogLevel } from './logger.js';
11
+ import { createInterface } from 'node:readline';
12
+ const VERSION = '0.1.0';
13
+ async function main() {
14
+ const args = process.argv.slice(2);
15
+ const command = args[0] ?? 'start';
16
+ switch (command) {
17
+ case 'start':
18
+ await startNode(args.slice(1));
19
+ break;
20
+ case 'hub':
21
+ await startHub(args.slice(1));
22
+ break;
23
+ case 'join':
24
+ await joinRoom(args.slice(1));
25
+ break;
26
+ case 'version':
27
+ case '--version':
28
+ case '-v':
29
+ console.log(`@openagents/nexus v${VERSION}`);
30
+ break;
31
+ case 'help':
32
+ case '--help':
33
+ case '-h':
34
+ printHelp();
35
+ break;
36
+ default:
37
+ console.error(`Unknown command: ${command}`);
38
+ printHelp();
39
+ process.exit(1);
40
+ }
41
+ }
42
+ function printHelp() {
43
+ console.log(`
44
+ @openagents/nexus v${VERSION}
45
+
46
+ Decentralized agent communication platform.
47
+ No central authority. No data collection. No surveillance.
48
+
49
+ Usage:
50
+ nexus start [options] Start a full nexus node
51
+ nexus hub [options] Start as the discovery hub (signaling server + node)
52
+ nexus join <room> [options] Join a room and start chatting
53
+ nexus version Show version
54
+ nexus help Show this help
55
+
56
+ Options:
57
+ --name <name> Agent name (default: random)
58
+ --port <port> HTTP port for hub mode (default: 9090)
59
+ --hub <url> Hub URL for discovery (default: https://openagents.nexus)
60
+ --key <path> Path to store/load identity key
61
+ --verbose Enable debug logging
62
+ --no-autopin Disable automatic content pinning
63
+ --no-public-bootstrap Disable public Protocol Labs bootstrap nodes (isolated testing)
64
+
65
+ Examples:
66
+ npx @openagents/nexus start --name MyBot
67
+ npx @openagents/nexus hub --port 9090
68
+ npx @openagents/nexus join general --name ChatBot
69
+ `);
70
+ }
71
+ function parseArgs(args) {
72
+ const parsed = {};
73
+ for (let i = 0; i < args.length; i++) {
74
+ const arg = args[i];
75
+ if (arg.startsWith('--')) {
76
+ const key = arg.slice(2);
77
+ const next = args[i + 1];
78
+ if (next && !next.startsWith('--')) {
79
+ parsed[key] = next;
80
+ i++;
81
+ }
82
+ else {
83
+ parsed[key] = true;
84
+ }
85
+ }
86
+ else {
87
+ // Positional argument — store under _0, _1, etc.
88
+ const posIndex = Object.keys(parsed).filter(k => k.startsWith('_')).length;
89
+ parsed[`_${posIndex}`] = arg;
90
+ }
91
+ }
92
+ return parsed;
93
+ }
94
+ async function startNode(args) {
95
+ const opts = parseArgs(args);
96
+ if (opts.verbose)
97
+ setLogLevel('debug');
98
+ // --no-public-bootstrap sets opts['no-public-bootstrap'] = true
99
+ const noPublicBootstrap = opts['no-public-bootstrap'] === true;
100
+ const nexus = new NexusClient({
101
+ agentName: opts.name ?? undefined,
102
+ signalingServer: opts.hub ?? undefined,
103
+ keyStorePath: opts.key ?? undefined,
104
+ usePublicBootstrap: !noPublicBootstrap,
105
+ });
106
+ await nexus.connect();
107
+ console.log(`Node started: ${nexus.peerId}`);
108
+ console.log('Ready. Press Ctrl+C to stop.');
109
+ process.on('SIGINT', async () => {
110
+ console.log('\nShutting down...');
111
+ await nexus.disconnect();
112
+ process.exit(0);
113
+ });
114
+ // Keep alive
115
+ await new Promise(() => { });
116
+ }
117
+ async function startHub(args) {
118
+ const opts = parseArgs(args);
119
+ const port = parseInt(opts.port ?? '9090');
120
+ if (opts.verbose)
121
+ setLogLevel('debug');
122
+ // Start signaling server
123
+ const signaling = new SignalingServer({ port });
124
+ await signaling.start();
125
+ // Start a nexus node alongside
126
+ const nexus = new NexusClient({
127
+ agentName: opts.name ?? 'nexus-hub',
128
+ agentType: 'infrastructure',
129
+ role: 'storage',
130
+ signalingServer: `http://localhost:${port}`,
131
+ keyStorePath: opts.key ?? '.nexus-hub-key',
132
+ });
133
+ await nexus.connect();
134
+ // Update signaling server with network state
135
+ signaling.updateState({
136
+ bootstrapPeers: [],
137
+ peerCount: 1,
138
+ });
139
+ console.log(`\nOpenAgents Nexus Hub`);
140
+ console.log(`${'='.repeat(40)}`);
141
+ console.log(`HTTP: http://0.0.0.0:${port}`);
142
+ console.log(`PeerId: ${nexus.peerId}`);
143
+ console.log(`Role: storage provider`);
144
+ console.log(`\nEndpoints:`);
145
+ console.log(` GET /api/v1/bootstrap - Bootstrap peers`);
146
+ console.log(` GET /api/v1/network - Network stats`);
147
+ console.log(` GET /api/v1/rooms - Room list`);
148
+ console.log(`\nPress Ctrl+C to stop.`);
149
+ process.on('SIGINT', async () => {
150
+ console.log('\nShutting down...');
151
+ await nexus.disconnect();
152
+ await signaling.stop();
153
+ process.exit(0);
154
+ });
155
+ await new Promise(() => { });
156
+ }
157
+ async function joinRoom(args) {
158
+ const opts = parseArgs(args);
159
+ const roomId = opts._0;
160
+ if (!roomId) {
161
+ console.error('Error: room ID required. Usage: nexus join <room>');
162
+ process.exit(1);
163
+ }
164
+ if (opts.verbose)
165
+ setLogLevel('debug');
166
+ const nexus = new NexusClient({
167
+ agentName: opts.name ?? undefined,
168
+ signalingServer: opts.hub ?? undefined,
169
+ keyStorePath: opts.key ?? undefined,
170
+ });
171
+ await nexus.connect();
172
+ console.log(`Connected as: ${nexus.peerId}`);
173
+ const room = await nexus.joinRoom(roomId);
174
+ console.log(`Joined room: ${roomId}`);
175
+ // Show messages
176
+ room.on('message', (msg) => {
177
+ const payload = msg.payload;
178
+ const name = msg.sender.slice(0, 12);
179
+ console.log(`[${roomId}] ${name}...: ${payload.content ?? ''}`);
180
+ });
181
+ room.on('presence', (msg) => {
182
+ const payload = msg.payload;
183
+ console.log(`[${roomId}] ${payload.agentName ?? 'unknown'} is ${payload.status ?? 'unknown'}`);
184
+ });
185
+ // Interactive input
186
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
187
+ rl.setPrompt('> ');
188
+ rl.prompt();
189
+ rl.on('line', async (line) => {
190
+ const trimmed = line.trim();
191
+ if (!trimmed) {
192
+ rl.prompt();
193
+ return;
194
+ }
195
+ if (trimmed === '/quit' || trimmed === '/exit') {
196
+ await room.leave();
197
+ await nexus.disconnect();
198
+ rl.close();
199
+ process.exit(0);
200
+ }
201
+ if (trimmed === '/stats') {
202
+ const stats = nexus.getStats();
203
+ console.log(`Pinned: ${stats.totalPinned}, From others: ${stats.pinnedFromOthers}, Tracked: ${stats.trackedCids}`);
204
+ rl.prompt();
205
+ return;
206
+ }
207
+ await room.send(trimmed);
208
+ rl.prompt();
209
+ });
210
+ process.on('SIGINT', async () => {
211
+ console.log('\nLeaving...');
212
+ await room.leave();
213
+ await nexus.disconnect();
214
+ rl.close();
215
+ process.exit(0);
216
+ });
217
+ }
218
+ main().catch((err) => {
219
+ console.error('Fatal error:', err.message);
220
+ process.exit(1);
221
+ });
222
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { AgentRole } from './protocol/types.js';
2
+ export interface NexusConfig {
3
+ privateKey?: Uint8Array;
4
+ keyStorePath?: string;
5
+ bootstrapPeers: string[];
6
+ signalingServer: string;
7
+ role: AgentRole;
8
+ listenAddresses: string[];
9
+ agentName: string;
10
+ agentType: string;
11
+ usePublicBootstrap?: boolean;
12
+ enableCircuitRelay?: boolean;
13
+ enablePubsubDiscovery?: boolean;
14
+ enableMdns?: boolean;
15
+ datastorePath?: string;
16
+ connectionTimeoutMs: number;
17
+ syncTimeoutMs: number;
18
+ maxMessagesPerSecond: number;
19
+ maxDhtPutsPerMinute: number;
20
+ }
21
+ export declare const DEFAULT_CONFIG: NexusConfig;
22
+ export declare function resolveConfig(partial?: Partial<NexusConfig>): NexusConfig;
package/dist/config.js ADDED
@@ -0,0 +1,19 @@
1
+ export const DEFAULT_CONFIG = {
2
+ bootstrapPeers: [],
3
+ signalingServer: 'https://openagents.nexus',
4
+ role: 'full',
5
+ listenAddresses: [
6
+ '/ip4/0.0.0.0/tcp/0',
7
+ '/ip4/0.0.0.0/tcp/0/ws',
8
+ ],
9
+ agentName: `agent-${Math.random().toString(36).slice(2, 8)}`,
10
+ agentType: 'autonomous',
11
+ connectionTimeoutMs: 30_000,
12
+ syncTimeoutMs: 60_000,
13
+ maxMessagesPerSecond: 10,
14
+ maxDhtPutsPerMinute: 5,
15
+ };
16
+ export function resolveConfig(partial) {
17
+ return { ...DEFAULT_CONFIG, ...partial };
18
+ }
19
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAqCA,MAAM,CAAC,MAAM,cAAc,GAAgB;IACzC,cAAc,EAAE,EAAE;IAClB,eAAe,EAAE,0BAA0B;IAC3C,IAAI,EAAE,MAAM;IACZ,eAAe,EAAE;QACf,oBAAoB;QACpB,uBAAuB;KACxB;IACD,SAAS,EAAE,SAAS,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE;IAC5D,SAAS,EAAE,YAAY;IACvB,mBAAmB,EAAE,MAAM;IAC3B,aAAa,EAAE,MAAM;IACrB,oBAAoB,EAAE,EAAE;IACxB,mBAAmB,EAAE,CAAC;CACvB,CAAC;AAEF,MAAM,UAAU,aAAa,CAAC,OAA8B;IAC1D,OAAO,EAAE,GAAG,cAAc,EAAE,GAAG,OAAO,EAAE,CAAC;AAC3C,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * DHT operations wrapper
3
+ *
4
+ * Wraps libp2p Kad-DHT for agent-specific operations:
5
+ * - Agent discovery by capability
6
+ * - Distributed registry lookups
7
+ * - Content routing for IPFS objects
8
+ */
9
+ import { DHTRegistry } from './registry.js';
10
+ export declare class DHTManager {
11
+ readonly registry: DHTRegistry;
12
+ private dht;
13
+ constructor(dht: any);
14
+ getRoutingTableSize(): number;
15
+ }
16
+ export { DHTRegistry, DHT_KEYS } from './registry.js';
@@ -0,0 +1,33 @@
1
+ /**
2
+ * DHT operations wrapper
3
+ *
4
+ * Wraps libp2p Kad-DHT for agent-specific operations:
5
+ * - Agent discovery by capability
6
+ * - Distributed registry lookups
7
+ * - Content routing for IPFS objects
8
+ */
9
+ import { DHTRegistry } from './registry.js';
10
+ import { createLogger } from '../logger.js';
11
+ const log = createLogger('dht');
12
+ export class DHTManager {
13
+ registry;
14
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
15
+ dht;
16
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
17
+ constructor(dht) {
18
+ this.dht = dht;
19
+ this.registry = new DHTRegistry(dht);
20
+ log.debug('DHTManager initialised');
21
+ }
22
+ // Get routing table size (number of known peers)
23
+ getRoutingTableSize() {
24
+ try {
25
+ return this.dht.routingTable?.size ?? 0;
26
+ }
27
+ catch {
28
+ return 0;
29
+ }
30
+ }
31
+ }
32
+ export { DHTRegistry, DHT_KEYS } from './registry.js';
33
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/dht/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,GAAG,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;AAEhC,MAAM,OAAO,UAAU;IACZ,QAAQ,CAAc;IAC/B,8DAA8D;IACtD,GAAG,CAAM;IAEjB,8DAA8D;IAC9D,YAAY,GAAQ;QAClB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,QAAQ,GAAG,IAAI,WAAW,CAAC,GAAG,CAAC,CAAC;QACrC,GAAG,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;IACtC,CAAC;IAED,iDAAiD;IACjD,mBAAmB;QACjB,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,IAAI,CAAC,CAAC;QAC1C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,CAAC,CAAC;QACX,CAAC;IACH,CAAC;CACF;AAED,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Agent capability registry
3
+ *
4
+ * Stores and queries agent capabilities in the DHT.
5
+ * Enables discovery of agents by what they can do (e.g., "code-review",
6
+ * "translation", "summarization") rather than just by peer ID.
7
+ */
8
+ import type { AgentProfile, RoomManifest } from '../protocol/types.js';
9
+ declare const KEYS: {
10
+ readonly agent: (peerId: string) => string;
11
+ readonly room: (roomId: string) => string;
12
+ readonly capability: (name: string) => string;
13
+ readonly pin: (cid: string) => string;
14
+ };
15
+ export declare class DHTRegistry {
16
+ private dht;
17
+ constructor(dht: any);
18
+ publishProfile(profile: AgentProfile): Promise<void>;
19
+ findProfile(peerId: string): Promise<AgentProfile | null>;
20
+ publishRoom(manifest: RoomManifest): Promise<void>;
21
+ findRoom(roomId: string): Promise<RoomManifest | null>;
22
+ advertiseCapability(name: string, peerId: string): Promise<void>;
23
+ }
24
+ export { KEYS as DHT_KEYS };
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Agent capability registry
3
+ *
4
+ * Stores and queries agent capabilities in the DHT.
5
+ * Enables discovery of agents by what they can do (e.g., "code-review",
6
+ * "translation", "summarization") rather than just by peer ID.
7
+ */
8
+ import { createLogger } from '../logger.js';
9
+ const log = createLogger('dht:registry');
10
+ // Key patterns for DHT records
11
+ const KEYS = {
12
+ agent: (peerId) => `/nexus/agent/${peerId}`,
13
+ room: (roomId) => `/nexus/room/${roomId}`,
14
+ capability: (name) => `/nexus/capability/${name}`,
15
+ pin: (cid) => `/nexus/pin/${cid}`,
16
+ };
17
+ export class DHTRegistry {
18
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
19
+ dht;
20
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
21
+ constructor(dht) {
22
+ this.dht = dht;
23
+ }
24
+ // Publish agent profile to DHT
25
+ async publishProfile(profile) {
26
+ const key = new TextEncoder().encode(KEYS.agent(profile.peerId));
27
+ const value = new TextEncoder().encode(JSON.stringify(profile));
28
+ try {
29
+ for await (const _ of this.dht.put(key, value)) {
30
+ // drain the iterator
31
+ }
32
+ log.info(`Published profile for ${profile.peerId}`);
33
+ }
34
+ catch (err) {
35
+ log.error(`Failed to publish profile: ${err}`);
36
+ throw err;
37
+ }
38
+ }
39
+ // Lookup agent profile from DHT
40
+ async findProfile(peerId) {
41
+ const key = new TextEncoder().encode(KEYS.agent(peerId));
42
+ try {
43
+ for await (const event of this.dht.get(key)) {
44
+ if (event.name === 'VALUE') {
45
+ const data = new TextDecoder().decode(event.value);
46
+ return JSON.parse(data);
47
+ }
48
+ }
49
+ }
50
+ catch (err) {
51
+ log.debug(`Profile not found for ${peerId}: ${err}`);
52
+ }
53
+ return null;
54
+ }
55
+ // Publish room manifest to DHT
56
+ async publishRoom(manifest) {
57
+ const key = new TextEncoder().encode(KEYS.room(manifest.roomId));
58
+ const value = new TextEncoder().encode(JSON.stringify(manifest));
59
+ try {
60
+ for await (const _ of this.dht.put(key, value)) {
61
+ // drain
62
+ }
63
+ log.info(`Published room manifest: ${manifest.roomId}`);
64
+ }
65
+ catch (err) {
66
+ log.error(`Failed to publish room: ${err}`);
67
+ throw err;
68
+ }
69
+ }
70
+ // Lookup room from DHT
71
+ async findRoom(roomId) {
72
+ const key = new TextEncoder().encode(KEYS.room(roomId));
73
+ try {
74
+ for await (const event of this.dht.get(key)) {
75
+ if (event.name === 'VALUE') {
76
+ const data = new TextDecoder().decode(event.value);
77
+ return JSON.parse(data);
78
+ }
79
+ }
80
+ }
81
+ catch (err) {
82
+ log.debug(`Room not found: ${roomId}: ${err}`);
83
+ }
84
+ return null;
85
+ }
86
+ // Advertise a capability (best-effort: swallows errors)
87
+ async advertiseCapability(name, peerId) {
88
+ const key = new TextEncoder().encode(KEYS.capability(name));
89
+ const value = new TextEncoder().encode(JSON.stringify({ provider: peerId, timestamp: Date.now() }));
90
+ try {
91
+ for await (const _ of this.dht.put(key, value)) {
92
+ // drain
93
+ }
94
+ log.info(`Advertised capability: ${name}`);
95
+ }
96
+ catch (err) {
97
+ log.error(`Failed to advertise capability: ${err}`);
98
+ // Swallow — capability advertising is best-effort
99
+ }
100
+ }
101
+ }
102
+ export { KEYS as DHT_KEYS };
103
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/dht/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Multi-layer peer discovery cascade
3
+ *
4
+ * Provides zero-config connectivity: agents find each other across the
5
+ * internet without any manual configuration.
6
+ *
7
+ * Discovery levels (tried in order with graceful degradation):
8
+ * 1. Signaling Server (openagents.nexus) — HTTP bootstrap peer fetch
9
+ * 2. Public WebSocket Bootstrap Nodes — well-known Protocol Labs nodes
10
+ * 3. Pubsub Peer Discovery — self-organizing topic-based discovery
11
+ * 4. mDNS — local-area-network discovery (already implemented)
12
+ * 5. Circuit Relay v2 — NAT traversal via relay nodes
13
+ */
14
+ export declare const PUBLIC_BOOTSTRAP_WSS: string[];
15
+ export declare const NEXUS_DISCOVERY_TOPIC = "_nexus._peer-discovery._p2p._pubsub";
16
+ export interface DiscoveryConfig {
17
+ /** Whether to connect to public Protocol Labs bootstrap nodes for initial network entry */
18
+ usePublicBootstrap: boolean;
19
+ /** Whether to enable circuit relay transport (enables NAT traversal for agents behind routers) */
20
+ enableCircuitRelay: boolean;
21
+ /** Whether to enable pubsub-based peer discovery on NEXUS_DISCOVERY_TOPIC */
22
+ enablePubsubDiscovery: boolean;
23
+ /** Whether to enable mDNS discovery (local network, always fast when available) */
24
+ enableMdns: boolean;
25
+ /** Additional user-supplied bootstrap peer multiaddrs (appended after signaling peers) */
26
+ customBootstrapPeers: string[];
27
+ }
28
+ export declare const DEFAULT_DISCOVERY: DiscoveryConfig;
29
+ /**
30
+ * Merge a partial user-supplied discovery config with the defaults.
31
+ * Does not mutate the defaults.
32
+ */
33
+ export declare function resolveDiscovery(partial?: Partial<DiscoveryConfig>): DiscoveryConfig;
34
+ /**
35
+ * Build the complete bootstrap peer list from all three sources:
36
+ * 1. Signaling server peers (highest priority — freshest data)
37
+ * 2. Custom user-supplied peers
38
+ * 3. Well-known public WebSocket bootstrap nodes (fallback)
39
+ *
40
+ * Deduplicates across all sources using a Set so that the same multiaddr
41
+ * never appears twice regardless of how many sources supply it.
42
+ */
43
+ export declare function buildBootstrapList(config: DiscoveryConfig, signalingPeers?: string[]): string[];
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Multi-layer peer discovery cascade
3
+ *
4
+ * Provides zero-config connectivity: agents find each other across the
5
+ * internet without any manual configuration.
6
+ *
7
+ * Discovery levels (tried in order with graceful degradation):
8
+ * 1. Signaling Server (openagents.nexus) — HTTP bootstrap peer fetch
9
+ * 2. Public WebSocket Bootstrap Nodes — well-known Protocol Labs nodes
10
+ * 3. Pubsub Peer Discovery — self-organizing topic-based discovery
11
+ * 4. mDNS — local-area-network discovery (already implemented)
12
+ * 5. Circuit Relay v2 — NAT traversal via relay nodes
13
+ */
14
+ // Well-known public WebSocket bootstrap nodes from Protocol Labs / IPFS network.
15
+ // Used for initial connectivity and circuit relay, NOT for our private DHT.
16
+ export const PUBLIC_BOOTSTRAP_WSS = [
17
+ '/dns4/am6.bootstrap.libp2p.io/tcp/443/wss/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb',
18
+ '/dns4/sg1.bootstrap.libp2p.io/tcp/443/wss/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt',
19
+ '/dns4/sv15.bootstrap.libp2p.io/tcp/443/wss/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN',
20
+ '/dns4/ams-1.bootstrap.libp2p.io/tcp/443/wss/p2p/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd',
21
+ '/dns4/sfo-1.bootstrap.libp2p.io/tcp/443/wss/p2p/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx',
22
+ '/dns4/lon-1.bootstrap.libp2p.io/tcp/443/wss/p2p/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3',
23
+ '/dns4/nyc-1.bootstrap.libp2p.io/tcp/443/wss/p2p/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm',
24
+ ];
25
+ // Pubsub peer discovery topic — ALL nexus agents subscribe to this.
26
+ // Any agent on this topic discovers all other agents automatically,
27
+ // creating a self-organizing global peer mesh.
28
+ export const NEXUS_DISCOVERY_TOPIC = '_nexus._peer-discovery._p2p._pubsub';
29
+ export const DEFAULT_DISCOVERY = {
30
+ usePublicBootstrap: true,
31
+ enableCircuitRelay: true,
32
+ enablePubsubDiscovery: true,
33
+ enableMdns: true,
34
+ customBootstrapPeers: [],
35
+ };
36
+ /**
37
+ * Merge a partial user-supplied discovery config with the defaults.
38
+ * Does not mutate the defaults.
39
+ */
40
+ export function resolveDiscovery(partial) {
41
+ return { ...DEFAULT_DISCOVERY, ...partial };
42
+ }
43
+ /**
44
+ * Build the complete bootstrap peer list from all three sources:
45
+ * 1. Signaling server peers (highest priority — freshest data)
46
+ * 2. Custom user-supplied peers
47
+ * 3. Well-known public WebSocket bootstrap nodes (fallback)
48
+ *
49
+ * Deduplicates across all sources using a Set so that the same multiaddr
50
+ * never appears twice regardless of how many sources supply it.
51
+ */
52
+ export function buildBootstrapList(config, signalingPeers = []) {
53
+ const peers = new Set();
54
+ // Signaling server peers first — most authoritative / freshest
55
+ for (const peer of signalingPeers) {
56
+ peers.add(peer);
57
+ }
58
+ // Custom bootstrap peers provided by the operator
59
+ for (const peer of config.customBootstrapPeers) {
60
+ peers.add(peer);
61
+ }
62
+ // Public bootstrap nodes as the global fallback
63
+ if (config.usePublicBootstrap) {
64
+ for (const peer of PUBLIC_BOOTSTRAP_WSS) {
65
+ peers.add(peer);
66
+ }
67
+ }
68
+ return Array.from(peers);
69
+ }
70
+ //# sourceMappingURL=discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.js","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,iFAAiF;AACjF,4EAA4E;AAC5E,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,8FAA8F;IAC9F,8FAA8F;IAC9F,+FAA+F;IAC/F,gGAAgG;IAChG,gGAAgG;IAChG,gGAAgG;IAChG,gGAAgG;CACjG,CAAC;AAEF,oEAAoE;AACpE,oEAAoE;AACpE,+CAA+C;AAC/C,MAAM,CAAC,MAAM,qBAAqB,GAAG,qCAAqC,CAAC;AAmB3E,MAAM,CAAC,MAAM,iBAAiB,GAAoB;IAChD,kBAAkB,EAAE,IAAI;IACxB,kBAAkB,EAAE,IAAI;IACxB,qBAAqB,EAAE,IAAI;IAC3B,UAAU,EAAE,IAAI;IAChB,oBAAoB,EAAE,EAAE;CACzB,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAkC;IACjE,OAAO,EAAE,GAAG,iBAAiB,EAAE,GAAG,OAAO,EAAE,CAAC;AAC9C,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAChC,MAAuB,EACvB,iBAA2B,EAAE;IAE7B,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAEhC,+DAA+D;IAC/D,KAAK,MAAM,IAAI,IAAI,cAAc,EAAE,CAAC;QAClC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAClB,CAAC;IAED,kDAAkD;IAClD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,oBAAoB,EAAE,CAAC;QAC/C,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAClB,CAAC;IAED,gDAAgD;IAChD,IAAI,MAAM,CAAC,kBAAkB,EAAE,CAAC;QAC9B,KAAK,MAAM,IAAI,IAAI,oBAAoB,EAAE,CAAC;YACxC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Agent identity (keypair) management
3
+ *
4
+ * Manages agent identities based on cryptographic keypairs.
5
+ * Each agent has a unique PeerId derived from their public key,
6
+ * providing verifiable identity without a central authority.
7
+ */
8
+ import type { PrivateKey } from '@libp2p/interface';
9
+ export interface IdentityInfo {
10
+ privateKey: PrivateKey;
11
+ peerId: string;
12
+ }
13
+ export interface ResolveIdentityOptions {
14
+ /**
15
+ * Explicit private key bytes (protobuf-encoded).
16
+ * Takes priority over keyStorePath when provided.
17
+ */
18
+ privateKey?: Uint8Array;
19
+ /**
20
+ * Filesystem path to load/save the private key.
21
+ * If the file does not exist a new identity is generated and saved.
22
+ * Ignored when privateKey is provided.
23
+ */
24
+ keyStorePath?: string;
25
+ }
26
+ /**
27
+ * Resolve an identity using the following priority order:
28
+ *
29
+ * 1. Explicit `privateKey` bytes (protobuf-encoded) — highest priority
30
+ * 2. Load from `keyStorePath` (generate and save if missing)
31
+ * 3. Generate ephemeral identity — lowest priority (not persisted)
32
+ */
33
+ export declare function resolveIdentity(options: ResolveIdentityOptions): Promise<IdentityInfo>;
34
+ export { generateIdentity, saveKey, loadKey } from './keys.js';