@decentnetwork/beagle 0.1.58 → 0.1.59
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/bridge-roster.d.ts +20 -0
- package/dist/bridge-roster.js +105 -0
- package/dist/cli.js +6 -0
- package/dist/desktop/app.js +4761 -4900
- package/dist/embedded-host.js +5 -0
- package/dist/server.d.ts +4 -0
- package/dist/server.js +70 -5
- package/package.json +7 -3
package/dist/embedded-host.js
CHANGED
|
@@ -201,6 +201,10 @@ export class EmbeddedHost {
|
|
|
201
201
|
// evidence than any status flag, so use it.
|
|
202
202
|
void this.#chainFlush(pubkey);
|
|
203
203
|
});
|
|
204
|
+
// `description` is the self-introduction the sender was asked to write —
|
|
205
|
+
// the entire reason for asking is so the recipient knows who is knocking.
|
|
206
|
+
// It arrives on the packet and used to be dropped here, so the request
|
|
207
|
+
// card had nothing to show but a truncated key.
|
|
204
208
|
this.#node.on("friend-request", (req) => {
|
|
205
209
|
const userid = req.userid ?? req.pubkey;
|
|
206
210
|
if (this.#autoAccept) {
|
|
@@ -214,6 +218,7 @@ export class EmbeddedHost {
|
|
|
214
218
|
userid,
|
|
215
219
|
pubkey: req.pubkey,
|
|
216
220
|
name: req.name,
|
|
221
|
+
descr: req.description,
|
|
217
222
|
hello: req.hello,
|
|
218
223
|
arrivedAt: Date.now(),
|
|
219
224
|
});
|
package/dist/server.d.ts
CHANGED
|
@@ -49,6 +49,10 @@ export interface BeagleServerOptions {
|
|
|
49
49
|
pk: string;
|
|
50
50
|
}>;
|
|
51
51
|
};
|
|
52
|
+
/** Bridge whose roster the "Here" tab shows. The desktop does not route
|
|
53
|
+
* traffic through it — it only completes the handshake to prove its key
|
|
54
|
+
* and read who else is there. */
|
|
55
|
+
bridgeWs?: string;
|
|
52
56
|
}
|
|
53
57
|
export declare function startBeagleServer(opts: BeagleServerOptions): {
|
|
54
58
|
stop: () => void;
|
package/dist/server.js
CHANGED
|
@@ -21,6 +21,7 @@ import { INSTALL_COMMAND as LAN_INSTALL_COMMAND } from "./lan-handoff.js";
|
|
|
21
21
|
import yaml from "js-yaml";
|
|
22
22
|
import { DEFAULT_EXITS } from "./exits.js";
|
|
23
23
|
import * as peerAddr from "@decentnetwork/peer";
|
|
24
|
+
import { bridgeRoster } from "./bridge-roster.js";
|
|
24
25
|
// Directory holding the built desktop UI bundle (index.html, app.js, vendor/).
|
|
25
26
|
// scripts/build-ui.mjs emits it next to this compiled module at dist/ui/desktop/.
|
|
26
27
|
const DESKTOP_DIR = join(dirname(fileURLToPath(import.meta.url)), "desktop");
|
|
@@ -760,7 +761,13 @@ export function startBeagleServer(opts) {
|
|
|
760
761
|
sendJson(res, 200, { ok: true, punk });
|
|
761
762
|
}
|
|
762
763
|
catch (err) {
|
|
763
|
-
|
|
764
|
+
// An id the set does not contain is a normal negative answer, not a
|
|
765
|
+
// gateway failure. Reporting 502 made a bad stored punkId look like
|
|
766
|
+
// the punks service was down, and the client — which only cached
|
|
767
|
+
// successes — retried it on every render.
|
|
768
|
+
const msg = String(err?.message ?? err);
|
|
769
|
+
const missing = /\b404\b|not found/i.test(msg);
|
|
770
|
+
sendJson(res, missing ? 404 : 502, { ok: false, error: missing ? "no such punk" : msg });
|
|
764
771
|
}
|
|
765
772
|
return;
|
|
766
773
|
}
|
|
@@ -1152,6 +1159,9 @@ export function startBeagleServer(opts) {
|
|
|
1152
1159
|
}
|
|
1153
1160
|
const q = new URL(req.url || "", "http://x").searchParams;
|
|
1154
1161
|
const userid = q.get("userid") || "";
|
|
1162
|
+
// The sender's own copy needs saving too, or its chip renders as an
|
|
1163
|
+
// empty 0 B card: the bytes went peer-to-peer and never touched here.
|
|
1164
|
+
const dir = q.get("dir") === "out" ? "out" : "in";
|
|
1155
1165
|
const rawName = q.get("name") || "agentnet-file";
|
|
1156
1166
|
const safe = rawName.replace(/[/\\]/g, "_").slice(0, 200) || "agentnet-file";
|
|
1157
1167
|
if (!userid) {
|
|
@@ -1178,7 +1188,7 @@ export function startBeagleServer(opts) {
|
|
|
1178
1188
|
ws.on("finish", () => resolve2());
|
|
1179
1189
|
});
|
|
1180
1190
|
const st = statSync(finalPath);
|
|
1181
|
-
const r = await opts.call({ op: "file-log-local", userid, dir
|
|
1191
|
+
const r = await opts.call({ op: "file-log-local", userid, dir, name: finalName, size: st.size });
|
|
1182
1192
|
if (!r.ok) {
|
|
1183
1193
|
sendJson(res, 502, r);
|
|
1184
1194
|
return;
|
|
@@ -1359,6 +1369,32 @@ export function startBeagleServer(opts) {
|
|
|
1359
1369
|
}
|
|
1360
1370
|
return;
|
|
1361
1371
|
}
|
|
1372
|
+
if (req.method === "GET" && url === "/api/bridge-roster") {
|
|
1373
|
+
// Same shape the browser build returns, so discover.jsx renders it
|
|
1374
|
+
// without knowing which client it is running in.
|
|
1375
|
+
if (!opts.bridgeWs || !opts.callIce?.keyFile) {
|
|
1376
|
+
return sendJson(res, 200, { ok: true, list: [], pending: true });
|
|
1377
|
+
}
|
|
1378
|
+
try {
|
|
1379
|
+
// diag already carries both facts, so there is no second round trip
|
|
1380
|
+
// and no op to add: the address is the identity, the nickname is the
|
|
1381
|
+
// node's own name.
|
|
1382
|
+
const diag = (await opts.call({ op: "diag" }));
|
|
1383
|
+
const r = await bridgeRoster(opts.bridgeWs, opts.callIce.keyFile, {
|
|
1384
|
+
name: diag?.node?.name,
|
|
1385
|
+
address: diag?.identity?.address,
|
|
1386
|
+
});
|
|
1387
|
+
if (!r)
|
|
1388
|
+
return sendJson(res, 200, { ok: true, list: [], pending: true });
|
|
1389
|
+
return sendJson(res, 200, {
|
|
1390
|
+
ok: true, bridge: r.bridge, online: r.online,
|
|
1391
|
+
list: r.peers.map((p) => ({ ...p, punkId: p.punk ?? null })),
|
|
1392
|
+
});
|
|
1393
|
+
}
|
|
1394
|
+
catch (err) {
|
|
1395
|
+
return sendJson(res, 200, { ok: false, error: String(err?.message ?? err) });
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1362
1398
|
if (req.method === "GET" && url === "/api/discover-registered") {
|
|
1363
1399
|
try {
|
|
1364
1400
|
const raw = (await fetchDiscoverJson(`${ENS_GATEWAY}/names`));
|
|
@@ -1475,8 +1511,28 @@ export function startBeagleServer(opts) {
|
|
|
1475
1511
|
if (req.method === "GET" && url === "/api/ens-profile") {
|
|
1476
1512
|
const q = new URL(req.url || "", "http://localhost").searchParams;
|
|
1477
1513
|
let userid = q.get("userid") || "";
|
|
1514
|
+
// Also accept ?name= (a beagles.eth display name), so a group sender
|
|
1515
|
+
// known only by nickname still resolves to its avatar — the userid is
|
|
1516
|
+
// simply not available for those.
|
|
1517
|
+
const qname = q.get("name") || "";
|
|
1518
|
+
if (!userid && qname) {
|
|
1519
|
+
const norm = (x) => String(x || "").toLowerCase().replace(/\s+/g, "");
|
|
1520
|
+
for (const [uid, prof] of await ensPublicByUserid(1500)) {
|
|
1521
|
+
if (norm(prof.displayName || "") === norm(qname) || norm(prof.ens || "") === norm(qname)) {
|
|
1522
|
+
userid = uid;
|
|
1523
|
+
break;
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
}
|
|
1527
|
+
// A name nobody has registered is a lookup that found nothing, not a
|
|
1528
|
+
// bad request: 400 makes the caller log an error and, worse, retry.
|
|
1529
|
+
// Only the missing PARAMETER is the client's mistake.
|
|
1478
1530
|
if (!userid) {
|
|
1479
|
-
|
|
1531
|
+
if (qname) {
|
|
1532
|
+
sendJson(res, 200, { ok: true, registered: false, profile: null });
|
|
1533
|
+
return;
|
|
1534
|
+
}
|
|
1535
|
+
sendJson(res, 400, { ok: false, error: "userid or name required" });
|
|
1480
1536
|
return;
|
|
1481
1537
|
}
|
|
1482
1538
|
// A 52-char Carrier ADDRESS also works (group cards only have that):
|
|
@@ -1596,6 +1652,10 @@ export function startBeagleServer(opts) {
|
|
|
1596
1652
|
agent: false,
|
|
1597
1653
|
lastMsg: lm ? (lm.dir === "out" ? "you: " : "") + (lm.text ?? "") : "",
|
|
1598
1654
|
lastTime: fmtTime(lm?.ts),
|
|
1655
|
+
// The raw stamp too: lastTime is formatted for display and cannot
|
|
1656
|
+
// be ordered, which is why the sidebar never reordered on new
|
|
1657
|
+
// activity.
|
|
1658
|
+
lastTs: lm?.ts ?? 0,
|
|
1599
1659
|
wire: "163",
|
|
1600
1660
|
avatarUrl: ensPub.get(uid)?.avatarUrl ?? null,
|
|
1601
1661
|
punkId: ensPub.get(uid)?.punkId ?? null,
|
|
@@ -1606,8 +1666,13 @@ export function startBeagleServer(opts) {
|
|
|
1606
1666
|
id: p.userid || p.address || `r${i}`,
|
|
1607
1667
|
carrier: p.address || p.userid || "",
|
|
1608
1668
|
userid: p.userid || "",
|
|
1609
|
-
|
|
1610
|
-
|
|
1669
|
+
// Name and introduction travel in the friend-request packet and were
|
|
1670
|
+
// being dropped here, so every request looked identical and there
|
|
1671
|
+
// was nothing to decide on.
|
|
1672
|
+
name: p.name || "",
|
|
1673
|
+
descr: p.descr || "",
|
|
1674
|
+
via: p.hello || "lan",
|
|
1675
|
+
time: fmtTime(p.arrivedAt),
|
|
1611
1676
|
}));
|
|
1612
1677
|
// Exit nodes = the AVAILABLE exits this node knows about, grouped by
|
|
1613
1678
|
// region. The authoritative list is the shipped DEFAULT_EXITS
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@decentnetwork/beagle",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.59",
|
|
4
4
|
"description": "Beagle — P2P chat, file transfer and calls for regular users, on the Decent Network. No admin privilege required.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
}
|
|
20
20
|
},
|
|
21
21
|
"scripts": {
|
|
22
|
-
"build": "tsc -p tsconfig.json && chmod +x dist/cli.js && node scripts/build-ui.mjs",
|
|
22
|
+
"build": "npm run build -w @decentnetwork/beagle-ui && tsc -p tsconfig.json && chmod +x dist/cli.js && node scripts/build-ui.mjs",
|
|
23
23
|
"typecheck": "tsc --noEmit",
|
|
24
24
|
"clean": "rm -rf dist",
|
|
25
25
|
"start": "node dist/cli.js"
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"yargs": "^17.7.2"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
|
+
"@decentnetwork/beagle-ui": "0.1.0",
|
|
36
37
|
"@types/js-yaml": "^4.0.9",
|
|
37
38
|
"@types/node": "^20.11.0",
|
|
38
39
|
"@types/yargs": "^17.0.32",
|
|
@@ -42,5 +43,8 @@
|
|
|
42
43
|
"engines": {
|
|
43
44
|
"node": ">=20"
|
|
44
45
|
},
|
|
45
|
-
"license": "MIT"
|
|
46
|
+
"license": "MIT",
|
|
47
|
+
"workspaces": [
|
|
48
|
+
"packages/*"
|
|
49
|
+
]
|
|
46
50
|
}
|