@decentnetwork/lan 0.1.301 → 0.1.302

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.
@@ -945,11 +945,17 @@ export class DaemonServer {
945
945
  // (INBOX 2026-08-22 #2). Detect systemd by the env it stamps on
946
946
  // every unit (sudo's env_reset strips these, so an interactive
947
947
  // `sudo agentnet up` still takes the spawn path).
948
- const underSystemd = process.platform === "linux" &&
949
- Boolean(process.env.INVOCATION_ID || process.env.JOURNAL_STREAM);
948
+ //
949
+ // launchd is the same trap on macOS: the replacement is not
950
+ // launchd's job, so the KeepAlive job keeps starting its own copy,
951
+ // which refuses the identity every ~10 s, forever (mac-dev
952
+ // 2026-09-14, 20934 runs). See supervisor.ts.
953
+ const { restartSupervisor } = await import("./supervisor.js");
954
+ const supervisor = restartSupervisor();
955
+ const underSupervisor = supervisor !== null;
950
956
  setExitReason("selfRestart via IPC");
951
- this.logger.info(underSystemd
952
- ? "Self-restart requested via IPC — running under systemd, will exit non-zero for the supervisor to relaunch"
957
+ this.logger.info(underSupervisor
958
+ ? `Self-restart requested via IPC — running under ${supervisor}, will exit non-zero for the supervisor to relaunch`
953
959
  : `Self-restart requested via IPC — relaunching ${node} ${argv.join(" ")}`);
954
960
  // Schedule shutdown for after the IPC response goes out. The
955
961
  // 50ms timeout lets the response leave before cleanup closes IPC.
@@ -980,7 +986,7 @@ export class DaemonServer {
980
986
  child.unref();
981
987
  }
982
988
  }
983
- else if (!underSystemd) {
989
+ else if (!underSupervisor) {
984
990
  // sh -c so we can shell-quote argv safely and use sleep.
985
991
  // Node's detached flag reparents the relauncher to PID 1.
986
992
  // At this point stop() has released IPC, TUN and the pidfile;
@@ -1000,7 +1006,7 @@ export class DaemonServer {
1000
1006
  // Non-zero under systemd so Restart=on-failure (and =always)
1001
1007
  // relaunches us; zero elsewhere — the detached child is the
1002
1008
  // replacement and a supervisor must not also start one.
1003
- setTimeout(() => process.exit(underSystemd ? 70 : 0), 200);
1009
+ setTimeout(() => process.exit(underSupervisor ? 70 : 0), 200);
1004
1010
  })();
1005
1011
  }, 50);
1006
1012
  return { scheduledMs: 1500, argv: [node, ...argv] };
@@ -0,0 +1,4 @@
1
+ export type RestartSupervisor = "systemd" | "launchd" | null;
2
+ /** The launchd label `agentnet service install` writes. */
3
+ export declare const LAUNCHD_LABEL = "com.decentlan.agentnet";
4
+ export declare function restartSupervisor(platform?: NodeJS.Platform, env?: NodeJS.ProcessEnv): RestartSupervisor;
@@ -0,0 +1,25 @@
1
+ // supervisor.ts — who brings this daemon back after it exits?
2
+ //
3
+ // selfRestart re-execs a detached replacement everywhere except under a
4
+ // supervisor. Under systemd that replacement dies with the cgroup (INBOX
5
+ // 2026-08-22 #2). Under launchd it survives but is not launchd's job: it is
6
+ // reparented to pid 1, and the KeepAlive job keeps starting its own copy,
7
+ // which refuses the identity ("Another decentlan daemon is already running")
8
+ // every ~10 s, forever — 20934 runs on mac-dev by 2026-09-14, with
9
+ // /var/log/agentnet.log growing without bound. Under either supervisor the
10
+ // right restart is to exit and let the supervisor start the new code.
11
+ /** The launchd label `agentnet service install` writes. */
12
+ export const LAUNCHD_LABEL = "com.decentlan.agentnet";
13
+ export function restartSupervisor(platform = process.platform, env = process.env) {
14
+ // systemd stamps these on every unit; sudo's env_reset strips them, so an
15
+ // interactive `sudo agentnet up` still takes the spawn path.
16
+ if (platform === "linux" && (env.INVOCATION_ID || env.JOURNAL_STREAM))
17
+ return "systemd";
18
+ // launchd sets XPC_SERVICE_NAME to the job's label. A shell has "0" or its
19
+ // terminal app's name there, so only the installed job matches. A
20
+ // replacement an older build re-exec'd inherited it too — and exiting is
21
+ // right for that orphan as well: launchd's job takes the identity back.
22
+ if (platform === "darwin" && env.XPC_SERVICE_NAME === LAUNCHD_LABEL)
23
+ return "launchd";
24
+ return null;
25
+ }
@@ -1,4 +1,4 @@
1
- window.__DK_UI_VERSION="0.1.301";
1
+ window.__DK_UI_VERSION="0.1.302";
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"/>',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decentnetwork/lan",
3
- "version": "0.1.301",
3
+ "version": "0.1.302",
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",