@decentnetwork/lan 0.1.108 → 0.1.110

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.
Binary file
Binary file
Binary file
Binary file
@@ -5,6 +5,7 @@ import { render } from "ink";
5
5
  import React from "react";
6
6
  import { Box as Box2, Text as Text2, useApp, useInput, useStdout } from "ink";
7
7
  import { spawn } from "node:child_process";
8
+ import { homedir } from "node:os";
8
9
 
9
10
  // src/console/theme.ts
10
11
  var PALETTES = {
@@ -274,7 +275,7 @@ function HelpBar({ th, T, focus, overlay }) {
274
275
  if (focus === "input") {
275
276
  return /* @__PURE__ */ jsxs(Box, { children: [
276
277
  /* @__PURE__ */ jsx(Text, { color: th.accent, children: "\u25CF input " }),
277
- /* @__PURE__ */ jsx(Text, { color: th.dim, children: `type to compose \xB7 \u21B5 ${focusSend(T)} \xB7 esc/< ${T.friends.toLowerCase()} \xB7 Tab switch \xB7 /q /r /add /alias` })
278
+ /* @__PURE__ */ jsx(Text, { color: th.dim, children: `type to compose \xB7 \u21B5 ${focusSend(T)} \xB7 esc/< ${T.friends.toLowerCase()} \xB7 Tab \xB7 /send <path> /q /r /add /alias` })
278
279
  ] });
279
280
  }
280
281
  const items = [["\u2191\u2193", T.move], ["\u21B5/>", T.chat], ["r", T.reqShort], ["d", T.remove], ["a", T.alias], ["+", T.add], ["q", T.quit]];
@@ -520,6 +521,16 @@ function App({ client }) {
520
521
  clipboardWrite(me.userId);
521
522
  flashCopied();
522
523
  }
524
+ } else if (c === "send" || c === "file") {
525
+ if (friend && arg) {
526
+ const id = friend.id;
527
+ const path = arg.replace(/^~(?=$|\/)/, homedir());
528
+ const base = path.split("/").pop() || "file";
529
+ setThreads((t) => ({ ...t, [id]: [...t[id] || [], { t: now(), who: "me", text: `\u{1F4CE} ${base} \u2026` }] }));
530
+ void client.sendFile(id, path).then((r) => {
531
+ if (!r.ok) setThreads((t) => ({ ...t, [id]: [...t[id] || [], { t: now(), who: "me", text: `\u26A0 ${r.error || "send failed"}` }] }));
532
+ }).catch(() => void 0);
533
+ }
523
534
  }
524
535
  };
525
536
  const n = friends.length;
@@ -642,16 +653,16 @@ function now() {
642
653
  // src/console/data.ts
643
654
  import { createConnection } from "node:net";
644
655
  import { resolve as resolve2 } from "node:path";
645
- import { homedir as homedir2 } from "node:os";
656
+ import { homedir as homedir3 } from "node:os";
646
657
  import { createRequire } from "node:module";
647
658
 
648
659
  // src/config/loader.ts
649
660
  import { readFileSync, existsSync } from "fs";
650
661
  import { resolve, dirname } from "path";
651
662
  import { mkdirSync } from "fs";
652
- import { homedir } from "os";
663
+ import { homedir as homedir2 } from "os";
653
664
  import yaml from "js-yaml";
654
- var DEFAULT_CONFIG_DIR = resolve(homedir(), ".agentnet");
665
+ var DEFAULT_CONFIG_DIR = resolve(homedir2(), ".agentnet");
655
666
  var DEFAULT_CONFIG_FILE = resolve(DEFAULT_CONFIG_DIR, "config.yaml");
656
667
  var DEFAULT_BOOTSTRAP_NODES = [
657
668
  // US-East — closest for typical North-American peers.
@@ -873,6 +884,13 @@ var ConfigLoader = class {
873
884
  };
874
885
 
875
886
  // src/console/data.ts
887
+ function fileSize(n) {
888
+ if (!n || n < 0) return "0 B";
889
+ if (n < 1024) return `${n} B`;
890
+ if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;
891
+ if (n < 1024 * 1024 * 1024) return `${(n / (1024 * 1024)).toFixed(1)} MB`;
892
+ return `${(n / (1024 * 1024 * 1024)).toFixed(2)} GB`;
893
+ }
876
894
  function hhmm(ts) {
877
895
  if (!ts) return "";
878
896
  const d = new Date(ts);
@@ -891,7 +909,7 @@ var DaemonClient = class _DaemonClient {
891
909
  this.sockPath = sockPath;
892
910
  }
893
911
  static async create(configDir) {
894
- const dir = configDir ?? resolve2(homedir2(), ".agentnet");
912
+ const dir = configDir ?? resolve2(homedir3(), ".agentnet");
895
913
  const config = await ConfigLoader.load(resolve2(dir, "config.yaml"));
896
914
  const dataDir = (config.carrier.dataDir || resolve2(dir, "carrier")).replace(/\/+$/, "");
897
915
  return new _DaemonClient(`${dataDir}/daemon.sock`);
@@ -1034,15 +1052,24 @@ var DaemonClient = class _DaemonClient {
1034
1052
  const r = await this.call({ op: "chat-history", userid }).catch(() => ({ ok: false, error: "x" }));
1035
1053
  const chats = _DaemonClient.data(r).chats ?? {};
1036
1054
  const arr = chats[userid] ?? [];
1037
- return arr.map((m) => ({
1038
- t: hhmm(typeof m.ts === "number" ? m.ts : void 0),
1039
- who: m.dir === "out" ? "me" : "them",
1040
- text: String(m.text ?? "")
1041
- }));
1055
+ return arr.map((m) => {
1056
+ const file = m.file;
1057
+ const text = file ? `\u{1F4CE} ${file.name ?? "file"} (${fileSize(typeof file.size === "number" ? file.size : 0)})` : String(m.text ?? "");
1058
+ return {
1059
+ t: hhmm(typeof m.ts === "number" ? m.ts : void 0),
1060
+ who: m.dir === "out" ? "me" : "them",
1061
+ text
1062
+ };
1063
+ });
1042
1064
  }
1043
1065
  send(userid, text) {
1044
1066
  return this.call({ op: "chat-send", userid, text });
1045
1067
  }
1068
+ /** Send a local file to a friend (toxcore transfer); recipient auto-saves to
1069
+ * ~/.agentnet/downloads. The 30s timeout covers reading + offering a file. */
1070
+ sendFile(userid, path) {
1071
+ return this.call({ op: "file-send", userid, path }, 3e4);
1072
+ }
1046
1073
  markRead(userid) {
1047
1074
  return this.call({ op: "chat-mark-read", userid });
1048
1075
  }
@@ -197,10 +197,23 @@ const dkApi = {
197
197
  alias: (userid, alias) => dkPost("/api/friend-alias", { userid, alias }),
198
198
  markRead: (userid) => dkPost("/api/chat-mark-read", { userid }),
199
199
  setProfile: (name, description) => dkPost("/api/set-profile", { name, description }),
200
- sendFile: (userid, file) => fetch(
201
- "/api/file-send?userid=" + encodeURIComponent(userid) + "&name=" + encodeURIComponent(file.name),
202
- { method: "POST", body: file }
203
- ).then((r) => r.json()).catch((e) => ({ ok: false, error: String(e) }))
200
+ sendFile: async (userid, file) => {
201
+ try {
202
+ const r = await fetch(
203
+ "/api/file-send?userid=" + encodeURIComponent(userid) + "&name=" + encodeURIComponent(file.name),
204
+ { method: "POST", body: file }
205
+ );
206
+ const txt = await r.text();
207
+ try {
208
+ return JSON.parse(txt);
209
+ } catch {
210
+ if (r.status === 404) return { ok: false, error: "file upload not supported \u2014 update & restart `agentnet ui`" };
211
+ return { ok: false, error: (txt || "HTTP " + r.status).slice(0, 120) };
212
+ }
213
+ } catch (e) {
214
+ return { ok: false, error: String(e) };
215
+ }
216
+ }
204
217
  };
205
218
  const DK_ME_FALLBACK = {
206
219
  name: "\u2026",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decentnetwork/lan",
3
- "version": "0.1.108",
3
+ "version": "0.1.110",
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",