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.
- package/ARCHITECTURE.md +2104 -0
- package/LICENSE +28 -0
- package/README.md +198 -0
- package/dist/chat/index.d.ts +24 -0
- package/dist/chat/index.js +56 -0
- package/dist/chat/index.js.map +1 -0
- package/dist/chat/messages.d.ts +28 -0
- package/dist/chat/messages.js +33 -0
- package/dist/chat/messages.js.map +1 -0
- package/dist/chat/room.d.ts +49 -0
- package/dist/chat/room.js +123 -0
- package/dist/chat/room.js.map +1 -0
- package/dist/cli.d.ts +8 -0
- package/dist/cli.js +222 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +22 -0
- package/dist/config.js +19 -0
- package/dist/config.js.map +1 -0
- package/dist/dht/index.d.ts +16 -0
- package/dist/dht/index.js +33 -0
- package/dist/dht/index.js.map +1 -0
- package/dist/dht/registry.d.ts +24 -0
- package/dist/dht/registry.js +103 -0
- package/dist/dht/registry.js.map +1 -0
- package/dist/discovery.d.ts +43 -0
- package/dist/discovery.js +70 -0
- package/dist/discovery.js.map +1 -0
- package/dist/identity/index.d.ts +34 -0
- package/dist/identity/index.js +46 -0
- package/dist/identity/index.js.map +1 -0
- package/dist/identity/keys.d.ts +26 -0
- package/dist/identity/keys.js +49 -0
- package/dist/identity/keys.js.map +1 -0
- package/dist/index.d.ts +83 -0
- package/dist/index.js +299 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +8 -0
- package/dist/logger.js +32 -0
- package/dist/logger.js.map +1 -0
- package/dist/node.d.ts +47 -0
- package/dist/node.js +136 -0
- package/dist/node.js.map +1 -0
- package/dist/protocol/index.d.ts +11 -0
- package/dist/protocol/index.js +66 -0
- package/dist/protocol/index.js.map +1 -0
- package/dist/protocol/types.d.ts +197 -0
- package/dist/protocol/types.js +18 -0
- package/dist/protocol/types.js.map +1 -0
- package/dist/signaling/onboarding.d.ts +10 -0
- package/dist/signaling/onboarding.js +40 -0
- package/dist/signaling/onboarding.js.map +1 -0
- package/dist/signaling/server.d.ts +35 -0
- package/dist/signaling/server.js +140 -0
- package/dist/signaling/server.js.map +1 -0
- package/dist/storage/index.d.ts +31 -0
- package/dist/storage/index.js +103 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/mirror.d.ts +9 -0
- package/dist/storage/mirror.js +24 -0
- package/dist/storage/mirror.js.map +1 -0
- package/dist/storage/pin.d.ts +8 -0
- package/dist/storage/pin.js +42 -0
- package/dist/storage/pin.js.map +1 -0
- package/dist/storage/propagation.d.ts +32 -0
- package/dist/storage/propagation.js +89 -0
- package/dist/storage/propagation.js.map +1 -0
- 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
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -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';
|