@decentnetwork/lan 0.1.98 → 0.1.100
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/bin/tun-helper-darwin-amd64 +0 -0
- package/bin/tun-helper-darwin-arm64 +0 -0
- package/bin/tun-helper-linux-amd64 +0 -0
- package/bin/tun-helper-linux-arm64 +0 -0
- package/dist/carrier/peer-manager.d.ts +15 -0
- package/dist/carrier/peer-manager.js +29 -0
- package/dist/cli/commands.d.ts +21 -0
- package/dist/cli/commands.js +29 -0
- package/dist/cli/index.js +15 -1
- package/dist/console/console.js +1011 -0
- package/dist/daemon/ipc.d.ts +11 -1
- package/dist/daemon/ipc.js +11 -0
- package/dist/daemon/server.js +46 -1
- package/dist/types.d.ts +2 -0
- package/dist/ui/desktop/app.js +32 -6
- package/dist/ui/server.js +9 -1
- package/package.json +7 -5
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -16,6 +16,8 @@ export interface PeerManagerOptions {
|
|
|
16
16
|
/** Display name advertised to friends (this node's name, so friend lists show
|
|
17
17
|
* "cn"/"tokyo"/"mac-dev" instead of the generic "@decentnetwork/peer"). */
|
|
18
18
|
nickname?: string;
|
|
19
|
+
/** Status-message / short bio advertised to friends (Carrier USERINFO descr). */
|
|
20
|
+
statusMessage?: string;
|
|
19
21
|
}
|
|
20
22
|
export declare class PeerManager extends EventEmitter {
|
|
21
23
|
private peer;
|
|
@@ -42,6 +44,19 @@ export declare class PeerManager extends EventEmitter {
|
|
|
42
44
|
* removed, false if no such friend existed.
|
|
43
45
|
*/
|
|
44
46
|
removeFriend(userid: string): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Update our own profile (display name + status-message description) at
|
|
49
|
+
* runtime and re-push it to friends over Carrier. The daemon also persists
|
|
50
|
+
* the name to config.yaml so it survives a restart.
|
|
51
|
+
*/
|
|
52
|
+
setUserInfo(info: {
|
|
53
|
+
name?: string;
|
|
54
|
+
description?: string;
|
|
55
|
+
}): void;
|
|
56
|
+
/** Offer a file to a friend (toxcore-standard transfer). Returns the fileId. */
|
|
57
|
+
sendFile(userid: string, data: Uint8Array, name: string): string | null;
|
|
58
|
+
/** Accept an incoming file offer. */
|
|
59
|
+
acceptFile(userid: string, fileNumber: number): void;
|
|
45
60
|
/**
|
|
46
61
|
* Send an outbound friend request to a Carrier address (NOT a bare
|
|
47
62
|
* userid — sendFriendRequest needs the address form because it
|
|
@@ -27,6 +27,7 @@ export class PeerManager extends EventEmitter {
|
|
|
27
27
|
expressNodes: opts.expressNodes,
|
|
28
28
|
expressControlPlaneOnly: opts.expressControlPlaneOnly,
|
|
29
29
|
nickname: opts.nickname,
|
|
30
|
+
statusMessage: opts.statusMessage,
|
|
30
31
|
// Register our IP channel (163) as the SDK's bulk-data stream so it
|
|
31
32
|
// rides a single transport instead of fanning out over UDP + relay +
|
|
32
33
|
// TCP relay (which delivered 3-4 duplicates of every IP packet).
|
|
@@ -93,6 +94,28 @@ export class PeerManager extends EventEmitter {
|
|
|
93
94
|
this.logger.info(`Removed friend ${userid}`);
|
|
94
95
|
return removed;
|
|
95
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* Update our own profile (display name + status-message description) at
|
|
99
|
+
* runtime and re-push it to friends over Carrier. The daemon also persists
|
|
100
|
+
* the name to config.yaml so it survives a restart.
|
|
101
|
+
*/
|
|
102
|
+
setUserInfo(info) {
|
|
103
|
+
if (!this.peer) {
|
|
104
|
+
throw new Error("Peer not created. Call create() first.");
|
|
105
|
+
}
|
|
106
|
+
this.peer.setUserInfo(info);
|
|
107
|
+
this.logger.info(`Profile updated (name="${info.name ?? "(unchanged)"}")`);
|
|
108
|
+
}
|
|
109
|
+
/** Offer a file to a friend (toxcore-standard transfer). Returns the fileId. */
|
|
110
|
+
sendFile(userid, data, name) {
|
|
111
|
+
if (!this.peer)
|
|
112
|
+
throw new Error("Peer not created. Call create() first.");
|
|
113
|
+
return this.peer.sendFile(userid, data, { name });
|
|
114
|
+
}
|
|
115
|
+
/** Accept an incoming file offer. */
|
|
116
|
+
acceptFile(userid, fileNumber) {
|
|
117
|
+
this.peer?.acceptFile(userid, fileNumber);
|
|
118
|
+
}
|
|
96
119
|
/**
|
|
97
120
|
* Send an outbound friend request to a Carrier address (NOT a bare
|
|
98
121
|
* userid — sendFriendRequest needs the address form because it
|
|
@@ -464,6 +487,12 @@ export class PeerManager extends EventEmitter {
|
|
|
464
487
|
}
|
|
465
488
|
this.emit("message", message.pubkey, message.text);
|
|
466
489
|
});
|
|
490
|
+
// Toxcore-standard file transfer (native-compatible). Forward offers,
|
|
491
|
+
// progress, and completions to the daemon, which auto-accepts and saves.
|
|
492
|
+
this.peer.onFile((o) => this.emit("file-offer", o));
|
|
493
|
+
this.peer.onFileProgress((p) => this.emit("file-progress", p));
|
|
494
|
+
this.peer.onFileComplete((p) => this.emit("file-complete", p));
|
|
495
|
+
this.peer.onFileCancel((p) => this.emit("file-cancel", p));
|
|
467
496
|
// decentlan custom packets, all lossless so they traverse relay-only
|
|
468
497
|
// sessions: IP data (163), session handshake (161), dora control (162).
|
|
469
498
|
// Each on its own Carrier packet id — a chat message can never be mistaken
|
package/dist/cli/commands.d.ts
CHANGED
|
@@ -254,6 +254,17 @@ export declare function cmdChatSend(args: {
|
|
|
254
254
|
text: string;
|
|
255
255
|
configDir?: string;
|
|
256
256
|
}): Promise<void>;
|
|
257
|
+
/**
|
|
258
|
+
* Send a file to a friend over toxcore-standard file transfer (direct, over the
|
|
259
|
+
* reliable net_crypto channel — no express, no size cap). The daemon reads the
|
|
260
|
+
* file by absolute path, so it must be readable by the daemon's user. The
|
|
261
|
+
* recipient's daemon auto-accepts and saves to its <configDir>/downloads/.
|
|
262
|
+
*/
|
|
263
|
+
export declare function cmdFileSend(args: {
|
|
264
|
+
to: string;
|
|
265
|
+
path: string;
|
|
266
|
+
configDir?: string;
|
|
267
|
+
}): Promise<void>;
|
|
257
268
|
/**
|
|
258
269
|
* Print chat history (sent + received). Incoming messages are logged by the
|
|
259
270
|
* daemon as they arrive, so this is also how you READ messages from friends.
|
|
@@ -263,6 +274,16 @@ export declare function cmdChatHistory(args: {
|
|
|
263
274
|
peer?: string;
|
|
264
275
|
configDir?: string;
|
|
265
276
|
}): Promise<void>;
|
|
277
|
+
/**
|
|
278
|
+
* Launch the interactive terminal UI (TUI). The console is an ink (React-for-CLI)
|
|
279
|
+
* app built separately by esbuild into dist/console/console.js — the .tsx is
|
|
280
|
+
* excluded from the main tsc build, so we import the built bundle at runtime.
|
|
281
|
+
* The specifier is held in a variable so tsc treats it as a dynamic import and
|
|
282
|
+
* doesn't try to resolve the (non-existent) .ts source.
|
|
283
|
+
*/
|
|
284
|
+
export declare function cmdConsole(args: {
|
|
285
|
+
configDir?: string;
|
|
286
|
+
}): Promise<void>;
|
|
266
287
|
export declare function cmdUi(args: {
|
|
267
288
|
port?: number;
|
|
268
289
|
listen?: string;
|
package/dist/cli/commands.js
CHANGED
|
@@ -1083,6 +1083,23 @@ export async function cmdChatSend(args) {
|
|
|
1083
1083
|
throw new Error(`Daemon refused: ${res.error}`);
|
|
1084
1084
|
console.log(`-> ${args.to.slice(0, 16)}… ${args.text}`);
|
|
1085
1085
|
}
|
|
1086
|
+
/**
|
|
1087
|
+
* Send a file to a friend over toxcore-standard file transfer (direct, over the
|
|
1088
|
+
* reliable net_crypto channel — no express, no size cap). The daemon reads the
|
|
1089
|
+
* file by absolute path, so it must be readable by the daemon's user. The
|
|
1090
|
+
* recipient's daemon auto-accepts and saves to its <configDir>/downloads/.
|
|
1091
|
+
*/
|
|
1092
|
+
export async function cmdFileSend(args) {
|
|
1093
|
+
const dir = args.configDir || ConfigLoader.defaultConfigDir();
|
|
1094
|
+
const config = await ConfigLoader.load(resolve(dir, "config.yaml"));
|
|
1095
|
+
const abs = resolve(process.cwd(), args.path);
|
|
1096
|
+
const res = await ipcCall(config, { op: "file-send", userid: args.to, path: abs }, 30000);
|
|
1097
|
+
if (!res.ok)
|
|
1098
|
+
throw new Error(`File send failed: ${res.error}`);
|
|
1099
|
+
const d = (res.data ?? {});
|
|
1100
|
+
console.log(`Offered "${d.name}" (${d.size} bytes) to ${args.to.slice(0, 16)}… — fileId ${d.fileId}`);
|
|
1101
|
+
console.log("Streams once the recipient accepts; their daemon saves it to ~/.agentnet/downloads/.");
|
|
1102
|
+
}
|
|
1086
1103
|
/**
|
|
1087
1104
|
* Print chat history (sent + received). Incoming messages are logged by the
|
|
1088
1105
|
* daemon as they arrive, so this is also how you READ messages from friends.
|
|
@@ -1108,6 +1125,18 @@ export async function cmdChatHistory(args) {
|
|
|
1108
1125
|
}
|
|
1109
1126
|
}
|
|
1110
1127
|
}
|
|
1128
|
+
/**
|
|
1129
|
+
* Launch the interactive terminal UI (TUI). The console is an ink (React-for-CLI)
|
|
1130
|
+
* app built separately by esbuild into dist/console/console.js — the .tsx is
|
|
1131
|
+
* excluded from the main tsc build, so we import the built bundle at runtime.
|
|
1132
|
+
* The specifier is held in a variable so tsc treats it as a dynamic import and
|
|
1133
|
+
* doesn't try to resolve the (non-existent) .ts source.
|
|
1134
|
+
*/
|
|
1135
|
+
export async function cmdConsole(args) {
|
|
1136
|
+
const spec = "../console/console.js";
|
|
1137
|
+
const mod = (await import(spec));
|
|
1138
|
+
await mod.runConsole({ configDir: args.configDir });
|
|
1139
|
+
}
|
|
1111
1140
|
export async function cmdUi(args) {
|
|
1112
1141
|
const dir = args.configDir || ConfigLoader.defaultConfigDir();
|
|
1113
1142
|
const config = await ConfigLoader.load(resolve(dir, "config.yaml"));
|
package/dist/cli/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import { hideBin } from "yargs/helpers";
|
|
|
10
10
|
// Belt-and-braces — also raise it here in case the CLI is run directly
|
|
11
11
|
// (e.g. `node dist/cli/index.js` rather than via dist/index.js).
|
|
12
12
|
EventEmitter.defaultMaxListeners = 100;
|
|
13
|
-
import { cmdInit, cmdIdentityShow, cmdPeersList, cmdIpamAssign, cmdGrant, cmdRevoke, cmdResolve, cmdStatus, cmdUp, cmdAuditLog, cmdFriendRequest, cmdFriendAccept, cmdFriendsList, cmdFriendsPending, cmdFriendsAccept, cmdFriendsReject, cmdProxyEnable, cmdProxyDisable, cmdProxyStatus, cmdProxyAllowHost, cmdProxyRevokeHost, cmdProxyListHosts, cmdProxyUse, cmdProxyRouter, cmdDoraEnable, cmdDoraDisable, cmdDoraStatus, cmdDoraAutofriend, cmdDiag, cmdDoctor, cmdDnsInstall, cmdDnsHosts, cmdServiceInstall, cmdRestart, cmdServiceStatus, cmdServiceRestart, cmdUi, cmdChatSend, cmdChatHistory, cmdFriendRemove, cmdFriendAlias, } from "./commands.js";
|
|
13
|
+
import { cmdInit, cmdIdentityShow, cmdPeersList, cmdIpamAssign, cmdGrant, cmdRevoke, cmdResolve, cmdStatus, cmdUp, cmdAuditLog, cmdFriendRequest, cmdFriendAccept, cmdFriendsList, cmdFriendsPending, cmdFriendsAccept, cmdFriendsReject, cmdProxyEnable, cmdProxyDisable, cmdProxyStatus, cmdProxyAllowHost, cmdProxyRevokeHost, cmdProxyListHosts, cmdProxyUse, cmdProxyRouter, cmdDoraEnable, cmdDoraDisable, cmdDoraStatus, cmdDoraAutofriend, cmdDiag, cmdDoctor, cmdDnsInstall, cmdDnsHosts, cmdServiceInstall, cmdRestart, cmdServiceStatus, cmdServiceRestart, cmdUi, cmdConsole, cmdFileSend, cmdChatSend, cmdChatHistory, cmdFriendRemove, cmdFriendAlias, } from "./commands.js";
|
|
14
14
|
async function main() {
|
|
15
15
|
await yargs(hideBin(process.argv))
|
|
16
16
|
.scriptName("agentnet")
|
|
@@ -152,6 +152,20 @@ async function main() {
|
|
|
152
152
|
.option("dora-dir", { type: "string", describe: "If this node runs a dora server, its data-dir (to show allocations)" })
|
|
153
153
|
.option("config-dir", { type: "string" }), async (argv) => {
|
|
154
154
|
await cmdUi({ port: argv.port, listen: argv.host ?? argv.listen, doraDir: argv["dora-dir"], configDir: argv["config-dir"] });
|
|
155
|
+
})
|
|
156
|
+
.command("console", "Interactive terminal UI (TUI) — friends list + chat, keyboard-driven (q to quit)", (y) => y.option("config-dir", { type: "string" }), async (argv) => {
|
|
157
|
+
await cmdConsole({ configDir: argv["config-dir"] });
|
|
158
|
+
})
|
|
159
|
+
.command("file <action> <userid> [path]", "Send a file to a friend (toxcore-standard, direct; recipient auto-saves to ~/.agentnet/downloads)", (y) => y
|
|
160
|
+
.positional("action", { type: "string", choices: ["send"], demandOption: true })
|
|
161
|
+
.positional("userid", { type: "string", demandOption: true, describe: "Friend's userid" })
|
|
162
|
+
.positional("path", { type: "string", describe: "Path to the file to send" })
|
|
163
|
+
.option("config-dir", { type: "string" }), async (argv) => {
|
|
164
|
+
if (argv.action === "send") {
|
|
165
|
+
if (!argv.path)
|
|
166
|
+
throw new Error("path is required: agentnet file send <userid> <path>");
|
|
167
|
+
await cmdFileSend({ to: argv.userid, path: argv.path, configDir: argv["config-dir"] });
|
|
168
|
+
}
|
|
155
169
|
})
|
|
156
170
|
// Tell the running daemon to re-exec itself with its original argv.
|
|
157
171
|
// The daemon inherits its own uid (root if it was launched as root)
|