@decentnetwork/lan 0.1.48 → 0.1.50

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.
@@ -180,6 +180,7 @@ export class PeerManager extends EventEmitter {
180
180
  address: friend.address,
181
181
  lastSeen: friend.acceptedAt,
182
182
  acceptedAt: friend.acceptedAt,
183
+ requestedAt: friend.requestedAt,
183
184
  };
184
185
  });
185
186
  }
@@ -673,6 +673,7 @@ export async function cmdFriendsList(args) {
673
673
  status: f.status,
674
674
  address: f.address,
675
675
  acceptedAt: f.acceptedAt,
676
+ requestedAt: f.requestedAt,
676
677
  }));
677
678
  await peer.stop();
678
679
  source = "disk";
@@ -681,16 +682,43 @@ export async function cmdFriendsList(args) {
681
682
  console.log("No friends. Use 'agentnet friend-request --address <addr>' to add one.");
682
683
  return;
683
684
  }
685
+ // A friend we only friend-requested (status "requested") has no name in
686
+ // the local SDK record yet — but the dora roster knows it. Cross-reference
687
+ // live IPAM so the list shows "cn", "mac-dev", … instead of "(unnamed)".
688
+ const ipamNames = new Map();
689
+ try {
690
+ const { peers } = await fetchLiveIpam(config);
691
+ for (const p of peers) {
692
+ if (p.carrierId && p.name)
693
+ ipamNames.set(p.carrierId, p.name);
694
+ }
695
+ }
696
+ catch {
697
+ // IPAM unavailable (daemon down / no dora) — fall back to (unnamed).
698
+ }
699
+ const ago = (ms) => {
700
+ const s = Math.max(0, Math.round((Date.now() - ms) / 1000));
701
+ if (s < 60)
702
+ return `${s}s ago`;
703
+ if (s < 3600)
704
+ return `${Math.round(s / 60)}m ago`;
705
+ if (s < 86400)
706
+ return `${Math.round(s / 3600)}h ago`;
707
+ return `${Math.round(s / 86400)}d ago`;
708
+ };
684
709
  console.log(`Friends (${friends.length}) ${source === "daemon" ? "[live]" : "[disk]"}:`);
685
710
  for (const friend of friends) {
686
- console.log(``);
687
- console.log(` ${friend.name || "(unnamed)"} status=${friend.status}`);
688
711
  const userid = friend.carrierId || friend.pubkey;
712
+ const name = friend.name || ipamNames.get(userid) || "(unnamed)";
713
+ console.log(``);
714
+ console.log(` ${name} status=${friend.status}`);
689
715
  console.log(` userid: ${userid}`);
690
716
  if (friend.address)
691
717
  console.log(` address: ${friend.address}`);
718
+ if (friend.requestedAt)
719
+ console.log(` requested: ${new Date(friend.requestedAt).toISOString()} (${ago(friend.requestedAt)})`);
692
720
  if (friend.acceptedAt)
693
- console.log(` accepted: ${new Date(friend.acceptedAt).toISOString()}`);
721
+ console.log(` accepted: ${new Date(friend.acceptedAt).toISOString()} (${ago(friend.acceptedAt)})`);
694
722
  }
695
723
  }
696
724
  /**
package/dist/types.d.ts CHANGED
@@ -23,6 +23,8 @@ export interface RemotePeer {
23
23
  address?: string;
24
24
  lastSeen?: number;
25
25
  acceptedAt?: number;
26
+ /** When we sent the outbound friend-request (ms epoch). */
27
+ requestedAt?: number;
26
28
  }
27
29
  export interface FriendConnectionEvent {
28
30
  pubkey: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decentnetwork/lan",
3
- "version": "0.1.48",
3
+ "version": "0.1.50",
4
4
  "description": "Private virtual LAN for self-hosted services and AI agents, built on Elastos Carrier. NAT-traversal, name service, ACL, all over a peer-to-peer mesh — no public IP required.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -74,8 +74,8 @@
74
74
  "prepublishOnly": "rm -rf dist && npm run build && npm run typecheck && npm run build:helpers:all"
75
75
  },
76
76
  "dependencies": {
77
- "@decentnetwork/dora": "^0.1.0",
78
- "@decentnetwork/peer": "^0.1.20",
77
+ "@decentnetwork/dora": "^0.1.6",
78
+ "@decentnetwork/peer": "^0.1.21",
79
79
  "js-yaml": "^4.1.0",
80
80
  "yargs": "^17.7.2"
81
81
  },