@highway1/cli 0.1.42 → 0.1.44

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@highway1/cli",
3
- "version": "0.1.42",
3
+ "version": "0.1.44",
4
4
  "description": "CLI tool for Clawiverse network",
5
5
  "type": "module",
6
6
  "bin": {
@@ -13,7 +13,7 @@
13
13
  "clean": "rm -rf dist"
14
14
  },
15
15
  "dependencies": {
16
- "@highway1/core": "^0.1.41",
16
+ "@highway1/core": "^0.1.44",
17
17
  "chalk": "^5.3.0",
18
18
  "cli-table3": "^0.6.5",
19
19
  "commander": "^12.1.0",
@@ -39,6 +39,9 @@ export function registerJoinCommand(program: Command): void {
39
39
  });
40
40
 
41
41
  const bootstrapPeers = options.bootstrap || getBootstrapPeers();
42
+ const bootstrapPeerIds = bootstrapPeers
43
+ .map((addr: string) => addr.split('/p2p/')[1])
44
+ .filter((peerId: string | undefined): peerId is string => Boolean(peerId));
42
45
 
43
46
  const node = await createNode({
44
47
  keyPair,
@@ -195,7 +198,25 @@ export function registerJoinCommand(program: Command): void {
195
198
 
196
199
  cardSpin.succeed('Agent Card published!');
197
200
 
198
- // Keep connection alive by pinging bootstrap peers periodically
201
+ // Keep bootstrap connectivity stable: proactively re-dial missing bootstrap peers.
202
+ const ensureBootstrapConnections = async () => {
203
+ const connections = node.libp2p.getConnections();
204
+ const connectedPeerIds = new Set(connections.map((conn) => conn.remotePeer.toString()));
205
+
206
+ for (const bootstrapAddr of bootstrapPeers) {
207
+ const targetPeerId = bootstrapAddr.split('/p2p/')[1];
208
+ if (!targetPeerId || connectedPeerIds.has(targetPeerId)) continue;
209
+
210
+ try {
211
+ await node.libp2p.dial(bootstrapAddr);
212
+ info(`Reconnected bootstrap peer: ${targetPeerId}`);
213
+ } catch {
214
+ // best effort; keep trying on next tick
215
+ }
216
+ }
217
+ };
218
+
219
+ // Keep connection alive by pinging peers periodically
199
220
  const pingInterval = setInterval(async () => {
200
221
  const peers = node.libp2p.getPeers();
201
222
  if (peers.length === 0) {
@@ -210,6 +231,7 @@ export function registerJoinCommand(program: Command): void {
210
231
  }
211
232
  }
212
233
  } else {
234
+ await ensureBootstrapConnections();
213
235
  // Ping existing peers to keep connection alive
214
236
  for (const peer of peers) {
215
237
  try {
@@ -221,6 +243,25 @@ export function registerJoinCommand(program: Command): void {
221
243
  }
222
244
  }, 15000); // ping every 15s (reduced from 30s for better stability)
223
245
 
246
+ // If a bootstrap peer disconnects, attempt immediate recovery.
247
+ const onPeerDisconnect = async (evt: any) => {
248
+ const disconnectedPeerId = evt?.detail?.toString?.() ?? '';
249
+ if (!bootstrapPeerIds.includes(disconnectedPeerId)) return;
250
+
251
+ info(`Bootstrap peer disconnected: ${disconnectedPeerId}, attempting reconnect...`);
252
+ for (const bootstrapAddr of bootstrapPeers) {
253
+ if (!bootstrapAddr.endsWith(`/p2p/${disconnectedPeerId}`)) continue;
254
+ try {
255
+ await node.libp2p.dial(bootstrapAddr);
256
+ info(`Recovered bootstrap connection: ${disconnectedPeerId}`);
257
+ return;
258
+ } catch {
259
+ // Continue trying other bootstrap peers if available
260
+ }
261
+ }
262
+ };
263
+ node.libp2p.addEventListener('peer:disconnect', onPeerDisconnect);
264
+
224
265
  const verifyFn = async (signature: Uint8Array, data: Uint8Array): Promise<boolean> => {
225
266
  try {
226
267
  const decoded = JSON.parse(new TextDecoder().decode(data)) as { from?: string };
@@ -303,6 +344,7 @@ export function registerJoinCommand(program: Command): void {
303
344
  console.log();
304
345
  const stopSpin = spinner('Stopping node...');
305
346
  clearInterval(pingInterval);
347
+ node.libp2p.removeEventListener('peer:disconnect', onPeerDisconnect);
306
348
  await router.stop();
307
349
  await node.stop();
308
350
  stopSpin.succeed('Node stopped');