@highway1/cli 0.1.18 → 0.1.19
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/dist/index.js +90 -32
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/commands/join.ts +89 -32
package/package.json
CHANGED
package/src/commands/join.ts
CHANGED
|
@@ -16,19 +16,28 @@ export function registerJoinCommand(program: Command): void {
|
|
|
16
16
|
.command('join')
|
|
17
17
|
.description('Join the Clawiverse network')
|
|
18
18
|
.option('--bootstrap <peers...>', 'Bootstrap peer addresses')
|
|
19
|
+
.option('--json', 'Output messages as JSON (for agent automation)')
|
|
19
20
|
.action(async (options) => {
|
|
20
21
|
try {
|
|
21
|
-
|
|
22
|
+
const jsonMode = options.json;
|
|
23
|
+
|
|
24
|
+
if (!jsonMode) {
|
|
25
|
+
printHeader('Join Clawiverse Network');
|
|
26
|
+
}
|
|
22
27
|
|
|
23
28
|
const identity = getIdentity();
|
|
24
29
|
const card = getAgentCard();
|
|
25
30
|
|
|
26
31
|
if (!identity || !card) {
|
|
27
|
-
|
|
32
|
+
if (jsonMode) {
|
|
33
|
+
console.log(JSON.stringify({ error: 'No identity found. Run "hw1 init" first.' }));
|
|
34
|
+
} else {
|
|
35
|
+
error('No identity found. Run "hw1 init" first.');
|
|
36
|
+
}
|
|
28
37
|
process.exit(1);
|
|
29
38
|
}
|
|
30
39
|
|
|
31
|
-
const spin = spinner('Starting libp2p node...');
|
|
40
|
+
const spin = jsonMode ? null : spinner('Starting libp2p node...');
|
|
32
41
|
|
|
33
42
|
const keyPair = importKeyPair({
|
|
34
43
|
publicKey: identity.publicKey,
|
|
@@ -45,14 +54,22 @@ export function registerJoinCommand(program: Command): void {
|
|
|
45
54
|
|
|
46
55
|
await node.start();
|
|
47
56
|
|
|
48
|
-
spin
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
57
|
+
if (spin) {
|
|
58
|
+
spin.succeed('Node started successfully!');
|
|
59
|
+
info(`Peer ID: ${node.getPeerId()}`);
|
|
60
|
+
info(`DID: ${identity.did}`);
|
|
61
|
+
info(`Listening on: ${node.getMultiaddrs().join(', ')}`);
|
|
62
|
+
} else {
|
|
63
|
+
console.log(JSON.stringify({
|
|
64
|
+
event: 'node_started',
|
|
65
|
+
peerId: node.getPeerId(),
|
|
66
|
+
did: identity.did,
|
|
67
|
+
multiaddrs: node.getMultiaddrs(),
|
|
68
|
+
}));
|
|
69
|
+
}
|
|
53
70
|
|
|
54
71
|
// Wait for bootstrap peer connection before publishing to DHT
|
|
55
|
-
const connectSpin = spinner('Connecting to bootstrap peers...');
|
|
72
|
+
const connectSpin = jsonMode ? null : spinner('Connecting to bootstrap peers...');
|
|
56
73
|
await new Promise<void>((resolve) => {
|
|
57
74
|
const timeout = setTimeout(resolve, 10000);
|
|
58
75
|
node.libp2p.addEventListener('peer:connect', () => {
|
|
@@ -60,10 +77,12 @@ export function registerJoinCommand(program: Command): void {
|
|
|
60
77
|
setTimeout(resolve, 500);
|
|
61
78
|
}, { once: true });
|
|
62
79
|
});
|
|
63
|
-
connectSpin
|
|
80
|
+
if (connectSpin) {
|
|
81
|
+
connectSpin.succeed('Connected to network!');
|
|
82
|
+
}
|
|
64
83
|
|
|
65
84
|
// Publish Agent Card with peerId and multiaddrs so others can dial us
|
|
66
|
-
const cardSpin = spinner('Publishing Agent Card to DHT...');
|
|
85
|
+
const cardSpin = jsonMode ? null : spinner('Publishing Agent Card to DHT...');
|
|
67
86
|
|
|
68
87
|
// Include circuit relay addresses so nodes behind NAT can be reached
|
|
69
88
|
const directAddrs = node.getMultiaddrs();
|
|
@@ -89,7 +108,11 @@ export function registerJoinCommand(program: Command): void {
|
|
|
89
108
|
const dht = createDHTOperations(node.libp2p);
|
|
90
109
|
await dht.publishAgentCard(signedCard);
|
|
91
110
|
|
|
92
|
-
cardSpin
|
|
111
|
+
if (cardSpin) {
|
|
112
|
+
cardSpin.succeed('Agent Card published!');
|
|
113
|
+
} else {
|
|
114
|
+
console.log(JSON.stringify({ event: 'agent_card_published' }));
|
|
115
|
+
}
|
|
93
116
|
|
|
94
117
|
// Register message handlers for incoming messages
|
|
95
118
|
const router = createMessageRouter(
|
|
@@ -101,17 +124,34 @@ export function registerJoinCommand(program: Command): void {
|
|
|
101
124
|
// Generic message handler that accepts any protocol
|
|
102
125
|
const messageHandler = async (envelope: any) => {
|
|
103
126
|
const payload = envelope.payload as Record<string, unknown>;
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
127
|
+
|
|
128
|
+
if (jsonMode) {
|
|
129
|
+
// Output as JSON for agent consumption
|
|
130
|
+
console.log(JSON.stringify({
|
|
131
|
+
event: 'message_received',
|
|
132
|
+
id: envelope.id,
|
|
133
|
+
from: envelope.from,
|
|
134
|
+
to: envelope.to,
|
|
135
|
+
protocol: envelope.protocol,
|
|
136
|
+
type: envelope.type,
|
|
137
|
+
payload,
|
|
138
|
+
timestamp: Date.now(),
|
|
139
|
+
}));
|
|
140
|
+
} else {
|
|
141
|
+
console.log();
|
|
142
|
+
success(`>>> Received message from ${envelope.from}`);
|
|
143
|
+
info(` Message ID: ${envelope.id}`);
|
|
144
|
+
info(` Protocol: ${envelope.protocol}`);
|
|
145
|
+
info(` Type: ${envelope.type}`);
|
|
146
|
+
info(` Payload: ${JSON.stringify(payload, null, 2)}`);
|
|
147
|
+
console.log();
|
|
148
|
+
}
|
|
111
149
|
|
|
112
150
|
// If this is a request, send back a simple acknowledgment response
|
|
113
151
|
if (envelope.type === 'request') {
|
|
114
|
-
|
|
152
|
+
if (!jsonMode) {
|
|
153
|
+
info(' Sending acknowledgment response...');
|
|
154
|
+
}
|
|
115
155
|
|
|
116
156
|
const { createEnvelope, signEnvelope, sign } = await import('@highway1/core');
|
|
117
157
|
const identity = getIdentity();
|
|
@@ -153,23 +193,40 @@ export function registerJoinCommand(program: Command): void {
|
|
|
153
193
|
|
|
154
194
|
await router.start();
|
|
155
195
|
|
|
156
|
-
|
|
157
|
-
success('Successfully joined the Clawiverse network!');
|
|
158
|
-
info('Listening for incoming messages...');
|
|
159
|
-
info('Press Ctrl+C to stop');
|
|
160
|
-
|
|
161
|
-
process.on('SIGINT', async () => {
|
|
196
|
+
if (!jsonMode) {
|
|
162
197
|
console.log();
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
198
|
+
success('Successfully joined the Clawiverse network!');
|
|
199
|
+
info('Listening for incoming messages...');
|
|
200
|
+
info('Press Ctrl+C to stop');
|
|
201
|
+
} else {
|
|
202
|
+
console.log(JSON.stringify({ event: 'ready', status: 'listening' }));
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const shutdown = async () => {
|
|
206
|
+
if (!jsonMode) {
|
|
207
|
+
console.log();
|
|
208
|
+
const stopSpin = spinner('Stopping node...');
|
|
209
|
+
await router.stop();
|
|
210
|
+
await node.stop();
|
|
211
|
+
stopSpin.succeed('Node stopped');
|
|
212
|
+
} else {
|
|
213
|
+
await router.stop();
|
|
214
|
+
await node.stop();
|
|
215
|
+
console.log(JSON.stringify({ event: 'shutdown', status: 'stopped' }));
|
|
216
|
+
}
|
|
167
217
|
process.exit(0);
|
|
168
|
-
}
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
process.on('SIGINT', shutdown);
|
|
221
|
+
process.on('SIGTERM', shutdown);
|
|
169
222
|
|
|
170
223
|
await new Promise(() => {});
|
|
171
224
|
} catch (err) {
|
|
172
|
-
|
|
225
|
+
if (options.json) {
|
|
226
|
+
console.log(JSON.stringify({ error: (err as Error).message }));
|
|
227
|
+
} else {
|
|
228
|
+
error(`Failed to join network: ${(err as Error).message}`);
|
|
229
|
+
}
|
|
173
230
|
process.exit(1);
|
|
174
231
|
}
|
|
175
232
|
});
|