@decentnetwork/beagle 0.1.101 → 0.1.103
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/desktop/app.js +35 -7
- package/dist/server.js +26 -7
- package/package.json +2 -2
package/dist/desktop/app.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
window.__DK_UI_VERSION="0.1.
|
|
1
|
+
window.__DK_UI_VERSION="0.1.103";
|
|
2
2
|
"use strict";
|
|
3
3
|
(() => {
|
|
4
4
|
// packages/beagle-ui/dist/beagle-ui.js
|
|
@@ -118,12 +118,14 @@ window.__DK_UI_VERSION="0.1.101";
|
|
|
118
118
|
var hostPrefersRtcFile = false;
|
|
119
119
|
var hostHasKeyBackup = false;
|
|
120
120
|
var hostEnsWrite = true;
|
|
121
|
+
var hostBrandHref = "";
|
|
121
122
|
function setUiHost(host2) {
|
|
122
123
|
H = host2 || {};
|
|
123
124
|
hostNeedsWelcome = !!H.hostNeedsWelcome;
|
|
124
125
|
hostPrefersRtcFile = !!H.hostPrefersRtcFile;
|
|
125
126
|
hostHasKeyBackup = !!H.hostHasKeyBackup;
|
|
126
127
|
hostEnsWrite = H.hostEnsWrite !== void 0 ? !!H.hostEnsWrite : !H.hostNeedsWelcome;
|
|
128
|
+
hostBrandHref = typeof H.hostBrandHref === "string" ? H.hostBrandHref : "";
|
|
127
129
|
}
|
|
128
130
|
function fileUrl(name) {
|
|
129
131
|
return H.fileUrl ? H.fileUrl(name) : "/api/file-download?name=" + encodeURIComponent(name);
|
|
@@ -4957,6 +4959,7 @@ ${peer.address}`
|
|
|
4957
4959
|
pubRecSent: "sent \u2713",
|
|
4958
4960
|
updTitle: "Update available",
|
|
4959
4961
|
updLater: "Later",
|
|
4962
|
+
brandAbout: "What is Beagle?",
|
|
4960
4963
|
updNow: "Update now",
|
|
4961
4964
|
updRestart: "Restart",
|
|
4962
4965
|
updBusy: "Updating\u2026 (about a minute)",
|
|
@@ -4971,9 +4974,10 @@ ${peer.address}`
|
|
|
4971
4974
|
updCheckLabel: "updates",
|
|
4972
4975
|
updLatest: "up to date \u2713",
|
|
4973
4976
|
updLanNow: "Update lan",
|
|
4977
|
+
updDaemonNote: "The network daemon (agentnet) is behind. Update reinstalls it and restarts it \u2014 messages pause for a few seconds.",
|
|
4974
4978
|
updManualHint: "Run it in a terminal, then click Restart to apply.",
|
|
4975
4979
|
updLanDone: "lan updated \u2014 daemon restarted with the new version \u2713",
|
|
4976
|
-
updLanNoRestart: "
|
|
4980
|
+
updLanNoRestart: "Installed, but the daemon did not come back within a minute \u2014 the new version applies on its next start.",
|
|
4977
4981
|
pubOpen: "View public profile",
|
|
4978
4982
|
pubNone: "No public profile \u2014 this user has not registered a beagles.eth name.",
|
|
4979
4983
|
ensNoEthWallet: "no Ethereum wallet extension found (MetaMask\u2026)",
|
|
@@ -5145,6 +5149,7 @@ ${peer.address}`
|
|
|
5145
5149
|
pubRecSent: "\u5DF2\u53D1\u9001 \u2713",
|
|
5146
5150
|
updTitle: "\u53D1\u73B0\u65B0\u7248\u672C",
|
|
5147
5151
|
updLater: "\u7A0D\u540E",
|
|
5152
|
+
brandAbout: "Beagle \u662F\u4EC0\u4E48?",
|
|
5148
5153
|
updNow: "\u7ACB\u5373\u66F4\u65B0",
|
|
5149
5154
|
updRestart: "\u91CD\u542F",
|
|
5150
5155
|
updBusy: "\u66F4\u65B0\u4E2D\u2026(\u7EA6\u4E00\u5206\u949F)",
|
|
@@ -5159,9 +5164,10 @@ ${peer.address}`
|
|
|
5159
5164
|
updCheckLabel: "\u66F4\u65B0",
|
|
5160
5165
|
updLatest: "\u5DF2\u662F\u6700\u65B0\u7248\u672C \u2713",
|
|
5161
5166
|
updLanNow: "\u66F4\u65B0 lan",
|
|
5167
|
+
updDaemonNote: "\u7F51\u7EDC\u5B88\u62A4\u8FDB\u7A0B(agentnet)\u6709\u65B0\u7248\u672C\u3002\u70B9\u300C\u7ACB\u5373\u66F4\u65B0\u300D\u4F1A\u91CD\u88C5\u5E76\u91CD\u542F\u5B83,\u6D88\u606F\u4F1A\u6682\u505C\u51E0\u79D2\u3002",
|
|
5162
5168
|
updManualHint: "\u5728\u7EC8\u7AEF\u91CC\u6267\u884C\u4E0A\u9762\u7684\u547D\u4EE4,\u5B8C\u6210\u540E\u70B9\u300C\u91CD\u542F\u300D\u751F\u6548\u3002",
|
|
5163
5169
|
updLanDone: "lan \u5DF2\u66F4\u65B0\u2014\u2014daemon \u5DF2\u7528\u65B0\u7248\u91CD\u542F \u2713",
|
|
5164
|
-
updLanNoRestart: "
|
|
5170
|
+
updLanNoRestart: "\u5DF2\u5B89\u88C5,\u4F46 daemon \u4E00\u5206\u949F\u5185\u6CA1\u6709\u91CD\u65B0\u8D77\u6765\u2014\u2014\u4E0B\u6B21\u542F\u52A8\u65F6\u751F\u6548\u3002",
|
|
5165
5171
|
pubOpen: "\u67E5\u770B\u516C\u5F00\u8D44\u6599",
|
|
5166
5172
|
pubNone: "\u6682\u65E0\u516C\u5F00\u8D44\u6599\u2014\u2014\u5BF9\u65B9\u8FD8\u6CA1\u6709\u6CE8\u518C beagles.eth \u540D\u5B57\u3002",
|
|
5167
5173
|
ensNoEthWallet: "\u672A\u68C0\u6D4B\u5230\u4EE5\u592A\u574A\u94B1\u5305\u63D2\u4EF6(MetaMask \u7B49)",
|
|
@@ -5233,6 +5239,21 @@ ${peer.address}`
|
|
|
5233
5239
|
} }, /* @__PURE__ */ React.createElement(Icon, { name: icon, size: 22, stroke: active ? 2.1 : 1.8, color: active ? "var(--accent)" : "var(--dim)" }), /* @__PURE__ */ React.createElement("span", { style: { fontSize: 10, fontWeight: 600, color: active ? "var(--accent)" : "var(--faint)", whiteSpace: "nowrap" } }, label), badge ? /* @__PURE__ */ React.createElement("span", { style: { position: "absolute", top: 4, left: "50%", marginLeft: 6 } }, /* @__PURE__ */ React.createElement(Unread, { n: badge })) : null);
|
|
5234
5240
|
}
|
|
5235
5241
|
var DK_PEOPLE_TABS = ["here", "recommended", "registered"];
|
|
5242
|
+
function Brand({ T, children, style }) {
|
|
5243
|
+
if (!hostBrandHref)
|
|
5244
|
+
return /* @__PURE__ */ React.createElement("span", { style }, children);
|
|
5245
|
+
return /* @__PURE__ */ React.createElement(
|
|
5246
|
+
"a",
|
|
5247
|
+
{
|
|
5248
|
+
href: hostBrandHref,
|
|
5249
|
+
target: "_blank",
|
|
5250
|
+
rel: "noopener noreferrer",
|
|
5251
|
+
title: T.brandAbout || "What is Beagle?",
|
|
5252
|
+
style: { textDecoration: "none", color: "inherit", display: "flex", alignItems: "center", ...style }
|
|
5253
|
+
},
|
|
5254
|
+
children
|
|
5255
|
+
);
|
|
5256
|
+
}
|
|
5236
5257
|
function DkUpdateModal({ T, info, onClose }) {
|
|
5237
5258
|
const [phase, setPhase] = React.useState("idle");
|
|
5238
5259
|
const [err, setErr] = React.useState(null);
|
|
@@ -5320,10 +5341,17 @@ ${peer.address}`
|
|
|
5320
5341
|
padding: "8px 10px",
|
|
5321
5342
|
userSelect: "all",
|
|
5322
5343
|
wordBreak: "break-all"
|
|
5323
|
-
} }, ownershipFix(info)), /* @__PURE__ */ React.createElement(Btn, { size: "sm", icon: "copy", title: T.copy || "Copy", onClick: () => dkCopy(ownershipFix(info)) })), /* @__PURE__ */ React.createElement("div", { style: { marginTop: 6, fontSize: 11.5, color: "var(--faint)" } }, T.updNoPermAlt || "Do not widen permissions there to make this button work \u2014 a group-writable bin directory lets any admin user replace programs that root later runs. For one-click updates, move npm out of the system prefix instead: `npm config set prefix ~/.npm-global`, then put `~/.npm-global/bin` first on your PATH.")), phase === "idle" && appBehind && info.mode === "dev" && /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12, color: "var(--dim)", lineHeight: 1.5 } }, T.updDev || "Running from a source checkout \u2014 update with:", /* @__PURE__ */ React.createElement("br", null), /* @__PURE__ */ React.createElement("code", { style: { fontFamily: "var(--mono)", fontSize: 11.5, color: "var(--text)" } }, "git pull && npm run build")), phase === "idle" && appBehind && info.mode === "unknown" && /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12, color: "var(--dim)", lineHeight: 1.5 } }, T.updUnknown || "Update now runs the global install. If that is not how this was installed, run:", /* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "center", gap: 8, marginTop: 6 } }, /* @__PURE__ */ React.createElement("code", { style: { flex: 1, minWidth: 0, fontFamily: "var(--mono)", fontSize: 11.5, color: "var(--text)", background: "var(--panel-2)", border: "1px solid var(--line)", borderRadius: 8, padding: "8px 10px", userSelect: "all", wordBreak: "break-all" } }, "npm i -g @decentnetwork/beagle@latest"), /* @__PURE__ */ React.createElement(Btn, { size: "sm", icon: "copy", title: T.copy || "Copy", onClick: () => dkCopy("npm i -g @decentnetwork/beagle@latest") }))), phase === "idle" && appBehind && info.mode === "npx" && /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12, color: "var(--dim)", lineHeight: 1.5 } }, T.updNpx || "Running via npx \u2014 restarting picks up the latest version automatically."), daemonPeerBehind
|
|
5344
|
+
} }, ownershipFix(info)), /* @__PURE__ */ React.createElement(Btn, { size: "sm", icon: "copy", title: T.copy || "Copy", onClick: () => dkCopy(ownershipFix(info)) })), /* @__PURE__ */ React.createElement("div", { style: { marginTop: 6, fontSize: 11.5, color: "var(--faint)" } }, T.updNoPermAlt || "Do not widen permissions there to make this button work \u2014 a group-writable bin directory lets any admin user replace programs that root later runs. For one-click updates, move npm out of the system prefix instead: `npm config set prefix ~/.npm-global`, then put `~/.npm-global/bin` first on your PATH.")), phase === "idle" && appBehind && info.mode === "dev" && /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12, color: "var(--dim)", lineHeight: 1.5 } }, T.updDev || "Running from a source checkout \u2014 update with:", /* @__PURE__ */ React.createElement("br", null), /* @__PURE__ */ React.createElement("code", { style: { fontFamily: "var(--mono)", fontSize: 11.5, color: "var(--text)" } }, "git pull && npm run build")), phase === "idle" && appBehind && info.mode === "unknown" && /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12, color: "var(--dim)", lineHeight: 1.5 } }, T.updUnknown || "Update now runs the global install. If that is not how this was installed, run:", /* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "center", gap: 8, marginTop: 6 } }, /* @__PURE__ */ React.createElement("code", { style: { flex: 1, minWidth: 0, fontFamily: "var(--mono)", fontSize: 11.5, color: "var(--text)", background: "var(--panel-2)", border: "1px solid var(--line)", borderRadius: 8, padding: "8px 10px", userSelect: "all", wordBreak: "break-all" } }, "npm i -g @decentnetwork/beagle@latest"), /* @__PURE__ */ React.createElement(Btn, { size: "sm", icon: "copy", title: T.copy || "Copy", onClick: () => dkCopy("npm i -g @decentnetwork/beagle@latest") }))), phase === "idle" && appBehind && info.mode === "npx" && /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12, color: "var(--dim)", lineHeight: 1.5 } }, T.updNpx || "Running via npx \u2014 restarting picks up the latest version automatically."), (daemonPeerBehind || lanBehind) && phase === "idle" && // One button, no terminal. The command this used to print ran the
|
|
5345
|
+
// shell's npm, which on an nvm machine is often a different node from
|
|
5346
|
+
// the one launchd runs the daemon with — it installed where nothing
|
|
5347
|
+
// looks, and the daemon kept the old peer (Weili's two Macs,
|
|
5348
|
+
// 2026-09-18). The server's update runs with the app's own node and
|
|
5349
|
+
// restarts the daemon the launchd-safe way. Reinstalling lan also
|
|
5350
|
+
// pulls the newest peer it allows, which is what moves the peer row.
|
|
5351
|
+
/* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12, color: "var(--dim)", lineHeight: 1.5 } }, T.updDaemonNote || "The network daemon (agentnet) is behind. Update reinstalls it and restarts it \u2014 messages pause for a few seconds."), phase === "lan-done" && /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12.5, color: "var(--online)" } }, T.updLanDone || "lan updated \u2014 daemon restarted with the new version \u2713"), phase === "lan-norestart" && /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12.5, color: "var(--warn, #f59e0b)" } }, T.updLanNoRestart || "Installed, but the daemon did not come back within a minute \u2014 the new version applies on its next start."), phase === "running" && /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12.5, color: "var(--dim)" } }, T.updBusy || "Updating\u2026 (about a minute)"), phase === "done" && /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12.5, color: "var(--online)" } }, T.updDone || "Updated \u2014 restart to apply."), phase === "restarting" && /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12.5, color: "var(--dim)" } }, T.updRestarting || "Restarting\u2026 this page reloads when it\u2019s back. (If beagle was started by hand in a terminal, run it again.)"), phase === "error" && (() => {
|
|
5324
5352
|
const m = /`([^`]+)`/.exec(err || "");
|
|
5325
5353
|
return /* @__PURE__ */ React.createElement("div", { style: { display: "flex", flexDirection: "column", gap: 8 } }, /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 12, color: "var(--danger)", wordBreak: "break-word" } }, m ? err.replace("`" + m[1] + "`", "") : err), m && /* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "center", gap: 8 } }, /* @__PURE__ */ React.createElement("code", { style: { flex: 1, minWidth: 0, fontFamily: "var(--mono)", fontSize: 11.5, color: "var(--text)", background: "var(--panel-2)", border: "1px solid var(--line)", borderRadius: 8, padding: "8px 10px", userSelect: "all", wordBreak: "break-all" } }, m[1]), /* @__PURE__ */ React.createElement(Btn, { size: "sm", icon: "copy", title: T.copy || "Copy", onClick: () => dkCopy(m[1]) })), m && /* @__PURE__ */ React.createElement("div", { style: { fontFamily: "var(--ui)", fontSize: 11.5, color: "var(--dim)" } }, T.updManualHint || "Run it in a terminal, then click Restart to apply."));
|
|
5326
|
-
})(), /* @__PURE__ */ React.createElement("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8 } }, (phase === "idle" || phase === "error" || phase === "lan-done" || phase === "lan-norestart") && btn(phase === "idle" ? T.updLater || "Later" : T.receivedClose || "Close", onClose), phase === "idle" && lanBehind && btn(T.updLanNow || "Update lan", doLanUpdate, !appBehind), phase === "idle" && appBehind && (info.mode === "global" || info.mode === "unknown") && btn(T.updNow || "Update now", doUpdate, true), phase === "idle" && appBehind && info.mode === "npx" && btn(T.updRestart || "Restart", doRestart, true), phase === "error" && btn(T.updRestart || "Restart", doRestart, true), phase === "done" && btn(T.updRestart || "Restart", doRestart, true))));
|
|
5354
|
+
})(), /* @__PURE__ */ React.createElement("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8 } }, (phase === "idle" || phase === "error" || phase === "lan-done" || phase === "lan-norestart") && btn(phase === "idle" ? T.updLater || "Later" : T.receivedClose || "Close", onClose), phase === "idle" && (lanBehind || daemonPeerBehind) && btn(appBehind ? T.updLanNow || "Update lan" : T.updNow || "Update now", doLanUpdate, !appBehind), phase === "idle" && appBehind && (info.mode === "global" || info.mode === "unknown") && btn(T.updNow || "Update now", doUpdate, true), phase === "idle" && appBehind && info.mode === "npx" && btn(T.updRestart || "Restart", doRestart, true), phase === "error" && btn(T.updRestart || "Restart", doRestart, true), phase === "done" && btn(T.updRestart || "Restart", doRestart, true))));
|
|
5327
5355
|
}
|
|
5328
5356
|
function DkApp() {
|
|
5329
5357
|
const [t, setTweak] = useTweaks({ ...DK_DEFAULTS, lang: dkDetectLang() });
|
|
@@ -5641,14 +5669,14 @@ ${peer.address}`
|
|
|
5641
5669
|
{ id: "profile", icon: "userRound", label: T.profile, active: tab === "profile", go: () => setTab("profile") }
|
|
5642
5670
|
];
|
|
5643
5671
|
const inConversation = phone && tab === "chat" && !!activeId && (peers || []).some((p) => p.id === activeId);
|
|
5644
|
-
return /* @__PURE__ */ React.createElement("div", { style: { ...vars, "--row-pad": rowPad, position: "fixed", inset: 0, display: "flex", flexDirection: phone ? "column" : "row", background: "var(--bg)", color: "var(--text)", fontFamily: "var(--ui)" } }, /* @__PURE__ */ React.createElement(DkPhoneStyles, null), !phone && /* @__PURE__ */ React.createElement("div", { style: { width: 68, flexShrink: 0, borderRight: "1px solid var(--line)", background: "var(--rail)", display: "flex", flexDirection: "column", alignItems: "center", padding: "14px 0", gap: 8 } }, /* @__PURE__ */ React.createElement(
|
|
5672
|
+
return /* @__PURE__ */ React.createElement("div", { style: { ...vars, "--row-pad": rowPad, position: "fixed", inset: 0, display: "flex", flexDirection: phone ? "column" : "row", background: "var(--bg)", color: "var(--text)", fontFamily: "var(--ui)" } }, /* @__PURE__ */ React.createElement(DkPhoneStyles, null), !phone && /* @__PURE__ */ React.createElement("div", { style: { width: 68, flexShrink: 0, borderRight: "1px solid var(--line)", background: "var(--rail)", display: "flex", flexDirection: "column", alignItems: "center", padding: "14px 0", gap: 8 } }, /* @__PURE__ */ React.createElement(Brand, { T, style: { width: 38, height: 38, borderRadius: 10, background: "var(--accent)", display: "flex", alignItems: "center", justifyContent: "center", marginBottom: 8, flexShrink: 0 } }, /* @__PURE__ */ React.createElement(Icon, { name: "terminal", size: 20, color: "#fff", stroke: 2.2 })), nav.map((n) => /* @__PURE__ */ React.createElement(RailBtn, { key: n.id, icon: n.icon, label: n.label, active: tab === n.id, soon: n.soon, onClick: () => setTab(n.id) })), /* @__PURE__ */ React.createElement("div", { style: { flex: 1 } }), /* @__PURE__ */ React.createElement("button", { onClick: () => setTab("profile"), title: T.profile, style: {
|
|
5645
5673
|
padding: 4,
|
|
5646
5674
|
borderRadius: 12,
|
|
5647
5675
|
cursor: "pointer",
|
|
5648
5676
|
display: "flex",
|
|
5649
5677
|
border: "1px solid " + (tab === "profile" ? "var(--line)" : "transparent"),
|
|
5650
5678
|
background: tab === "profile" ? "var(--panel-2)" : "transparent"
|
|
5651
|
-
} }, /* @__PURE__ */ React.createElement(DkAvatar, { peer: { ...me, id: me.userId, agent: false }, size: 36, radius: 9 }))), /* @__PURE__ */ React.createElement("div", { style: { flex: 1, minWidth: 0, minHeight: 0, display: "flex", flexDirection: "column" } }, !inConversation && /* @__PURE__ */ React.createElement(DkBrowserNotice, { lang: t.lang }), !inConversation && /* @__PURE__ */ React.createElement("div", { style: { height: 46, boxSizing: "content-box", paddingTop: phone ? "env(safe-area-inset-top, 0px)" : 0, flexShrink: 0, borderBottom: "1px solid var(--line)", background: "var(--panel)", display: "flex", alignItems: "center", gap: phone ? 8 : 12, paddingLeft: phone ? 12 : 16, paddingRight: phone ? 12 : 16 } }, /* @__PURE__ */ React.createElement("svg", { width: 20, height: 20, viewBox: "0 0 24 24", fill: "none", stroke: "var(--accent)", strokeWidth: 2.2, strokeLinecap: "round", strokeLinejoin: "round", style: { display: "block", flexShrink: 0 } }, /* @__PURE__ */ React.createElement("path", { d: "m4.5 17 6-6-6-6" }), /* @__PURE__ */ React.createElement("path", { d: "M12 18.5h7.5" })), /* @__PURE__ */ React.createElement("span", { style: { fontFamily: "var(--mono)", fontSize: 14, fontWeight: 700, letterSpacing: -0.3, color: "var(--text)" } }, "beagle"), /* @__PURE__ */ React.createElement("span", { style: { fontFamily: "var(--mono)", fontSize: 12, color: "var(--faint)", whiteSpace: "nowrap" } }, "\xB7 ", (nav.find((n) => n.id === tab) || { label: T.profile }).label.toLowerCase()), /* @__PURE__ */ React.createElement("div", { style: { flex: 1 } }), phone ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(StatusDot, { online: me.online }), shareBtn, /* @__PURE__ */ React.createElement("button", { onClick: () => setTab("profile"), title: T.profile, style: { padding: 0, border: "none", background: "transparent", cursor: "pointer", display: "flex" } }, /* @__PURE__ */ React.createElement(DkAvatar, { peer: { ...me, id: me.userId, agent: false }, size: 28, radius: 7, dot: false }))) : /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Tag, { tone: "accent" }, me.channel, " \xB7 lan ", me.lanVer), /* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "center", gap: 7, padding: "0 4px" } }, /* @__PURE__ */ React.createElement(StatusDot, { online: me.online }), /* @__PURE__ */ React.createElement(Mono, { size: 12.5, copy: me.ip }, me.ip)), /* @__PURE__ */ React.createElement("span", { style: { width: 1, height: 22, background: "var(--line)" } }), shareBtn, /* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "center", gap: 8 } }, /* @__PURE__ */ React.createElement(DkAvatar, { peer: { ...me, id: me.userId, agent: false }, size: 26, radius: 7 }), /* @__PURE__ */ React.createElement("span", { style: { fontFamily: "var(--mono)", fontSize: 12.5, fontWeight: 600, color: "var(--text)" } }, me.name)))), phone && peopleTab && /* @__PURE__ */ React.createElement("div", { style: { flexShrink: 0, display: "flex", gap: 6, padding: "8px 12px", borderBottom: "1px solid var(--line)", background: "var(--panel)", overflowX: "auto" } }, nav.filter((n) => DK_PEOPLE_TABS.includes(n.id)).map((n) => /* @__PURE__ */ React.createElement("button", { key: n.id, onClick: () => setTab(n.id), style: {
|
|
5679
|
+
} }, /* @__PURE__ */ React.createElement(DkAvatar, { peer: { ...me, id: me.userId, agent: false }, size: 36, radius: 9 }))), /* @__PURE__ */ React.createElement("div", { style: { flex: 1, minWidth: 0, minHeight: 0, display: "flex", flexDirection: "column" } }, !inConversation && /* @__PURE__ */ React.createElement(DkBrowserNotice, { lang: t.lang }), !inConversation && /* @__PURE__ */ React.createElement("div", { style: { height: 46, boxSizing: "content-box", paddingTop: phone ? "env(safe-area-inset-top, 0px)" : 0, flexShrink: 0, borderBottom: "1px solid var(--line)", background: "var(--panel)", display: "flex", alignItems: "center", gap: phone ? 8 : 12, paddingLeft: phone ? 12 : 16, paddingRight: phone ? 12 : 16 } }, /* @__PURE__ */ React.createElement(Brand, { T, style: { gap: 12, flexShrink: 0 } }, /* @__PURE__ */ React.createElement("svg", { width: 20, height: 20, viewBox: "0 0 24 24", fill: "none", stroke: "var(--accent)", strokeWidth: 2.2, strokeLinecap: "round", strokeLinejoin: "round", style: { display: "block", flexShrink: 0 } }, /* @__PURE__ */ React.createElement("path", { d: "m4.5 17 6-6-6-6" }), /* @__PURE__ */ React.createElement("path", { d: "M12 18.5h7.5" })), /* @__PURE__ */ React.createElement("span", { style: { fontFamily: "var(--mono)", fontSize: 14, fontWeight: 700, letterSpacing: -0.3, color: "var(--text)" } }, "beagle")), /* @__PURE__ */ React.createElement("span", { style: { fontFamily: "var(--mono)", fontSize: 12, color: "var(--faint)", whiteSpace: "nowrap" } }, "\xB7 ", (nav.find((n) => n.id === tab) || { label: T.profile }).label.toLowerCase()), /* @__PURE__ */ React.createElement("div", { style: { flex: 1 } }), phone ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(StatusDot, { online: me.online }), shareBtn, /* @__PURE__ */ React.createElement("button", { onClick: () => setTab("profile"), title: T.profile, style: { padding: 0, border: "none", background: "transparent", cursor: "pointer", display: "flex" } }, /* @__PURE__ */ React.createElement(DkAvatar, { peer: { ...me, id: me.userId, agent: false }, size: 28, radius: 7, dot: false }))) : /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Tag, { tone: "accent" }, me.channel, " \xB7 lan ", me.lanVer), /* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "center", gap: 7, padding: "0 4px" } }, /* @__PURE__ */ React.createElement(StatusDot, { online: me.online }), /* @__PURE__ */ React.createElement(Mono, { size: 12.5, copy: me.ip }, me.ip)), /* @__PURE__ */ React.createElement("span", { style: { width: 1, height: 22, background: "var(--line)" } }), shareBtn, /* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "center", gap: 8 } }, /* @__PURE__ */ React.createElement(DkAvatar, { peer: { ...me, id: me.userId, agent: false }, size: 26, radius: 7 }), /* @__PURE__ */ React.createElement("span", { style: { fontFamily: "var(--mono)", fontSize: 12.5, fontWeight: 600, color: "var(--text)" } }, me.name)))), phone && peopleTab && /* @__PURE__ */ React.createElement("div", { style: { flexShrink: 0, display: "flex", gap: 6, padding: "8px 12px", borderBottom: "1px solid var(--line)", background: "var(--panel)", overflowX: "auto" } }, nav.filter((n) => DK_PEOPLE_TABS.includes(n.id)).map((n) => /* @__PURE__ */ React.createElement("button", { key: n.id, onClick: () => setTab(n.id), style: {
|
|
5652
5680
|
display: "inline-flex",
|
|
5653
5681
|
alignItems: "center",
|
|
5654
5682
|
gap: 6,
|
package/dist/server.js
CHANGED
|
@@ -382,14 +382,22 @@ function verLt(a, b) {
|
|
|
382
382
|
/** Run `npm i -g <pkg>@latest`. npm is found on PATH, else via npm-cli.js
|
|
383
383
|
* next to the running node (covers pm2/cron environments whose PATH lacks
|
|
384
384
|
* the nvm shims). */
|
|
385
|
-
|
|
385
|
+
/** `nodePath` pins the install to one node's npm. The daemon can run on a
|
|
386
|
+
* different node than this app (nvm: launchd starts v24.2.0 while the shell's
|
|
387
|
+
* npm is v24.3.0), and a global install lands in the prefix of whichever npm
|
|
388
|
+
* ran it — the wrong one leaves the daemon on the old code with no error. */
|
|
389
|
+
async function npmGlobalInstall(pkg, nodePath) {
|
|
386
390
|
const { spawn } = await import("node:child_process");
|
|
387
391
|
const args = ["i", "-g", `${pkg}@latest`];
|
|
388
|
-
const
|
|
389
|
-
const
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
392
|
+
const cliFor = (node) => join(dirname(node), "..", "lib", "node_modules", "npm", "bin", "npm-cli.js");
|
|
393
|
+
const npmCli = cliFor(process.execPath);
|
|
394
|
+
const pinned = nodePath && existsSync(nodePath) && existsSync(cliFor(nodePath)) ? cliFor(nodePath) : "";
|
|
395
|
+
const attempts = pinned
|
|
396
|
+
? [{ cmd: nodePath, args: [pinned, ...args] }]
|
|
397
|
+
: [
|
|
398
|
+
{ cmd: "npm", args },
|
|
399
|
+
...(existsSync(npmCli) ? [{ cmd: process.execPath, args: [npmCli, ...args] }] : []),
|
|
400
|
+
];
|
|
393
401
|
for (const a of attempts) {
|
|
394
402
|
const r = await new Promise((resolveRun) => {
|
|
395
403
|
const ch = spawn(a.cmd, a.args, { shell: process.platform === "win32" });
|
|
@@ -522,6 +530,17 @@ async function npmQuery(args) {
|
|
|
522
530
|
* every ~10 s. Either way the proof is a different pid that accepts a
|
|
523
531
|
* connection. Without a data dir there is nothing to watch, so the old
|
|
524
532
|
* answer stands. */
|
|
533
|
+
/** The node binary the running daemon was started with, from its pid's
|
|
534
|
+
* command line (`/…/bin/node /…/bin/agentnet up …`). Empty when unknown. */
|
|
535
|
+
async function daemonNodePath(dataDir) {
|
|
536
|
+
const pid = dataDir ? readDaemonPid(dataDir) : "";
|
|
537
|
+
if (!/^\d+$/.test(pid) || process.platform === "win32")
|
|
538
|
+
return "";
|
|
539
|
+
const { execFile } = await import("node:child_process");
|
|
540
|
+
const cmd = await new Promise((res) => execFile("ps", ["-o", "command=", "-p", pid], { timeout: 5000 }, (err, out) => res(err ? "" : String(out).trim())));
|
|
541
|
+
const first = cmd.split(/\s+/)[0] ?? "";
|
|
542
|
+
return /(^|\/)node(\.exe)?$/.test(first) && existsSync(first) ? first : "";
|
|
543
|
+
}
|
|
525
544
|
async function agentnetRestart(dataDir) {
|
|
526
545
|
const pidBefore = dataDir ? readDaemonPid(dataDir) : "";
|
|
527
546
|
const r = await requestAgentnetRestart();
|
|
@@ -1857,7 +1876,7 @@ export function startBeagleServer(opts) {
|
|
|
1857
1876
|
// lan (the agentnet daemon) updates independently of beagle's own
|
|
1858
1877
|
// install mode: global reinstall, then ask the daemon to re-exec.
|
|
1859
1878
|
if (body.pkg === "lan") {
|
|
1860
|
-
const inst = await npmGlobalInstall("@decentnetwork/lan");
|
|
1879
|
+
const inst = await npmGlobalInstall("@decentnetwork/lan", await daemonNodePath(opts.lanHost?.dataDir));
|
|
1861
1880
|
if (!inst.ok) {
|
|
1862
1881
|
sendJson(res, 502, inst);
|
|
1863
1882
|
return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@decentnetwork/beagle",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.103",
|
|
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",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"yargs": "^17.7.2"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@decentnetwork/beagle-ui": "^0.2.
|
|
38
|
+
"@decentnetwork/beagle-ui": "^0.2.18",
|
|
39
39
|
"@types/js-yaml": "^4.0.9",
|
|
40
40
|
"@types/node": "^20.11.0",
|
|
41
41
|
"@types/yargs": "^17.0.32",
|