@node9/proxy 2.2.1 → 2.3.0
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 +147 -20
- package/dist/cli.mjs +147 -20
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -21561,6 +21561,75 @@ function uninstallSystemd() {
|
|
|
21561
21561
|
function isSystemdInstalled() {
|
|
21562
21562
|
return import_fs43.default.existsSync(SYSTEMD_UNIT);
|
|
21563
21563
|
}
|
|
21564
|
+
function windowsLauncherVbs(nodePath, scriptPath) {
|
|
21565
|
+
for (const p of [nodePath, scriptPath]) {
|
|
21566
|
+
if (p.includes('"')) throw new Error(`Illegal quote in path: ${p}`);
|
|
21567
|
+
}
|
|
21568
|
+
return [
|
|
21569
|
+
"' Auto-generated by node9 \u2014 starts the approval daemon with no console window.",
|
|
21570
|
+
"' Recreated on every `node9 daemon install`; safe to delete (uninstall does).",
|
|
21571
|
+
'Set sh = CreateObject("Wscript.Shell")',
|
|
21572
|
+
'sh.Environment("PROCESS")("NODE9_AUTO_STARTED") = "1"',
|
|
21573
|
+
`sh.Run """${nodePath}"" ""${scriptPath}"" daemon", 0, False`,
|
|
21574
|
+
""
|
|
21575
|
+
].join("\r\n");
|
|
21576
|
+
}
|
|
21577
|
+
function schtasksCreateArgs(launcherPath) {
|
|
21578
|
+
return [
|
|
21579
|
+
"/Create",
|
|
21580
|
+
"/TN",
|
|
21581
|
+
SCHTASKS_TASK,
|
|
21582
|
+
"/TR",
|
|
21583
|
+
`wscript.exe //B "${launcherPath}"`,
|
|
21584
|
+
"/SC",
|
|
21585
|
+
"ONLOGON",
|
|
21586
|
+
"/F"
|
|
21587
|
+
];
|
|
21588
|
+
}
|
|
21589
|
+
function installSchtasks(binaryPath) {
|
|
21590
|
+
const launcher = WIN_LAUNCHER();
|
|
21591
|
+
const dir = import_path42.default.dirname(launcher);
|
|
21592
|
+
if (!import_fs43.default.existsSync(dir)) import_fs43.default.mkdirSync(dir, { recursive: true });
|
|
21593
|
+
import_fs43.default.writeFileSync(launcher, windowsLauncherVbs(process.execPath, binaryPath), "utf-8");
|
|
21594
|
+
const create = (0, import_child_process3.spawnSync)("schtasks", schtasksCreateArgs(launcher), {
|
|
21595
|
+
encoding: "utf8",
|
|
21596
|
+
timeout: 1e4
|
|
21597
|
+
});
|
|
21598
|
+
if (create.status !== 0) {
|
|
21599
|
+
throw new Error(
|
|
21600
|
+
`schtasks /Create failed: ${create.stderr || create.stdout || "unknown error"}`
|
|
21601
|
+
);
|
|
21602
|
+
}
|
|
21603
|
+
(0, import_child_process3.spawnSync)("schtasks", ["/Run", "/TN", SCHTASKS_TASK], { encoding: "utf8", timeout: 1e4 });
|
|
21604
|
+
}
|
|
21605
|
+
function uninstallSchtasks() {
|
|
21606
|
+
(0, import_child_process3.spawnSync)("schtasks", ["/Delete", "/TN", SCHTASKS_TASK, "/F"], {
|
|
21607
|
+
encoding: "utf8",
|
|
21608
|
+
timeout: 1e4
|
|
21609
|
+
});
|
|
21610
|
+
const launcher = WIN_LAUNCHER();
|
|
21611
|
+
if (import_fs43.default.existsSync(launcher)) {
|
|
21612
|
+
try {
|
|
21613
|
+
import_fs43.default.unlinkSync(launcher);
|
|
21614
|
+
} catch {
|
|
21615
|
+
}
|
|
21616
|
+
}
|
|
21617
|
+
}
|
|
21618
|
+
function isSchtasksInstalled() {
|
|
21619
|
+
const r = (0, import_child_process3.spawnSync)("schtasks", ["/Query", "/TN", SCHTASKS_TASK], {
|
|
21620
|
+
encoding: "utf8",
|
|
21621
|
+
timeout: 5e3
|
|
21622
|
+
});
|
|
21623
|
+
return r.status === 0;
|
|
21624
|
+
}
|
|
21625
|
+
function isSchtasksEnabled() {
|
|
21626
|
+
const r = (0, import_child_process3.spawnSync)("schtasks", ["/Query", "/TN", SCHTASKS_TASK, "/XML"], {
|
|
21627
|
+
encoding: "utf8",
|
|
21628
|
+
timeout: 5e3
|
|
21629
|
+
});
|
|
21630
|
+
if (r.status !== 0) return false;
|
|
21631
|
+
return !/<Enabled>\s*false\s*<\/Enabled>/i.test(r.stdout ?? "");
|
|
21632
|
+
}
|
|
21564
21633
|
function stopRunningDaemon() {
|
|
21565
21634
|
const pidFile = import_path42.default.join(import_os39.default.homedir(), ".node9", "daemon.pid");
|
|
21566
21635
|
if (!import_fs43.default.existsSync(pidFile)) return;
|
|
@@ -21572,15 +21641,15 @@ function stopRunningDaemon() {
|
|
|
21572
21641
|
try {
|
|
21573
21642
|
process.kill(pid, "SIGTERM");
|
|
21574
21643
|
const deadline = Date.now() + 3e3;
|
|
21575
|
-
const
|
|
21576
|
-
|
|
21577
|
-
|
|
21578
|
-
|
|
21579
|
-
|
|
21644
|
+
const sleeper = new Int32Array(new SharedArrayBuffer(4));
|
|
21645
|
+
while (Date.now() < deadline) {
|
|
21646
|
+
try {
|
|
21647
|
+
process.kill(pid, 0);
|
|
21648
|
+
} catch {
|
|
21649
|
+
break;
|
|
21580
21650
|
}
|
|
21581
|
-
|
|
21582
|
-
|
|
21583
|
-
void deadline;
|
|
21651
|
+
Atomics.wait(sleeper, 0, 0, 100);
|
|
21652
|
+
}
|
|
21584
21653
|
} catch {
|
|
21585
21654
|
}
|
|
21586
21655
|
}
|
|
@@ -21618,6 +21687,11 @@ function installDaemonService() {
|
|
|
21618
21687
|
installSystemd(binary);
|
|
21619
21688
|
return { ok: true, platform: "systemd", alreadyInstalled };
|
|
21620
21689
|
}
|
|
21690
|
+
if (process.platform === "win32") {
|
|
21691
|
+
const alreadyInstalled = isSchtasksInstalled();
|
|
21692
|
+
installSchtasks(binary);
|
|
21693
|
+
return { ok: true, platform: "schtasks", alreadyInstalled };
|
|
21694
|
+
}
|
|
21621
21695
|
return {
|
|
21622
21696
|
ok: false,
|
|
21623
21697
|
reason: `Automatic service install is not supported on ${process.platform}. Start the daemon manually with: node9 daemon start`
|
|
@@ -21639,6 +21713,10 @@ function uninstallDaemonService() {
|
|
|
21639
21713
|
uninstallSystemd();
|
|
21640
21714
|
return { ok: true, platform: "systemd", alreadyInstalled: false };
|
|
21641
21715
|
}
|
|
21716
|
+
if (process.platform === "win32") {
|
|
21717
|
+
uninstallSchtasks();
|
|
21718
|
+
return { ok: true, platform: "schtasks", alreadyInstalled: false };
|
|
21719
|
+
}
|
|
21642
21720
|
return {
|
|
21643
21721
|
ok: false,
|
|
21644
21722
|
reason: `Service management not supported on ${process.platform}.`
|
|
@@ -21653,11 +21731,14 @@ function uninstallDaemonService() {
|
|
|
21653
21731
|
function isDaemonServiceInstalled() {
|
|
21654
21732
|
if (process.platform === "darwin") return isLaunchdInstalled();
|
|
21655
21733
|
if (process.platform === "linux") return isSystemdInstalled();
|
|
21734
|
+
if (process.platform === "win32") return isSchtasksInstalled();
|
|
21656
21735
|
return false;
|
|
21657
21736
|
}
|
|
21658
21737
|
function autostartRepairDecision(opts) {
|
|
21659
21738
|
if (!opts.autoStartDaemon) return "skip";
|
|
21660
|
-
if (process.platform !== "linux" && process.platform !== "darwin"
|
|
21739
|
+
if (process.platform !== "linux" && process.platform !== "darwin" && process.platform !== "win32") {
|
|
21740
|
+
return "unsupported";
|
|
21741
|
+
}
|
|
21661
21742
|
if (!opts.installed) return "skip";
|
|
21662
21743
|
return opts.enabled ? "ok" : "repair";
|
|
21663
21744
|
}
|
|
@@ -21670,6 +21751,13 @@ function enableDaemonServiceQuiet() {
|
|
|
21670
21751
|
});
|
|
21671
21752
|
return r.status === 0;
|
|
21672
21753
|
}
|
|
21754
|
+
if (process.platform === "win32") {
|
|
21755
|
+
const r = (0, import_child_process3.spawnSync)("schtasks", ["/Change", "/TN", SCHTASKS_TASK, "/ENABLE"], {
|
|
21756
|
+
encoding: "utf8",
|
|
21757
|
+
timeout: 5e3
|
|
21758
|
+
});
|
|
21759
|
+
return r.status === 0;
|
|
21760
|
+
}
|
|
21673
21761
|
return process.platform === "darwin";
|
|
21674
21762
|
} catch {
|
|
21675
21763
|
return false;
|
|
@@ -21684,10 +21772,13 @@ function ensureAutostartHealthy(autoStartDaemon) {
|
|
|
21684
21772
|
if (decision === "repair") return enableDaemonServiceQuiet() ? "repaired" : "skipped";
|
|
21685
21773
|
return decision === "ok" ? "ok" : decision === "unsupported" ? "unsupported" : "skipped";
|
|
21686
21774
|
}
|
|
21775
|
+
function autostartInstallHint() {
|
|
21776
|
+
return process.platform === "linux" ? "Run: systemctl --user enable --now node9-daemon (or: node9 daemon install)" : "Run: node9 daemon install";
|
|
21777
|
+
}
|
|
21687
21778
|
function autostartAdvice(opts) {
|
|
21688
|
-
const installable = process.platform === "linux" || process.platform === "darwin";
|
|
21779
|
+
const installable = process.platform === "linux" || process.platform === "darwin" || process.platform === "win32";
|
|
21689
21780
|
if (!opts.cloudEnabled || !installable) return null;
|
|
21690
|
-
const installHint =
|
|
21781
|
+
const installHint = autostartInstallHint();
|
|
21691
21782
|
if (opts.installed && !opts.enabled) {
|
|
21692
21783
|
return {
|
|
21693
21784
|
level: "warn",
|
|
@@ -21720,11 +21811,14 @@ function isDaemonServiceEnabled() {
|
|
|
21720
21811
|
});
|
|
21721
21812
|
return r.status === 0;
|
|
21722
21813
|
}
|
|
21814
|
+
if (process.platform === "win32") {
|
|
21815
|
+
return isSchtasksEnabled();
|
|
21816
|
+
}
|
|
21723
21817
|
} catch {
|
|
21724
21818
|
}
|
|
21725
21819
|
return false;
|
|
21726
21820
|
}
|
|
21727
|
-
var import_fs43, import_path42, import_os39, import_child_process3, LAUNCHD_LABEL, LAUNCHD_PLIST, SYSTEMD_UNIT_DIR, SYSTEMD_UNIT;
|
|
21821
|
+
var import_fs43, import_path42, import_os39, import_child_process3, LAUNCHD_LABEL, LAUNCHD_PLIST, SYSTEMD_UNIT_DIR, SYSTEMD_UNIT, SCHTASKS_TASK, WIN_LAUNCHER;
|
|
21728
21822
|
var init_service = __esm({
|
|
21729
21823
|
"src/daemon/service.ts"() {
|
|
21730
21824
|
"use strict";
|
|
@@ -21736,6 +21830,8 @@ var init_service = __esm({
|
|
|
21736
21830
|
LAUNCHD_PLIST = import_path42.default.join(import_os39.default.homedir(), "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`);
|
|
21737
21831
|
SYSTEMD_UNIT_DIR = import_path42.default.join(import_os39.default.homedir(), ".config", "systemd", "user");
|
|
21738
21832
|
SYSTEMD_UNIT = import_path42.default.join(SYSTEMD_UNIT_DIR, "node9-daemon.service");
|
|
21833
|
+
SCHTASKS_TASK = "Node9Daemon";
|
|
21834
|
+
WIN_LAUNCHER = () => import_path42.default.join(import_os39.default.homedir(), ".node9", "daemon-launcher.vbs");
|
|
21739
21835
|
}
|
|
21740
21836
|
});
|
|
21741
21837
|
|
|
@@ -48029,6 +48125,20 @@ function buildReviewMessage(blockedByLabel, ruleDescription, reason) {
|
|
|
48029
48125
|
return `Node9 flagged this for your review: ${why}. Approve to proceed, or deny to cancel.`;
|
|
48030
48126
|
}
|
|
48031
48127
|
|
|
48128
|
+
// src/utils/platform-shell.ts
|
|
48129
|
+
function locatorCommand() {
|
|
48130
|
+
return process.platform === "win32" ? "where" : "which";
|
|
48131
|
+
}
|
|
48132
|
+
function shellInvocation(command) {
|
|
48133
|
+
if (process.platform === "win32") {
|
|
48134
|
+
return {
|
|
48135
|
+
file: process.env.ComSpec || "cmd.exe",
|
|
48136
|
+
args: ["/d", "/s", "/c", command]
|
|
48137
|
+
};
|
|
48138
|
+
}
|
|
48139
|
+
return { file: "/bin/bash", args: ["-c", command] };
|
|
48140
|
+
}
|
|
48141
|
+
|
|
48032
48142
|
// src/proxy/index.ts
|
|
48033
48143
|
function sanitize(value) {
|
|
48034
48144
|
return value.replace(/[\x00-\x1F\x7F]/g, "");
|
|
@@ -48040,14 +48150,16 @@ async function runProxy(targetCommand) {
|
|
|
48040
48150
|
let executable = cmd;
|
|
48041
48151
|
let useShell = false;
|
|
48042
48152
|
try {
|
|
48043
|
-
const { stdout } = await (0, import_execa.execa)(
|
|
48044
|
-
|
|
48153
|
+
const { stdout } = await (0, import_execa.execa)(locatorCommand(), [cmd]);
|
|
48154
|
+
const first = stdout.split(/\r?\n/)[0]?.trim();
|
|
48155
|
+
if (first) executable = first;
|
|
48045
48156
|
} catch {
|
|
48046
48157
|
useShell = true;
|
|
48047
48158
|
}
|
|
48048
48159
|
console.error(import_chalk8.default.green(`\u{1F680} Node9 Proxy Active: Monitoring [${targetCommand}]`));
|
|
48049
48160
|
const spawnEnv = { ...process.env, FORCE_COLOR: "1" };
|
|
48050
|
-
const
|
|
48161
|
+
const shell = shellInvocation(targetCommand);
|
|
48162
|
+
const child = useShell ? (0, import_child_process4.spawn)(shell.file, shell.args, {
|
|
48051
48163
|
stdio: ["pipe", "pipe", "inherit"],
|
|
48052
48164
|
shell: false,
|
|
48053
48165
|
env: spawnEnv
|
|
@@ -48111,6 +48223,17 @@ async function runProxy(targetCommand) {
|
|
|
48111
48223
|
child.stdin.write(line + "\n");
|
|
48112
48224
|
});
|
|
48113
48225
|
child.stdout.pipe(process.stdout);
|
|
48226
|
+
child.on("error", (err2) => {
|
|
48227
|
+
const what = useShell ? shell.file : executable;
|
|
48228
|
+
console.error(
|
|
48229
|
+
import_chalk8.default.red(
|
|
48230
|
+
err2.code === "ENOENT" ? `
|
|
48231
|
+
\u274C Node9 could not run "${targetCommand}": ${what} was not found on this machine.` : `
|
|
48232
|
+
\u274C Node9 could not run "${targetCommand}": ${err2.message}`
|
|
48233
|
+
)
|
|
48234
|
+
);
|
|
48235
|
+
process.exit(127);
|
|
48236
|
+
});
|
|
48114
48237
|
child.on("exit", (code) => process.exit(code || 0));
|
|
48115
48238
|
}
|
|
48116
48239
|
|
|
@@ -48256,7 +48379,7 @@ async function onboardMachine(apiKey, opts = {}) {
|
|
|
48256
48379
|
push.ok ? { name: "register", ok: true, detail: "machine visible in the dashboard" } : { name: "register", ok: false, detail: push.reason }
|
|
48257
48380
|
);
|
|
48258
48381
|
const healed = ensureAutostartHealthy(!!getConfig().settings.autoStartDaemon);
|
|
48259
|
-
const detail = healed === "repaired" ? "autostart re-enabled (survives reboot)" : isDaemonRunning() ? "running" : healed === "unsupported" ? "no background service on this platform: starts on agent activity" : "starts on agent activity";
|
|
48382
|
+
const detail = healed === "repaired" ? "autostart re-enabled (survives reboot)" : isDaemonRunning() ? "running" : healed === "unsupported" ? "no background service on this platform: starts on agent activity" : "starts on agent activity (make it survive reboots: node9 daemon install)";
|
|
48260
48383
|
steps.push({ name: "daemon", ok: true, detail });
|
|
48261
48384
|
}
|
|
48262
48385
|
const required = ["credentials", "policy-sync", "register"];
|
|
@@ -50232,8 +50355,10 @@ function registerDoctorCommand(program2, version2) {
|
|
|
50232
50355
|
`));
|
|
50233
50356
|
section("Binary");
|
|
50234
50357
|
try {
|
|
50235
|
-
const
|
|
50236
|
-
|
|
50358
|
+
const found = (0, import_child_process8.execSync)(`${locatorCommand()} node9`, {
|
|
50359
|
+
encoding: "utf-8",
|
|
50360
|
+
timeout: 3e3
|
|
50361
|
+
}).split(/\r?\n/)[0].trim();
|
|
50237
50362
|
pass(`node9 found at ${found}`);
|
|
50238
50363
|
} catch {
|
|
50239
50364
|
warn("node9 not found in $PATH \u2014 hooks may not find it", "Run: npm install -g node9-ai");
|
|
@@ -50360,7 +50485,9 @@ function registerDoctorCommand(program2, version2) {
|
|
|
50360
50485
|
const fails = health.consecutiveFailures > 0 ? ` (${health.consecutiveFailures} consecutive failure${health.consecutiveFailures === 1 ? "" : "s"}${health.lastError ? `: ${health.lastError}` : ""})` : "";
|
|
50361
50486
|
warn(
|
|
50362
50487
|
`Cloud policy is STALE \u2014 ${when}${fails}. The cached policy is still enforced, but changes from the dashboard are not reaching this machine.`,
|
|
50363
|
-
|
|
50488
|
+
// Platform-aware: this hint hardcoded systemctl and told a Windows
|
|
50489
|
+
// founder to run a Linux command (QA 2026-08-28).
|
|
50490
|
+
`Run: node9 policy sync (then keep it fresh across reboots \u2014 ${autostartInstallHint()})`
|
|
50364
50491
|
);
|
|
50365
50492
|
} else if (health.lastCheckedAt) {
|
|
50366
50493
|
pass(`Cloud policy fresh \u2014 last synced ${agoLabel(health.lastCheckedAt)}`);
|
|
@@ -52102,7 +52229,7 @@ function registerInitCommand(program2) {
|
|
|
52102
52229
|
await setupAgent(agent);
|
|
52103
52230
|
console.log("");
|
|
52104
52231
|
}
|
|
52105
|
-
if ((process.platform === "darwin" || process.platform === "linux") && process.stdout.isTTY) {
|
|
52232
|
+
if ((process.platform === "darwin" || process.platform === "linux" || process.platform === "win32") && process.stdout.isTTY) {
|
|
52106
52233
|
const alreadyInstalled = isDaemonServiceInstalled();
|
|
52107
52234
|
if (!alreadyInstalled) {
|
|
52108
52235
|
const { confirm: confirm4 } = await import("@inquirer/prompts");
|
package/dist/cli.mjs
CHANGED
|
@@ -21558,6 +21558,75 @@ function uninstallSystemd() {
|
|
|
21558
21558
|
function isSystemdInstalled() {
|
|
21559
21559
|
return fs44.existsSync(SYSTEMD_UNIT);
|
|
21560
21560
|
}
|
|
21561
|
+
function windowsLauncherVbs(nodePath, scriptPath) {
|
|
21562
|
+
for (const p of [nodePath, scriptPath]) {
|
|
21563
|
+
if (p.includes('"')) throw new Error(`Illegal quote in path: ${p}`);
|
|
21564
|
+
}
|
|
21565
|
+
return [
|
|
21566
|
+
"' Auto-generated by node9 \u2014 starts the approval daemon with no console window.",
|
|
21567
|
+
"' Recreated on every `node9 daemon install`; safe to delete (uninstall does).",
|
|
21568
|
+
'Set sh = CreateObject("Wscript.Shell")',
|
|
21569
|
+
'sh.Environment("PROCESS")("NODE9_AUTO_STARTED") = "1"',
|
|
21570
|
+
`sh.Run """${nodePath}"" ""${scriptPath}"" daemon", 0, False`,
|
|
21571
|
+
""
|
|
21572
|
+
].join("\r\n");
|
|
21573
|
+
}
|
|
21574
|
+
function schtasksCreateArgs(launcherPath) {
|
|
21575
|
+
return [
|
|
21576
|
+
"/Create",
|
|
21577
|
+
"/TN",
|
|
21578
|
+
SCHTASKS_TASK,
|
|
21579
|
+
"/TR",
|
|
21580
|
+
`wscript.exe //B "${launcherPath}"`,
|
|
21581
|
+
"/SC",
|
|
21582
|
+
"ONLOGON",
|
|
21583
|
+
"/F"
|
|
21584
|
+
];
|
|
21585
|
+
}
|
|
21586
|
+
function installSchtasks(binaryPath) {
|
|
21587
|
+
const launcher = WIN_LAUNCHER();
|
|
21588
|
+
const dir = path43.dirname(launcher);
|
|
21589
|
+
if (!fs44.existsSync(dir)) fs44.mkdirSync(dir, { recursive: true });
|
|
21590
|
+
fs44.writeFileSync(launcher, windowsLauncherVbs(process.execPath, binaryPath), "utf-8");
|
|
21591
|
+
const create = spawnSync2("schtasks", schtasksCreateArgs(launcher), {
|
|
21592
|
+
encoding: "utf8",
|
|
21593
|
+
timeout: 1e4
|
|
21594
|
+
});
|
|
21595
|
+
if (create.status !== 0) {
|
|
21596
|
+
throw new Error(
|
|
21597
|
+
`schtasks /Create failed: ${create.stderr || create.stdout || "unknown error"}`
|
|
21598
|
+
);
|
|
21599
|
+
}
|
|
21600
|
+
spawnSync2("schtasks", ["/Run", "/TN", SCHTASKS_TASK], { encoding: "utf8", timeout: 1e4 });
|
|
21601
|
+
}
|
|
21602
|
+
function uninstallSchtasks() {
|
|
21603
|
+
spawnSync2("schtasks", ["/Delete", "/TN", SCHTASKS_TASK, "/F"], {
|
|
21604
|
+
encoding: "utf8",
|
|
21605
|
+
timeout: 1e4
|
|
21606
|
+
});
|
|
21607
|
+
const launcher = WIN_LAUNCHER();
|
|
21608
|
+
if (fs44.existsSync(launcher)) {
|
|
21609
|
+
try {
|
|
21610
|
+
fs44.unlinkSync(launcher);
|
|
21611
|
+
} catch {
|
|
21612
|
+
}
|
|
21613
|
+
}
|
|
21614
|
+
}
|
|
21615
|
+
function isSchtasksInstalled() {
|
|
21616
|
+
const r = spawnSync2("schtasks", ["/Query", "/TN", SCHTASKS_TASK], {
|
|
21617
|
+
encoding: "utf8",
|
|
21618
|
+
timeout: 5e3
|
|
21619
|
+
});
|
|
21620
|
+
return r.status === 0;
|
|
21621
|
+
}
|
|
21622
|
+
function isSchtasksEnabled() {
|
|
21623
|
+
const r = spawnSync2("schtasks", ["/Query", "/TN", SCHTASKS_TASK, "/XML"], {
|
|
21624
|
+
encoding: "utf8",
|
|
21625
|
+
timeout: 5e3
|
|
21626
|
+
});
|
|
21627
|
+
if (r.status !== 0) return false;
|
|
21628
|
+
return !/<Enabled>\s*false\s*<\/Enabled>/i.test(r.stdout ?? "");
|
|
21629
|
+
}
|
|
21561
21630
|
function stopRunningDaemon() {
|
|
21562
21631
|
const pidFile = path43.join(os40.homedir(), ".node9", "daemon.pid");
|
|
21563
21632
|
if (!fs44.existsSync(pidFile)) return;
|
|
@@ -21569,15 +21638,15 @@ function stopRunningDaemon() {
|
|
|
21569
21638
|
try {
|
|
21570
21639
|
process.kill(pid, "SIGTERM");
|
|
21571
21640
|
const deadline = Date.now() + 3e3;
|
|
21572
|
-
const
|
|
21573
|
-
|
|
21574
|
-
|
|
21575
|
-
|
|
21576
|
-
|
|
21641
|
+
const sleeper = new Int32Array(new SharedArrayBuffer(4));
|
|
21642
|
+
while (Date.now() < deadline) {
|
|
21643
|
+
try {
|
|
21644
|
+
process.kill(pid, 0);
|
|
21645
|
+
} catch {
|
|
21646
|
+
break;
|
|
21577
21647
|
}
|
|
21578
|
-
|
|
21579
|
-
|
|
21580
|
-
void deadline;
|
|
21648
|
+
Atomics.wait(sleeper, 0, 0, 100);
|
|
21649
|
+
}
|
|
21581
21650
|
} catch {
|
|
21582
21651
|
}
|
|
21583
21652
|
}
|
|
@@ -21615,6 +21684,11 @@ function installDaemonService() {
|
|
|
21615
21684
|
installSystemd(binary);
|
|
21616
21685
|
return { ok: true, platform: "systemd", alreadyInstalled };
|
|
21617
21686
|
}
|
|
21687
|
+
if (process.platform === "win32") {
|
|
21688
|
+
const alreadyInstalled = isSchtasksInstalled();
|
|
21689
|
+
installSchtasks(binary);
|
|
21690
|
+
return { ok: true, platform: "schtasks", alreadyInstalled };
|
|
21691
|
+
}
|
|
21618
21692
|
return {
|
|
21619
21693
|
ok: false,
|
|
21620
21694
|
reason: `Automatic service install is not supported on ${process.platform}. Start the daemon manually with: node9 daemon start`
|
|
@@ -21636,6 +21710,10 @@ function uninstallDaemonService() {
|
|
|
21636
21710
|
uninstallSystemd();
|
|
21637
21711
|
return { ok: true, platform: "systemd", alreadyInstalled: false };
|
|
21638
21712
|
}
|
|
21713
|
+
if (process.platform === "win32") {
|
|
21714
|
+
uninstallSchtasks();
|
|
21715
|
+
return { ok: true, platform: "schtasks", alreadyInstalled: false };
|
|
21716
|
+
}
|
|
21639
21717
|
return {
|
|
21640
21718
|
ok: false,
|
|
21641
21719
|
reason: `Service management not supported on ${process.platform}.`
|
|
@@ -21650,11 +21728,14 @@ function uninstallDaemonService() {
|
|
|
21650
21728
|
function isDaemonServiceInstalled() {
|
|
21651
21729
|
if (process.platform === "darwin") return isLaunchdInstalled();
|
|
21652
21730
|
if (process.platform === "linux") return isSystemdInstalled();
|
|
21731
|
+
if (process.platform === "win32") return isSchtasksInstalled();
|
|
21653
21732
|
return false;
|
|
21654
21733
|
}
|
|
21655
21734
|
function autostartRepairDecision(opts) {
|
|
21656
21735
|
if (!opts.autoStartDaemon) return "skip";
|
|
21657
|
-
if (process.platform !== "linux" && process.platform !== "darwin"
|
|
21736
|
+
if (process.platform !== "linux" && process.platform !== "darwin" && process.platform !== "win32") {
|
|
21737
|
+
return "unsupported";
|
|
21738
|
+
}
|
|
21658
21739
|
if (!opts.installed) return "skip";
|
|
21659
21740
|
return opts.enabled ? "ok" : "repair";
|
|
21660
21741
|
}
|
|
@@ -21667,6 +21748,13 @@ function enableDaemonServiceQuiet() {
|
|
|
21667
21748
|
});
|
|
21668
21749
|
return r.status === 0;
|
|
21669
21750
|
}
|
|
21751
|
+
if (process.platform === "win32") {
|
|
21752
|
+
const r = spawnSync2("schtasks", ["/Change", "/TN", SCHTASKS_TASK, "/ENABLE"], {
|
|
21753
|
+
encoding: "utf8",
|
|
21754
|
+
timeout: 5e3
|
|
21755
|
+
});
|
|
21756
|
+
return r.status === 0;
|
|
21757
|
+
}
|
|
21670
21758
|
return process.platform === "darwin";
|
|
21671
21759
|
} catch {
|
|
21672
21760
|
return false;
|
|
@@ -21681,10 +21769,13 @@ function ensureAutostartHealthy(autoStartDaemon) {
|
|
|
21681
21769
|
if (decision === "repair") return enableDaemonServiceQuiet() ? "repaired" : "skipped";
|
|
21682
21770
|
return decision === "ok" ? "ok" : decision === "unsupported" ? "unsupported" : "skipped";
|
|
21683
21771
|
}
|
|
21772
|
+
function autostartInstallHint() {
|
|
21773
|
+
return process.platform === "linux" ? "Run: systemctl --user enable --now node9-daemon (or: node9 daemon install)" : "Run: node9 daemon install";
|
|
21774
|
+
}
|
|
21684
21775
|
function autostartAdvice(opts) {
|
|
21685
|
-
const installable = process.platform === "linux" || process.platform === "darwin";
|
|
21776
|
+
const installable = process.platform === "linux" || process.platform === "darwin" || process.platform === "win32";
|
|
21686
21777
|
if (!opts.cloudEnabled || !installable) return null;
|
|
21687
|
-
const installHint =
|
|
21778
|
+
const installHint = autostartInstallHint();
|
|
21688
21779
|
if (opts.installed && !opts.enabled) {
|
|
21689
21780
|
return {
|
|
21690
21781
|
level: "warn",
|
|
@@ -21717,11 +21808,14 @@ function isDaemonServiceEnabled() {
|
|
|
21717
21808
|
});
|
|
21718
21809
|
return r.status === 0;
|
|
21719
21810
|
}
|
|
21811
|
+
if (process.platform === "win32") {
|
|
21812
|
+
return isSchtasksEnabled();
|
|
21813
|
+
}
|
|
21720
21814
|
} catch {
|
|
21721
21815
|
}
|
|
21722
21816
|
return false;
|
|
21723
21817
|
}
|
|
21724
|
-
var LAUNCHD_LABEL, LAUNCHD_PLIST, SYSTEMD_UNIT_DIR, SYSTEMD_UNIT;
|
|
21818
|
+
var LAUNCHD_LABEL, LAUNCHD_PLIST, SYSTEMD_UNIT_DIR, SYSTEMD_UNIT, SCHTASKS_TASK, WIN_LAUNCHER;
|
|
21725
21819
|
var init_service = __esm({
|
|
21726
21820
|
"src/daemon/service.ts"() {
|
|
21727
21821
|
"use strict";
|
|
@@ -21729,6 +21823,8 @@ var init_service = __esm({
|
|
|
21729
21823
|
LAUNCHD_PLIST = path43.join(os40.homedir(), "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`);
|
|
21730
21824
|
SYSTEMD_UNIT_DIR = path43.join(os40.homedir(), ".config", "systemd", "user");
|
|
21731
21825
|
SYSTEMD_UNIT = path43.join(SYSTEMD_UNIT_DIR, "node9-daemon.service");
|
|
21826
|
+
SCHTASKS_TASK = "Node9Daemon";
|
|
21827
|
+
WIN_LAUNCHER = () => path43.join(os40.homedir(), ".node9", "daemon-launcher.vbs");
|
|
21732
21828
|
}
|
|
21733
21829
|
});
|
|
21734
21830
|
|
|
@@ -48022,6 +48118,20 @@ function buildReviewMessage(blockedByLabel, ruleDescription, reason) {
|
|
|
48022
48118
|
return `Node9 flagged this for your review: ${why}. Approve to proceed, or deny to cancel.`;
|
|
48023
48119
|
}
|
|
48024
48120
|
|
|
48121
|
+
// src/utils/platform-shell.ts
|
|
48122
|
+
function locatorCommand() {
|
|
48123
|
+
return process.platform === "win32" ? "where" : "which";
|
|
48124
|
+
}
|
|
48125
|
+
function shellInvocation(command) {
|
|
48126
|
+
if (process.platform === "win32") {
|
|
48127
|
+
return {
|
|
48128
|
+
file: process.env.ComSpec || "cmd.exe",
|
|
48129
|
+
args: ["/d", "/s", "/c", command]
|
|
48130
|
+
};
|
|
48131
|
+
}
|
|
48132
|
+
return { file: "/bin/bash", args: ["-c", command] };
|
|
48133
|
+
}
|
|
48134
|
+
|
|
48025
48135
|
// src/proxy/index.ts
|
|
48026
48136
|
function sanitize(value) {
|
|
48027
48137
|
return value.replace(/[\x00-\x1F\x7F]/g, "");
|
|
@@ -48033,14 +48143,16 @@ async function runProxy(targetCommand) {
|
|
|
48033
48143
|
let executable = cmd;
|
|
48034
48144
|
let useShell = false;
|
|
48035
48145
|
try {
|
|
48036
|
-
const { stdout } = await execa(
|
|
48037
|
-
|
|
48146
|
+
const { stdout } = await execa(locatorCommand(), [cmd]);
|
|
48147
|
+
const first = stdout.split(/\r?\n/)[0]?.trim();
|
|
48148
|
+
if (first) executable = first;
|
|
48038
48149
|
} catch {
|
|
48039
48150
|
useShell = true;
|
|
48040
48151
|
}
|
|
48041
48152
|
console.error(chalk8.green(`\u{1F680} Node9 Proxy Active: Monitoring [${targetCommand}]`));
|
|
48042
48153
|
const spawnEnv = { ...process.env, FORCE_COLOR: "1" };
|
|
48043
|
-
const
|
|
48154
|
+
const shell = shellInvocation(targetCommand);
|
|
48155
|
+
const child = useShell ? spawn2(shell.file, shell.args, {
|
|
48044
48156
|
stdio: ["pipe", "pipe", "inherit"],
|
|
48045
48157
|
shell: false,
|
|
48046
48158
|
env: spawnEnv
|
|
@@ -48104,6 +48216,17 @@ async function runProxy(targetCommand) {
|
|
|
48104
48216
|
child.stdin.write(line + "\n");
|
|
48105
48217
|
});
|
|
48106
48218
|
child.stdout.pipe(process.stdout);
|
|
48219
|
+
child.on("error", (err2) => {
|
|
48220
|
+
const what = useShell ? shell.file : executable;
|
|
48221
|
+
console.error(
|
|
48222
|
+
chalk8.red(
|
|
48223
|
+
err2.code === "ENOENT" ? `
|
|
48224
|
+
\u274C Node9 could not run "${targetCommand}": ${what} was not found on this machine.` : `
|
|
48225
|
+
\u274C Node9 could not run "${targetCommand}": ${err2.message}`
|
|
48226
|
+
)
|
|
48227
|
+
);
|
|
48228
|
+
process.exit(127);
|
|
48229
|
+
});
|
|
48107
48230
|
child.on("exit", (code) => process.exit(code || 0));
|
|
48108
48231
|
}
|
|
48109
48232
|
|
|
@@ -48249,7 +48372,7 @@ async function onboardMachine(apiKey, opts = {}) {
|
|
|
48249
48372
|
push.ok ? { name: "register", ok: true, detail: "machine visible in the dashboard" } : { name: "register", ok: false, detail: push.reason }
|
|
48250
48373
|
);
|
|
48251
48374
|
const healed = ensureAutostartHealthy(!!getConfig().settings.autoStartDaemon);
|
|
48252
|
-
const detail = healed === "repaired" ? "autostart re-enabled (survives reboot)" : isDaemonRunning() ? "running" : healed === "unsupported" ? "no background service on this platform: starts on agent activity" : "starts on agent activity";
|
|
48375
|
+
const detail = healed === "repaired" ? "autostart re-enabled (survives reboot)" : isDaemonRunning() ? "running" : healed === "unsupported" ? "no background service on this platform: starts on agent activity" : "starts on agent activity (make it survive reboots: node9 daemon install)";
|
|
48253
48376
|
steps.push({ name: "daemon", ok: true, detail });
|
|
48254
48377
|
}
|
|
48255
48378
|
const required = ["credentials", "policy-sync", "register"];
|
|
@@ -50225,8 +50348,10 @@ function registerDoctorCommand(program2, version2) {
|
|
|
50225
50348
|
`));
|
|
50226
50349
|
section("Binary");
|
|
50227
50350
|
try {
|
|
50228
|
-
const
|
|
50229
|
-
|
|
50351
|
+
const found = execSync(`${locatorCommand()} node9`, {
|
|
50352
|
+
encoding: "utf-8",
|
|
50353
|
+
timeout: 3e3
|
|
50354
|
+
}).split(/\r?\n/)[0].trim();
|
|
50230
50355
|
pass(`node9 found at ${found}`);
|
|
50231
50356
|
} catch {
|
|
50232
50357
|
warn("node9 not found in $PATH \u2014 hooks may not find it", "Run: npm install -g node9-ai");
|
|
@@ -50353,7 +50478,9 @@ function registerDoctorCommand(program2, version2) {
|
|
|
50353
50478
|
const fails = health.consecutiveFailures > 0 ? ` (${health.consecutiveFailures} consecutive failure${health.consecutiveFailures === 1 ? "" : "s"}${health.lastError ? `: ${health.lastError}` : ""})` : "";
|
|
50354
50479
|
warn(
|
|
50355
50480
|
`Cloud policy is STALE \u2014 ${when}${fails}. The cached policy is still enforced, but changes from the dashboard are not reaching this machine.`,
|
|
50356
|
-
|
|
50481
|
+
// Platform-aware: this hint hardcoded systemctl and told a Windows
|
|
50482
|
+
// founder to run a Linux command (QA 2026-08-28).
|
|
50483
|
+
`Run: node9 policy sync (then keep it fresh across reboots \u2014 ${autostartInstallHint()})`
|
|
50357
50484
|
);
|
|
50358
50485
|
} else if (health.lastCheckedAt) {
|
|
50359
50486
|
pass(`Cloud policy fresh \u2014 last synced ${agoLabel(health.lastCheckedAt)}`);
|
|
@@ -52095,7 +52222,7 @@ function registerInitCommand(program2) {
|
|
|
52095
52222
|
await setupAgent(agent);
|
|
52096
52223
|
console.log("");
|
|
52097
52224
|
}
|
|
52098
|
-
if ((process.platform === "darwin" || process.platform === "linux") && process.stdout.isTTY) {
|
|
52225
|
+
if ((process.platform === "darwin" || process.platform === "linux" || process.platform === "win32") && process.stdout.isTTY) {
|
|
52099
52226
|
const alreadyInstalled = isDaemonServiceInstalled();
|
|
52100
52227
|
if (!alreadyInstalled) {
|
|
52101
52228
|
const { confirm: confirm4 } = await import("@inquirer/prompts");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@node9/proxy",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "The Sudo Command for AI Agents. Execution Security for Claude Code, Codex, Gemini, Cursor, Opencode, Pi, and any MCP server.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|