@decentnetwork/beagle 0.1.49 → 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.
package/dist/cli.js CHANGED
@@ -50,6 +50,46 @@ const readJsonVer = (file) => {
50
50
  return "";
51
51
  }
52
52
  };
53
+ const moduleDir = dirname(fileURLToPath(import.meta.url));
54
+ // Version lookup for the "my node" panel.
55
+ //
56
+ // NOT via createRequire().resolve(): peer and lan declare `exports` with an
57
+ // "import" condition only, so CJS resolution throws
58
+ // ERR_PACKAGE_PATH_NOT_EXPORTED for both the bare specifier and
59
+ // "<pkg>/package.json". (decentlan's own UI has the same call and has been
60
+ // silently showing an empty peer version because of it.) import.meta.resolve
61
+ // uses ESM resolution, which honours that condition.
62
+ const resolveVer = (pkg) => {
63
+ const manifestFrom = (start) => {
64
+ let dir = start;
65
+ for (let depth = 0; depth < 6; depth++) {
66
+ const manifest = join(dir, "package.json");
67
+ if (existsSync(manifest)) {
68
+ try {
69
+ const parsed = JSON.parse(readFileSync(manifest, "utf-8"));
70
+ if (parsed.name === pkg)
71
+ return parsed.version ?? "";
72
+ }
73
+ catch {
74
+ // unreadable manifest — keep walking
75
+ }
76
+ }
77
+ const up = dirname(dir);
78
+ if (up === dir)
79
+ break;
80
+ dir = up;
81
+ }
82
+ return undefined;
83
+ };
84
+ try {
85
+ return manifestFrom(dirname(fileURLToPath(import.meta.resolve(pkg)))) ?? "";
86
+ }
87
+ catch {
88
+ // Fall back to a plain node_modules lookup beside this package, which
89
+ // also covers the case where the dependency is absent entirely.
90
+ return manifestFrom(join(moduleDir, "..", "node_modules", ...pkg.split("/"))) ?? "";
91
+ }
92
+ };
53
93
  async function main() {
54
94
  const args = parseArgs(process.argv.slice(2));
55
95
  // Bootstrap list: prefer the user's decentlan config so both stacks agree on
@@ -67,6 +107,7 @@ async function main() {
67
107
  statusMessage,
68
108
  autoAcceptFriends: autoAccept,
69
109
  onAutoAcceptChange: (enabled) => saveAutoAccept(args.configDir, enabled),
110
+ peerVersion: resolveVer("@decentnetwork/peer"),
70
111
  force: args.backend,
71
112
  }));
72
113
  }
@@ -94,46 +135,6 @@ async function main() {
94
135
  makeDaemon: () => makeDaemonHost(decentlanCarrierDir(args.configDir)),
95
136
  onChange: (state) => console.log(`[LAN] backend is now: ${state}`),
96
137
  });
97
- const moduleDir = dirname(fileURLToPath(import.meta.url));
98
- // Version lookup for the "my node" panel.
99
- //
100
- // NOT via createRequire().resolve(): peer and lan declare `exports` with an
101
- // "import" condition only, so CJS resolution throws
102
- // ERR_PACKAGE_PATH_NOT_EXPORTED for both the bare specifier and
103
- // "<pkg>/package.json". (decentlan's own UI has the same call and has been
104
- // silently showing an empty peer version because of it.) import.meta.resolve
105
- // uses ESM resolution, which honours that condition.
106
- const resolveVer = (pkg) => {
107
- const manifestFrom = (start) => {
108
- let dir = start;
109
- for (let depth = 0; depth < 6; depth++) {
110
- const manifest = join(dir, "package.json");
111
- if (existsSync(manifest)) {
112
- try {
113
- const parsed = JSON.parse(readFileSync(manifest, "utf-8"));
114
- if (parsed.name === pkg)
115
- return parsed.version ?? "";
116
- }
117
- catch {
118
- // unreadable manifest — keep walking
119
- }
120
- }
121
- const up = dirname(dir);
122
- if (up === dir)
123
- break;
124
- dir = up;
125
- }
126
- return undefined;
127
- };
128
- try {
129
- return manifestFrom(dirname(fileURLToPath(import.meta.resolve(pkg)))) ?? "";
130
- }
131
- catch {
132
- // Fall back to a plain node_modules lookup beside this package, which
133
- // also covers the case where the dependency is absent entirely.
134
- return manifestFrom(join(moduleDir, "..", "node_modules", ...pkg.split("/"))) ?? "";
135
- }
136
- };
137
138
  // If this machine also runs a dora, surface its allocation table.
138
139
  const doraCandidates = args.doraDir
139
140
  ? [resolve(args.doraDir, "roster.yaml")]
@@ -159,6 +160,9 @@ async function main() {
159
160
  // node look like it was running lan 0.1.0.
160
161
  lanVer: resolveVer("@decentnetwork/lan") || "(none)",
161
162
  peerVer: resolveVer("@decentnetwork/peer"),
163
+ // The call engine compiled into the served vendor bundle — the version
164
+ // that decides whether a screen share fits the Carrier invite cap.
165
+ webrtcVer: resolveVer("@decentnetwork/peer-webrtc"),
162
166
  wire: "163",
163
167
  channel: "@next",
164
168
  },
@@ -1,4 +1,4 @@
1
- window.__DK_UI_VERSION="0.1.49";
1
+ window.__DK_UI_VERSION="0.1.50";
2
2
  const ICON_PATHS = {
3
3
  // ---- tab bar (the four must feel like one set) ----
4
4
  users: '<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/>',
@@ -2983,6 +2983,20 @@ function CopyBtn({ value, copiedText = "Copied", copyFailedText = "Copy failed",
2983
2983
  function FieldRow({ T, label, value, mono = true, copy, qr, onQr, last }) {
2984
2984
  return /* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "center", gap: 14, padding: "13px 16px", borderBottom: last ? "none" : "1px solid var(--line)" } }, /* @__PURE__ */ React.createElement("span", { style: { width: 130, flexShrink: 0, fontFamily: "var(--mono)", fontSize: 11.5, fontWeight: 600, color: "var(--faint)", textTransform: "uppercase", letterSpacing: 0.5 } }, label), /* @__PURE__ */ React.createElement("span", { style: { flex: 1, minWidth: 0, fontFamily: mono ? "var(--mono)" : "var(--ui)", fontSize: 13.5, color: "var(--text)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" } }, value), copy && /* @__PURE__ */ React.createElement(CopyBtn, { value, copiedText: T.copied, copyFailedText: T.copyFailed, copyTitle: T.copy }), qr && /* @__PURE__ */ React.createElement(Btn, { icon: "qr", size: "sm", onClick: () => onQr && onQr(value, label) }));
2985
2985
  }
2986
+ function DkVersionRow({ T, me }) {
2987
+ const unsure = me.verFromBackend === false;
2988
+ const pill = (name, ver, mark) => /* @__PURE__ */ React.createElement("span", { key: name, style: { display: "inline-flex", alignItems: "baseline", gap: 5 } }, /* @__PURE__ */ React.createElement("span", { style: { color: "var(--faint)" } }, name), /* @__PURE__ */ React.createElement("span", { title: mark && unsure ? T.verInstalledHint : void 0 }, ver || "\u2014", mark && unsure && ver ? /* @__PURE__ */ React.createElement("span", { style: { color: "var(--faint)" } }, " ?") : null));
2989
+ const line = (label, items) => /* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "baseline", gap: 10, flexWrap: "wrap" } }, /* @__PURE__ */ React.createElement("span", { style: { width: 52, flexShrink: 0, fontSize: 11, color: "var(--faint)" } }, label), /* @__PURE__ */ React.createElement("span", { style: { display: "flex", gap: 12, flexWrap: "wrap" } }, items));
2990
+ const embedded = me.backend === "embedded";
2991
+ return /* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "flex-start", gap: 14, padding: "13px 16px", borderBottom: "1px solid var(--line)" } }, /* @__PURE__ */ React.createElement("span", { style: { width: 130, flexShrink: 0, fontFamily: "var(--mono)", fontSize: 11.5, fontWeight: 600, color: "var(--faint)", textTransform: "uppercase", letterSpacing: 0.5 } }, T.version), /* @__PURE__ */ React.createElement("div", { style: { flex: 1, minWidth: 0, display: "flex", flexDirection: "column", gap: 6, fontFamily: "var(--mono)", fontSize: 13, color: "var(--text)" } }, line(T.verApp || "app", [
2992
+ pill("beagle", me.beagleVer),
2993
+ pill("peer-webrtc", me.webrtcVer),
2994
+ ...embedded ? [pill("peer", me.peerVer)] : []
2995
+ ]), !embedded && line(T.verDaemon || "daemon", [
2996
+ pill("lan", me.lanVer, true),
2997
+ pill("peer", me.peerVer, true)
2998
+ ]), !embedded && unsure && /* @__PURE__ */ React.createElement("div", { style: { fontSize: 11, color: "var(--faint)", fontFamily: "var(--ui)" } }, T.verInstalledHint), line(T.verChannel || "channel", [/* @__PURE__ */ React.createElement("span", { key: "ch" }, me.channel)])));
2999
+ }
2986
3000
  function DkQrModal({ T, value, label, onClose }) {
2987
3001
  const qr = React.useMemo(() => {
2988
3002
  if (typeof qrcode === "undefined")
@@ -3472,7 +3486,7 @@ function ProfileTab({ T, me, onEdit }) {
3472
3486
  },
3473
3487
  style: { width: 16, height: 16, accentColor: "var(--accent)" }
3474
3488
  }
3475
- ), /* @__PURE__ */ React.createElement("div", { style: { flex: 1 } }, /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--mono)", fontSize: 13.5, fontWeight: 600, color: "var(--text)" } }, T && T.autoAcceptLabel || "Auto-accept friend requests"), /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 11.5, color: "var(--dim)", marginTop: 2 } }, T && T.autoAcceptSub || "Off: requests wait in the sidebar for your approval.")))), /* @__PURE__ */ React.createElement(Card, { label: T.network }, /* @__PURE__ */ React.createElement(FieldRow, { T, label: T.virtualIp, value: me.ip, copy: true }), /* @__PURE__ */ React.createElement(FieldRow, { T, label: T.wireLabel, value: `${me.wire} \xB7 lossless`, mono: false }), /* @__PURE__ */ React.createElement(FieldRow, { T, label: T.version, value: `lan ${me.lanVer} \xB7 peer ${me.peerVer} \xB7 ${me.channel}` }), /* @__PURE__ */ React.createElement(DkUpdateCheck, { T })), /* @__PURE__ */ React.createElement(Card, { label: T.dangerZone }, /* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "center", gap: 13, padding: "14px 16px" } }, /* @__PURE__ */ React.createElement("div", { style: { width: 34, height: 34, borderRadius: 8, flexShrink: 0, background: "color-mix(in oklab, var(--danger), transparent 86%)", display: "flex", alignItems: "center", justifyContent: "center", color: "var(--danger)" } }, /* @__PURE__ */ React.createElement(Icon, { name: "trash", size: 17, stroke: 2 })), /* @__PURE__ */ React.createElement("div", { style: { flex: 1 } }, /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--mono)", fontSize: 13.5, fontWeight: 600, color: "var(--danger)" } }, T.deleteNode), /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12, color: "var(--faint)", marginTop: 1 } }, T.deleteSub)), /* @__PURE__ */ React.createElement(Btn, { tone: "danger", size: "sm" }, T.delete)))), qr && /* @__PURE__ */ React.createElement(DkQrModal, { T, value: qr.value, label: qr.label, onClose: () => setQr(null) }), editing && /* @__PURE__ */ React.createElement(DkEditModal, { T, me, onClose: () => setEditing(false), onSave: (name, description) => {
3489
+ ), /* @__PURE__ */ React.createElement("div", { style: { flex: 1 } }, /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--mono)", fontSize: 13.5, fontWeight: 600, color: "var(--text)" } }, T && T.autoAcceptLabel || "Auto-accept friend requests"), /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 11.5, color: "var(--dim)", marginTop: 2 } }, T && T.autoAcceptSub || "Off: requests wait in the sidebar for your approval.")))), /* @__PURE__ */ React.createElement(Card, { label: T.network }, /* @__PURE__ */ React.createElement(FieldRow, { T, label: T.virtualIp, value: me.ip, copy: true }), /* @__PURE__ */ React.createElement(FieldRow, { T, label: T.wireLabel, value: `${me.wire} \xB7 lossless`, mono: false }), /* @__PURE__ */ React.createElement(DkVersionRow, { T, me }), /* @__PURE__ */ React.createElement(DkUpdateCheck, { T })), /* @__PURE__ */ React.createElement(Card, { label: T.dangerZone }, /* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "center", gap: 13, padding: "14px 16px" } }, /* @__PURE__ */ React.createElement("div", { style: { width: 34, height: 34, borderRadius: 8, flexShrink: 0, background: "color-mix(in oklab, var(--danger), transparent 86%)", display: "flex", alignItems: "center", justifyContent: "center", color: "var(--danger)" } }, /* @__PURE__ */ React.createElement(Icon, { name: "trash", size: 17, stroke: 2 })), /* @__PURE__ */ React.createElement("div", { style: { flex: 1 } }, /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--mono)", fontSize: 13.5, fontWeight: 600, color: "var(--danger)" } }, T.deleteNode), /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12, color: "var(--faint)", marginTop: 1 } }, T.deleteSub)), /* @__PURE__ */ React.createElement(Btn, { tone: "danger", size: "sm" }, T.delete)))), qr && /* @__PURE__ */ React.createElement(DkQrModal, { T, value: qr.value, label: qr.label, onClose: () => setQr(null) }), editing && /* @__PURE__ */ React.createElement(DkEditModal, { T, me, onClose: () => setEditing(false), onSave: (name, description) => {
3476
3490
  if (onEdit)
3477
3491
  onEdit(name, description);
3478
3492
  setEditing(false);
@@ -4595,6 +4609,10 @@ const STR = {
4595
4609
  virtualIp: "virtual ip",
4596
4610
  version: "version",
4597
4611
  editProfile: "edit",
4612
+ verApp: "app",
4613
+ verDaemon: "daemon",
4614
+ verChannel: "channel",
4615
+ verInstalledHint: "installed on disk \u2014 restart the daemon so it can report what it is actually running",
4598
4616
  copy: "Copy",
4599
4617
  copied: "Copied",
4600
4618
  copyFailed: "Copy failed",
@@ -4764,6 +4782,10 @@ const STR = {
4764
4782
  virtualIp: "\u865A\u62DF IP",
4765
4783
  version: "\u7248\u672C",
4766
4784
  editProfile: "\u7F16\u8F91",
4785
+ verApp: "\u5E94\u7528",
4786
+ verDaemon: "\u5B88\u62A4\u8FDB\u7A0B",
4787
+ verChannel: "\u901A\u9053",
4788
+ verInstalledHint: "\u8FD9\u662F\u78C1\u76D8\u4E0A\u5DF2\u5B89\u88C5\u7684\u7248\u672C\uFF1B\u91CD\u542F\u5B88\u62A4\u8FDB\u7A0B\u540E\u624D\u80FD\u663E\u793A\u5B83\u771F\u6B63\u8FD0\u884C\u7684\u7248\u672C",
4767
4789
  copy: "\u590D\u5236",
4768
4790
  copied: "\u5DF2\u590D\u5236",
4769
4791
  copyFailed: "\u590D\u5236\u5931\u8D25",
@@ -24,6 +24,9 @@ export interface EmbeddedHostOptions {
24
24
  description?: string;
25
25
  }) => void;
26
26
  onAutoAcceptChange?: (enabled: boolean) => void;
27
+ /** @decentnetwork/peer version backing this embedded node, surfaced by `ping`
28
+ * so the panel can name the code that is actually running. */
29
+ peerVersion?: string;
27
30
  }
28
31
  export declare class EmbeddedHost implements PeerHost {
29
32
  #private;
@@ -313,7 +313,10 @@ export class EmbeddedHost {
313
313
  const uid = (req.userid ?? "");
314
314
  switch (req.op) {
315
315
  case "ping":
316
- return { ok: true };
316
+ // Embedded backend: there is no daemon, so the versions the UI should
317
+ // show are this process's own — reported the same way the daemon
318
+ // reports its, so the panel needs no special case.
319
+ return { ok: true, backend: "embedded", peerVer: this.#opts.peerVersion ?? "" };
317
320
  case "diag": {
318
321
  const id = this.#node.identity();
319
322
  return {
@@ -37,6 +37,10 @@ export interface OpenPeerHostOptions {
37
37
  nickname?: string;
38
38
  statusMessage?: string;
39
39
  autoAcceptFriends?: boolean;
40
+ /** @decentnetwork/peer version, forwarded to an embedded host so its `ping`
41
+ * can name the code actually running. Ignored for a daemon host — the
42
+ * daemon reports its own. */
43
+ peerVersion?: string;
40
44
  /** Persist a runtime auto-accept toggle (embedded backend only). */
41
45
  onAutoAcceptChange?: (enabled: boolean) => void;
42
46
  /** Force a backend instead of auto-detecting. Mainly for testing the
package/dist/peer-host.js CHANGED
@@ -98,6 +98,7 @@ export async function openPeerHost(opts) {
98
98
  statusMessage: opts.statusMessage,
99
99
  autoAcceptFriends: opts.autoAcceptFriends ?? true,
100
100
  onAutoAcceptChange: opts.onAutoAcceptChange,
101
+ peerVersion: opts.peerVersion,
101
102
  });
102
103
  await host.start();
103
104
  return {
package/dist/server.d.ts CHANGED
@@ -14,6 +14,7 @@ export interface BeagleServerOptions {
14
14
  meExtra?: {
15
15
  lanVer?: string;
16
16
  peerVer?: string;
17
+ webrtcVer?: string;
17
18
  wire?: string;
18
19
  channel?: string;
19
20
  };
package/dist/server.js CHANGED
@@ -206,6 +206,35 @@ function beagleVersion() {
206
206
  return "";
207
207
  }
208
208
  }
209
+ /**
210
+ * Versions of the code the BACKEND process is running, straight from its `ping`.
211
+ *
212
+ * meExtra reads beagle's own node_modules, which describes the packages sitting
213
+ * beside beagle — not the daemon answering our calls. After `npm i -g` but
214
+ * before a daemon restart those disagree, and the panel confidently showed the
215
+ * new version while the old build was still serving every message. Ask the
216
+ * process itself; fall back to meExtra when it is too old to answer.
217
+ */
218
+ const RUNNING_VER_TTL_MS = 30_000;
219
+ let runningVerCache = null;
220
+ async function runningVersions(call) {
221
+ if (runningVerCache && Date.now() - runningVerCache.at < RUNNING_VER_TTL_MS) {
222
+ return { lanVer: runningVerCache.lanVer, peerVer: runningVerCache.peerVer };
223
+ }
224
+ let lanVer = "";
225
+ let peerVer = "";
226
+ try {
227
+ const r = await call({ op: "ping" });
228
+ const data = (r.ok ? r.data : undefined) ?? {};
229
+ lanVer = String(data.lanVer ?? "");
230
+ peerVer = String(data.peerVer ?? "");
231
+ }
232
+ catch {
233
+ // Backend down or too old to report — the caller falls back.
234
+ }
235
+ runningVerCache = { at: Date.now(), lanVer, peerVer };
236
+ return { lanVer, peerVer };
237
+ }
209
238
  /** How this copy of beagle got onto disk — decides what "update" can do.
210
239
  * npx cache paths contain _npx AND node_modules, so test _npx first. */
211
240
  function installMode() {
@@ -1309,7 +1338,8 @@ export function startBeagleServer(opts) {
1309
1338
  npmLatest("@decentnetwork/peer"),
1310
1339
  npmLatest("@decentnetwork/lan"),
1311
1340
  ]);
1312
- const curLan = opts.meExtra?.lanVer ?? "";
1341
+ const running = await runningVersions(opts.call);
1342
+ const curLan = running.lanVer || (opts.meExtra?.lanVer ?? "");
1313
1343
  const row = (pkg, current, latest) => ({
1314
1344
  pkg,
1315
1345
  current,
@@ -1322,8 +1352,10 @@ export function startBeagleServer(opts) {
1322
1352
  mode: installMode(),
1323
1353
  updates: [
1324
1354
  row(BEAGLE_PKG, beagleVersion(), beagleLatest),
1325
- // peer ships inside beagle: reinstalling beagle refreshes it too.
1326
- row("@decentnetwork/peer", opts.meExtra?.peerVer ?? "", peerLatest),
1355
+ // The peer the BACKEND is running a daemon that has been updated
1356
+ // on disk but not restarted must still read as behind, or the panel
1357
+ // reports a fix as live while the old build is serving.
1358
+ row("@decentnetwork/peer", running.peerVer || (opts.meExtra?.peerVer ?? ""), peerLatest),
1327
1359
  ...(curLan && curLan !== "(none)" ? [row("@decentnetwork/lan", curLan, lanLatest)] : []),
1328
1360
  ],
1329
1361
  };
@@ -1403,11 +1435,12 @@ export function startBeagleServer(opts) {
1403
1435
  return;
1404
1436
  }
1405
1437
  if (req.method === "GET" && url === "/api/desktop") {
1406
- const [diag, pending, flist, ensPub] = await Promise.all([
1438
+ const [diag, pending, flist, ensPub, running] = await Promise.all([
1407
1439
  opts.call({ op: "diag" }),
1408
1440
  opts.call({ op: "friends-pending" }),
1409
1441
  opts.call({ op: "friends-list" }),
1410
1442
  ensPublicByUserid(),
1443
+ runningVersions(opts.call),
1411
1444
  ]);
1412
1445
  const d = (diag.ok ? diag.data : {}) ?? {};
1413
1446
  const identity = d.identity ?? {};
@@ -1449,8 +1482,15 @@ export function startBeagleServer(opts) {
1449
1482
  ip: tun.ip ?? d.allocatedIp ?? "",
1450
1483
  online: node.backend === "embedded" ? embeddedOnline : !!tun.ip,
1451
1484
  lan: !!tun.ip,
1452
- lanVer: opts.meExtra?.lanVer ?? "",
1453
- peerVer: opts.meExtra?.peerVer ?? "",
1485
+ // Prefer what the backend says it is running over what sits in our
1486
+ // node_modules see `runningVersions`.
1487
+ lanVer: running.lanVer || (opts.meExtra?.lanVer ?? ""),
1488
+ peerVer: running.peerVer || (opts.meExtra?.peerVer ?? ""),
1489
+ webrtcVer: opts.meExtra?.webrtcVer ?? "",
1490
+ backend: String(node.backend ?? "daemon"),
1491
+ // false = the backend is too old to report its own versions, so the
1492
+ // numbers above are what is INSTALLED, which is not the same claim.
1493
+ verFromBackend: !!running.peerVer,
1454
1494
  channel: opts.meExtra?.channel ?? "@next",
1455
1495
  wire: opts.meExtra?.wire ?? "163",
1456
1496
  isExit: !!meExit,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decentnetwork/beagle",
3
- "version": "0.1.49",
3
+ "version": "0.1.50",
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",
@@ -26,7 +26,7 @@
26
26
  },
27
27
  "dependencies": {
28
28
  "@decentnetwork/chat-components": "^0.1.3",
29
- "@decentnetwork/lan": "^0.1.276",
29
+ "@decentnetwork/lan": "^0.1.277",
30
30
  "@decentnetwork/peer": "^0.1.139",
31
31
  "@decentnetwork/peer-webrtc": "^0.2.16",
32
32
  "js-yaml": "^4.1.0",