@node9/proxy 1.19.2 → 1.19.4
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 +200 -112
- package/dist/cli.mjs +168 -80
- package/dist/dashboard.mjs +4651 -0
- package/dist/index.js +21 -23
- package/dist/index.mjs +17 -19
- package/package.json +4 -1
package/dist/index.js
CHANGED
|
@@ -3601,7 +3601,6 @@ var import_fs8 = __toESM(require("fs"));
|
|
|
3601
3601
|
var import_net = __toESM(require("net"));
|
|
3602
3602
|
var import_path8 = __toESM(require("path"));
|
|
3603
3603
|
var import_os7 = __toESM(require("os"));
|
|
3604
|
-
var import_child_process = require("child_process");
|
|
3605
3604
|
var ACTIVITY_SOCKET_PATH = process.platform === "win32" ? "\\\\.\\pipe\\node9-activity" : import_path8.default.join(import_os7.default.tmpdir(), "node9-activity.sock");
|
|
3606
3605
|
function notifyActivitySocket(data) {
|
|
3607
3606
|
return new Promise((resolve) => {
|
|
@@ -3674,22 +3673,9 @@ function isDaemonRunning() {
|
|
|
3674
3673
|
}
|
|
3675
3674
|
return false;
|
|
3676
3675
|
}
|
|
3677
|
-
|
|
3678
|
-
encoding: "utf8",
|
|
3679
|
-
timeout: 300
|
|
3680
|
-
});
|
|
3681
|
-
if (r.status === 0 && (r.stdout ?? "").includes(`:${DAEMON_PORT}`)) return true;
|
|
3682
|
-
return false;
|
|
3683
|
-
}
|
|
3684
|
-
try {
|
|
3685
|
-
const r = (0, import_child_process.spawnSync)("ss", ["-Htnp", `sport = :${DAEMON_PORT}`], {
|
|
3686
|
-
encoding: "utf8",
|
|
3687
|
-
timeout: 300
|
|
3688
|
-
});
|
|
3689
|
-
return r.status === 0 && (r.stdout ?? "").includes(`:${DAEMON_PORT}`);
|
|
3690
|
-
} catch {
|
|
3691
|
-
return false;
|
|
3676
|
+
return true;
|
|
3692
3677
|
}
|
|
3678
|
+
return false;
|
|
3693
3679
|
}
|
|
3694
3680
|
async function registerDaemonEntry(toolName, args, meta, riskMetadata, activityId, cwd, recoveryCommand, skipBackgroundAuth, viewOnly, localSmartRuleMatched, socketActivitySent) {
|
|
3695
3681
|
const base = `http://${DAEMON_HOST}:${DAEMON_PORT}`;
|
|
@@ -3745,7 +3731,7 @@ async function waitForDaemonDecision(id, signal) {
|
|
|
3745
3731
|
if (signal) signal.removeEventListener("abort", onAbort);
|
|
3746
3732
|
}
|
|
3747
3733
|
}
|
|
3748
|
-
async function notifyDaemonViewer(toolName, args, meta, riskMetadata) {
|
|
3734
|
+
async function notifyDaemonViewer(toolName, args, meta, riskMetadata, activityId, socketActivitySent) {
|
|
3749
3735
|
const base = `http://${DAEMON_HOST}:${DAEMON_PORT}`;
|
|
3750
3736
|
const res = await fetch(`${base}/check`, {
|
|
3751
3737
|
method: "POST",
|
|
@@ -3756,7 +3742,12 @@ async function notifyDaemonViewer(toolName, args, meta, riskMetadata) {
|
|
|
3756
3742
|
slackDelegated: true,
|
|
3757
3743
|
agent: meta?.agent,
|
|
3758
3744
|
mcpServer: meta?.mcpServer,
|
|
3759
|
-
...riskMetadata && { riskMetadata }
|
|
3745
|
+
...riskMetadata && { riskMetadata },
|
|
3746
|
+
// fromCLI=true tells the daemon the CLI already sent the activity
|
|
3747
|
+
// event via socket. Same contract as registerDaemonEntry — without
|
|
3748
|
+
// it the daemon double-emits 'activity' for cloud-enforced flows.
|
|
3749
|
+
fromCLI: socketActivitySent !== false,
|
|
3750
|
+
activityId
|
|
3760
3751
|
}),
|
|
3761
3752
|
signal: AbortSignal.timeout(3e3)
|
|
3762
3753
|
});
|
|
@@ -3817,7 +3808,7 @@ async function resolveViaDaemon(id, decision, internalToken, source) {
|
|
|
3817
3808
|
var import_crypto3 = require("crypto");
|
|
3818
3809
|
|
|
3819
3810
|
// src/ui/native.ts
|
|
3820
|
-
var
|
|
3811
|
+
var import_child_process = require("child_process");
|
|
3821
3812
|
var import_path10 = __toESM(require("path"));
|
|
3822
3813
|
|
|
3823
3814
|
// src/context-sniper.ts
|
|
@@ -4091,7 +4082,7 @@ activate
|
|
|
4091
4082
|
display dialog (item 1 of argv) with title (item 2 of argv) ${buttons}
|
|
4092
4083
|
end tell
|
|
4093
4084
|
end run`;
|
|
4094
|
-
childProcess = (0,
|
|
4085
|
+
childProcess = (0, import_child_process.spawn)("osascript", ["-e", script, "--", message, title]);
|
|
4095
4086
|
} else if (process.platform === "linux") {
|
|
4096
4087
|
const pangoMessage = buildPangoMessage(
|
|
4097
4088
|
toolName,
|
|
@@ -4117,12 +4108,12 @@ end run`;
|
|
|
4117
4108
|
argsList.push("--cancel-label", "Block \u238B");
|
|
4118
4109
|
argsList.push("--extra-button", "Always Allow");
|
|
4119
4110
|
}
|
|
4120
|
-
childProcess = (0,
|
|
4111
|
+
childProcess = (0, import_child_process.spawn)("zenity", argsList);
|
|
4121
4112
|
} else if (process.platform === "win32") {
|
|
4122
4113
|
const b64Msg = Buffer.from(message).toString("base64");
|
|
4123
4114
|
const b64Title = Buffer.from(title).toString("base64");
|
|
4124
4115
|
const ps = `Add-Type -AssemblyName PresentationFramework; $msg = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String("${b64Msg}")); $title = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String("${b64Title}")); $res = [System.Windows.MessageBox]::Show($msg, $title, "${locked ? "OK" : "YesNo"}", "Warning", "Button2", "DefaultDesktopOnly"); if ($res -eq "Yes") { exit 0 } else { exit 1 }`;
|
|
4125
|
-
childProcess = (0,
|
|
4116
|
+
childProcess = (0, import_child_process.spawn)("powershell", ["-Command", ps]);
|
|
4126
4117
|
}
|
|
4127
4118
|
let output = "";
|
|
4128
4119
|
childProcess?.stdout?.on("data", (d) => output += d.toString());
|
|
@@ -4851,7 +4842,14 @@ async function _authorizeHeadlessCore(toolName, args, meta, options) {
|
|
|
4851
4842
|
let daemonAllowCount = 1;
|
|
4852
4843
|
if (approvers.terminal && isDaemonRunning() && !options?.calledFromDaemon) {
|
|
4853
4844
|
if (cloudEnforced && cloudRequestId) {
|
|
4854
|
-
const viewer = await notifyDaemonViewer(
|
|
4845
|
+
const viewer = await notifyDaemonViewer(
|
|
4846
|
+
toolName,
|
|
4847
|
+
args,
|
|
4848
|
+
meta,
|
|
4849
|
+
riskMetadata,
|
|
4850
|
+
options?.activityId,
|
|
4851
|
+
options?.socketActivitySent
|
|
4852
|
+
).catch(() => null);
|
|
4855
4853
|
viewerId = viewer?.id ?? null;
|
|
4856
4854
|
daemonEntryId = viewerId;
|
|
4857
4855
|
if (viewer) daemonAllowCount = viewer.allowCount;
|
package/dist/index.mjs
CHANGED
|
@@ -3571,7 +3571,6 @@ import fs8 from "fs";
|
|
|
3571
3571
|
import net from "net";
|
|
3572
3572
|
import path8 from "path";
|
|
3573
3573
|
import os7 from "os";
|
|
3574
|
-
import { spawnSync } from "child_process";
|
|
3575
3574
|
var ACTIVITY_SOCKET_PATH = process.platform === "win32" ? "\\\\.\\pipe\\node9-activity" : path8.join(os7.tmpdir(), "node9-activity.sock");
|
|
3576
3575
|
function notifyActivitySocket(data) {
|
|
3577
3576
|
return new Promise((resolve) => {
|
|
@@ -3644,22 +3643,9 @@ function isDaemonRunning() {
|
|
|
3644
3643
|
}
|
|
3645
3644
|
return false;
|
|
3646
3645
|
}
|
|
3647
|
-
|
|
3648
|
-
encoding: "utf8",
|
|
3649
|
-
timeout: 300
|
|
3650
|
-
});
|
|
3651
|
-
if (r.status === 0 && (r.stdout ?? "").includes(`:${DAEMON_PORT}`)) return true;
|
|
3652
|
-
return false;
|
|
3653
|
-
}
|
|
3654
|
-
try {
|
|
3655
|
-
const r = spawnSync("ss", ["-Htnp", `sport = :${DAEMON_PORT}`], {
|
|
3656
|
-
encoding: "utf8",
|
|
3657
|
-
timeout: 300
|
|
3658
|
-
});
|
|
3659
|
-
return r.status === 0 && (r.stdout ?? "").includes(`:${DAEMON_PORT}`);
|
|
3660
|
-
} catch {
|
|
3661
|
-
return false;
|
|
3646
|
+
return true;
|
|
3662
3647
|
}
|
|
3648
|
+
return false;
|
|
3663
3649
|
}
|
|
3664
3650
|
async function registerDaemonEntry(toolName, args, meta, riskMetadata, activityId, cwd, recoveryCommand, skipBackgroundAuth, viewOnly, localSmartRuleMatched, socketActivitySent) {
|
|
3665
3651
|
const base = `http://${DAEMON_HOST}:${DAEMON_PORT}`;
|
|
@@ -3715,7 +3701,7 @@ async function waitForDaemonDecision(id, signal) {
|
|
|
3715
3701
|
if (signal) signal.removeEventListener("abort", onAbort);
|
|
3716
3702
|
}
|
|
3717
3703
|
}
|
|
3718
|
-
async function notifyDaemonViewer(toolName, args, meta, riskMetadata) {
|
|
3704
|
+
async function notifyDaemonViewer(toolName, args, meta, riskMetadata, activityId, socketActivitySent) {
|
|
3719
3705
|
const base = `http://${DAEMON_HOST}:${DAEMON_PORT}`;
|
|
3720
3706
|
const res = await fetch(`${base}/check`, {
|
|
3721
3707
|
method: "POST",
|
|
@@ -3726,7 +3712,12 @@ async function notifyDaemonViewer(toolName, args, meta, riskMetadata) {
|
|
|
3726
3712
|
slackDelegated: true,
|
|
3727
3713
|
agent: meta?.agent,
|
|
3728
3714
|
mcpServer: meta?.mcpServer,
|
|
3729
|
-
...riskMetadata && { riskMetadata }
|
|
3715
|
+
...riskMetadata && { riskMetadata },
|
|
3716
|
+
// fromCLI=true tells the daemon the CLI already sent the activity
|
|
3717
|
+
// event via socket. Same contract as registerDaemonEntry — without
|
|
3718
|
+
// it the daemon double-emits 'activity' for cloud-enforced flows.
|
|
3719
|
+
fromCLI: socketActivitySent !== false,
|
|
3720
|
+
activityId
|
|
3730
3721
|
}),
|
|
3731
3722
|
signal: AbortSignal.timeout(3e3)
|
|
3732
3723
|
});
|
|
@@ -4821,7 +4812,14 @@ async function _authorizeHeadlessCore(toolName, args, meta, options) {
|
|
|
4821
4812
|
let daemonAllowCount = 1;
|
|
4822
4813
|
if (approvers.terminal && isDaemonRunning() && !options?.calledFromDaemon) {
|
|
4823
4814
|
if (cloudEnforced && cloudRequestId) {
|
|
4824
|
-
const viewer = await notifyDaemonViewer(
|
|
4815
|
+
const viewer = await notifyDaemonViewer(
|
|
4816
|
+
toolName,
|
|
4817
|
+
args,
|
|
4818
|
+
meta,
|
|
4819
|
+
riskMetadata,
|
|
4820
|
+
options?.activityId,
|
|
4821
|
+
options?.socketActivitySent
|
|
4822
|
+
).catch(() => null);
|
|
4825
4823
|
viewerId = viewer?.id ?? null;
|
|
4826
4824
|
daemonEntryId = viewerId;
|
|
4827
4825
|
if (viewer) daemonAllowCount = viewer.allowCount;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@node9/proxy",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.4",
|
|
4
4
|
"description": "The Sudo Command for AI Agents. Execution Security for Claude Code & MCP.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -77,8 +77,10 @@
|
|
|
77
77
|
"chalk": "^4.1.2",
|
|
78
78
|
"commander": "^14.0.3",
|
|
79
79
|
"execa": "^9.6.1",
|
|
80
|
+
"ink": "^7.0.2",
|
|
80
81
|
"mvdan-sh": "^0.10.1",
|
|
81
82
|
"picomatch": "^4.0.3",
|
|
83
|
+
"react": "^19.2.6",
|
|
82
84
|
"safe-regex2": "^5.1.0",
|
|
83
85
|
"smol-toml": "^1.6.1",
|
|
84
86
|
"zod": "^3.25.76"
|
|
@@ -96,6 +98,7 @@
|
|
|
96
98
|
"@semantic-release/release-notes-generator": "^14.1.0",
|
|
97
99
|
"@types/node": "^25.3.1",
|
|
98
100
|
"@types/picomatch": "^4.0.2",
|
|
101
|
+
"@types/react": "^19.2.14",
|
|
99
102
|
"@vitest/coverage-v8": "4.1.2",
|
|
100
103
|
"cross-env": "^10.1.0",
|
|
101
104
|
"prettier": "^3.4.2",
|