@decentnetwork/lan 0.1.16 → 0.1.17
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/carrier/peer-manager.js +23 -6
- package/dist/cli/commands.d.ts +4 -1
- package/dist/cli/commands.js +39 -22
- package/dist/daemon/server.js +2 -0
- package/dist/types.d.ts +11 -1
- package/package.json +1 -1
|
@@ -159,12 +159,29 @@ export class PeerManager extends EventEmitter {
|
|
|
159
159
|
if (!this.peer) {
|
|
160
160
|
throw new Error("Peer not created. Call create() first.");
|
|
161
161
|
}
|
|
162
|
-
return this.peer.friends().map((friend) =>
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
162
|
+
return this.peer.friends().map((friend) => {
|
|
163
|
+
// Preserve the SDK's three-state status ("requested" matters —
|
|
164
|
+
// collapsing it into "offline" hid the "did my friend-request
|
|
165
|
+
// make it across?" diagnostic from diag output).
|
|
166
|
+
const status = friend.status === "online"
|
|
167
|
+
? "online"
|
|
168
|
+
: friend.status === "requested"
|
|
169
|
+
? "requested"
|
|
170
|
+
: "offline";
|
|
171
|
+
// Both pubkey and userid are populated with the base58 userid in
|
|
172
|
+
// every current SDK code path, but persisted records from
|
|
173
|
+
// pre-1.7.x clients may only have pubkey. Keep both forms.
|
|
174
|
+
const carrierId = friend.userid || friend.pubkey;
|
|
175
|
+
return {
|
|
176
|
+
pubkey: friend.pubkey,
|
|
177
|
+
carrierId,
|
|
178
|
+
name: friend.name,
|
|
179
|
+
status,
|
|
180
|
+
address: friend.address,
|
|
181
|
+
lastSeen: friend.acceptedAt,
|
|
182
|
+
acceptedAt: friend.acceptedAt,
|
|
183
|
+
};
|
|
184
|
+
});
|
|
168
185
|
}
|
|
169
186
|
/**
|
|
170
187
|
* Check if a specific friend is currently online (direct UDP path established).
|
package/dist/cli/commands.d.ts
CHANGED
|
@@ -96,7 +96,10 @@ export declare function cmdFriendAccept(args: {
|
|
|
96
96
|
configDir?: string;
|
|
97
97
|
}): Promise<void>;
|
|
98
98
|
/**
|
|
99
|
-
* List friends in the friend store.
|
|
99
|
+
* List friends in the friend store. Prefers the live daemon over IPC —
|
|
100
|
+
* opening a second Peer with the same keyfile would stomp on the
|
|
101
|
+
* daemon's Carrier session, so we only fall back to that path when the
|
|
102
|
+
* daemon isn't running. Same pattern as `peers list` and `resolve`.
|
|
100
103
|
*/
|
|
101
104
|
export declare function cmdFriendsList(args: {
|
|
102
105
|
configDir?: string;
|
package/dist/cli/commands.js
CHANGED
|
@@ -511,46 +511,63 @@ export async function cmdFriendAccept(args) {
|
|
|
511
511
|
console.log(`Friend accepted: ${pubkey}`);
|
|
512
512
|
}
|
|
513
513
|
/**
|
|
514
|
-
* List friends in the friend store.
|
|
514
|
+
* List friends in the friend store. Prefers the live daemon over IPC —
|
|
515
|
+
* opening a second Peer with the same keyfile would stomp on the
|
|
516
|
+
* daemon's Carrier session, so we only fall back to that path when the
|
|
517
|
+
* daemon isn't running. Same pattern as `peers list` and `resolve`.
|
|
515
518
|
*/
|
|
516
519
|
export async function cmdFriendsList(args) {
|
|
517
520
|
const dir = args.configDir || ConfigLoader.defaultConfigDir();
|
|
518
521
|
const config = await ConfigLoader.load(resolve(dir, "config.yaml"));
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
522
|
+
let friends;
|
|
523
|
+
let source;
|
|
524
|
+
if (daemonPid(config) !== null) {
|
|
525
|
+
const res = await ipcCall(config, { op: "diag" });
|
|
526
|
+
if (!res.ok)
|
|
527
|
+
throw new Error(`Daemon diag failed: ${res.error}`);
|
|
528
|
+
friends = (res.data.friends ?? []);
|
|
529
|
+
source = "daemon";
|
|
530
|
+
}
|
|
531
|
+
else {
|
|
532
|
+
const { Peer } = await import("@decentnetwork/peer");
|
|
533
|
+
const keyFile = resolve(config.carrier.dataDir, "keypair.json");
|
|
534
|
+
if (!existsSync(keyFile)) {
|
|
535
|
+
console.log("No identity yet. Start the daemon at least once to generate one.");
|
|
536
|
+
return;
|
|
537
|
+
}
|
|
538
|
+
const peer = await Peer.create({
|
|
539
|
+
keyFile,
|
|
540
|
+
compatibilityMode: "legacy",
|
|
541
|
+
bootstrapNodes: config.carrier.bootstrapNodes,
|
|
542
|
+
expressNodes: config.carrier.expressNodes,
|
|
543
|
+
});
|
|
544
|
+
await peer.start();
|
|
545
|
+
friends = peer.friends().map((f) => ({
|
|
546
|
+
pubkey: f.pubkey,
|
|
547
|
+
carrierId: f.userid || f.pubkey,
|
|
548
|
+
name: f.name,
|
|
549
|
+
status: f.status,
|
|
550
|
+
address: f.address,
|
|
551
|
+
acceptedAt: f.acceptedAt,
|
|
552
|
+
}));
|
|
553
|
+
await peer.stop();
|
|
554
|
+
source = "disk";
|
|
525
555
|
}
|
|
526
|
-
// Open peer and start (start() loads friends from disk)
|
|
527
|
-
const peer = await Peer.create({
|
|
528
|
-
keyFile,
|
|
529
|
-
compatibilityMode: "legacy",
|
|
530
|
-
bootstrapNodes: config.carrier.bootstrapNodes,
|
|
531
|
-
expressNodes: config.carrier.expressNodes,
|
|
532
|
-
});
|
|
533
|
-
await peer.start();
|
|
534
|
-
const friends = peer.friends();
|
|
535
556
|
if (friends.length === 0) {
|
|
536
557
|
console.log("No friends. Use 'agentnet friend-request --address <addr>' to add one.");
|
|
537
|
-
await peer.stop();
|
|
538
558
|
return;
|
|
539
559
|
}
|
|
540
|
-
console.log(`Friends (${friends.length}):`);
|
|
560
|
+
console.log(`Friends (${friends.length}) ${source === "daemon" ? "[live]" : "[disk]"}:`);
|
|
541
561
|
for (const friend of friends) {
|
|
542
562
|
console.log(``);
|
|
543
563
|
console.log(` ${friend.name || "(unnamed)"} status=${friend.status}`);
|
|
544
|
-
|
|
545
|
-
// the raw hex pubkey unless someone explicitly needs it.
|
|
546
|
-
const userid = friend.userid && friend.userid !== friend.pubkey ? friend.userid : friend.pubkey;
|
|
564
|
+
const userid = friend.carrierId || friend.pubkey;
|
|
547
565
|
console.log(` userid: ${userid}`);
|
|
548
566
|
if (friend.address)
|
|
549
567
|
console.log(` address: ${friend.address}`);
|
|
550
568
|
if (friend.acceptedAt)
|
|
551
569
|
console.log(` accepted: ${new Date(friend.acceptedAt).toISOString()}`);
|
|
552
570
|
}
|
|
553
|
-
await peer.stop();
|
|
554
571
|
}
|
|
555
572
|
/**
|
|
556
573
|
* List queued friend-requests held by the running daemon (the ones
|
package/dist/daemon/server.js
CHANGED
package/dist/types.d.ts
CHANGED
|
@@ -8,11 +8,21 @@ export interface PeerIdentity {
|
|
|
8
8
|
}
|
|
9
9
|
export interface RemotePeer {
|
|
10
10
|
pubkey: string;
|
|
11
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Mirrors the SDK's FriendRecord.status verbatim:
|
|
13
|
+
* - "online": crypto session established
|
|
14
|
+
* - "offline": was a friend, currently disconnected
|
|
15
|
+
* - "requested": we sent a friend-request; peer hasn't accepted
|
|
16
|
+
* Collapsing "requested" into "offline" loses the operator signal
|
|
17
|
+
* ("did my friend-request go through?") so keep them distinct.
|
|
18
|
+
*/
|
|
19
|
+
status: "online" | "offline" | "requested";
|
|
12
20
|
name?: string;
|
|
13
21
|
carrierId?: string;
|
|
14
22
|
virtualIp?: string;
|
|
23
|
+
address?: string;
|
|
15
24
|
lastSeen?: number;
|
|
25
|
+
acceptedAt?: number;
|
|
16
26
|
}
|
|
17
27
|
export interface FriendConnectionEvent {
|
|
18
28
|
pubkey: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@decentnetwork/lan",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.17",
|
|
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",
|