@node9/proxy 2.48.0 → 2.48.1
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-main.js +65 -17
- package/dist/hook.js +64 -17
- package/package.json +1 -1
package/dist/cli-main.js
CHANGED
|
@@ -26965,7 +26965,7 @@ var init_negotiation = __esm({
|
|
|
26965
26965
|
init_cjs_shims();
|
|
26966
26966
|
init_dist();
|
|
26967
26967
|
USER_LINE_ICON = "\u{1F6E1}\uFE0F";
|
|
26968
|
-
QUOTE_INSTRUCTION = "Start your reply with the line above, exactly as written, on its own line.";
|
|
26968
|
+
QUOTE_INSTRUCTION = "Start your reply about this blocked action with the line above, exactly as written, on its own line. Leave it out of later replies.";
|
|
26969
26969
|
USER_LINE_PART_MAX = 160;
|
|
26970
26970
|
ONE_LINE_INPUT_MAX = 1e3;
|
|
26971
26971
|
PICTOGRAPHS = /[\p{Extended_Pictographic}\u200D\uFE0F]/gu;
|
|
@@ -74924,6 +74924,7 @@ var import_fs74 = __toESM(require("fs"));
|
|
|
74924
74924
|
var import_os61 = __toESM(require("os"));
|
|
74925
74925
|
var import_path74 = __toESM(require("path"));
|
|
74926
74926
|
init_dist();
|
|
74927
|
+
init_atomic_write();
|
|
74927
74928
|
var ICON2 = "\u{1F6E1}\uFE0F";
|
|
74928
74929
|
var LEVEL_NAMES = {
|
|
74929
74930
|
audit: "Audit",
|
|
@@ -74932,23 +74933,27 @@ var LEVEL_NAMES = {
|
|
|
74932
74933
|
strict: "Strict",
|
|
74933
74934
|
"block-all": "Block all"
|
|
74934
74935
|
};
|
|
74935
|
-
var
|
|
74936
|
+
var SESSION_NOTICE_NOTE = "node9 shows the user this line itself. Do not mention it unless the user asks about node9.";
|
|
74936
74937
|
var FLAG_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
74937
74938
|
var SAFE_SESSION_ID = /^[A-Za-z0-9_-]{1,128}$/;
|
|
74938
|
-
function sessionNoticeLine(mode) {
|
|
74939
|
+
function sessionNoticeLine(mode, kind = "first") {
|
|
74939
74940
|
const level = levelOf(mode);
|
|
74941
|
+
const name = LEVEL_NAMES[level];
|
|
74942
|
+
if (kind === "changed") {
|
|
74943
|
+
return level === "audit" ? `${ICON2} Node9 level changed to Audit: actions are logged, nothing is blocked.` : `${ICON2} Node9 level changed to ${name}. Every action in this session is checked.`;
|
|
74944
|
+
}
|
|
74940
74945
|
if (level === "audit") {
|
|
74941
74946
|
return `${ICON2} Node9 is in Audit mode: actions are logged, nothing is blocked.`;
|
|
74942
74947
|
}
|
|
74943
|
-
return `${ICON2} Node9 is on (${
|
|
74948
|
+
return `${ICON2} Node9 is on (${name}). Every action in this session is checked.`;
|
|
74944
74949
|
}
|
|
74945
|
-
function sessionNoticeOutput(mode) {
|
|
74946
|
-
const line = sessionNoticeLine(mode);
|
|
74950
|
+
function sessionNoticeOutput(mode, kind = "first") {
|
|
74951
|
+
const line = sessionNoticeLine(mode, kind);
|
|
74947
74952
|
return JSON.stringify({
|
|
74948
74953
|
hookSpecificOutput: {
|
|
74949
74954
|
hookEventName: "PreToolUse",
|
|
74950
74955
|
additionalContext: `${line}
|
|
74951
|
-
${
|
|
74956
|
+
${SESSION_NOTICE_NOTE}`
|
|
74952
74957
|
},
|
|
74953
74958
|
systemMessage: line
|
|
74954
74959
|
});
|
|
@@ -74957,19 +74962,61 @@ function sessionNoticeEnabled(env = process.env) {
|
|
|
74957
74962
|
if (env.NODE9_SESSION_NOTICE === "1") return true;
|
|
74958
74963
|
return env.NODE9_TESTING !== "1";
|
|
74959
74964
|
}
|
|
74960
|
-
|
|
74961
|
-
|
|
74965
|
+
var FLAG_MAX_BYTES = 32;
|
|
74966
|
+
function claimSessionNotice(sessionId, home = import_os61.default.homedir(), level = "standard") {
|
|
74967
|
+
if (!sessionId || !SAFE_SESSION_ID.test(sessionId)) return null;
|
|
74962
74968
|
const dir2 = import_path74.default.join(home, ".node9", "notice-sessions");
|
|
74963
74969
|
const seen = ensureOwnDir(dir2);
|
|
74964
|
-
if (!seen) return
|
|
74970
|
+
if (!seen) return null;
|
|
74971
|
+
const flag = import_path74.default.join(dir2, sessionId + SESSION_FLAG_SUFFIX);
|
|
74972
|
+
let created = false;
|
|
74965
74973
|
try {
|
|
74966
|
-
if (!isSameOwnDir(dir2, seen)) return
|
|
74967
|
-
import_fs74.default.
|
|
74968
|
-
|
|
74969
|
-
|
|
74974
|
+
if (!isSameOwnDir(dir2, seen)) return null;
|
|
74975
|
+
const fd = import_fs74.default.openSync(flag, "wx", 384);
|
|
74976
|
+
created = true;
|
|
74977
|
+
try {
|
|
74978
|
+
import_fs74.default.writeSync(fd, level);
|
|
74979
|
+
} finally {
|
|
74980
|
+
import_fs74.default.closeSync(fd);
|
|
74981
|
+
}
|
|
74982
|
+
} catch (err2) {
|
|
74983
|
+
if (created) {
|
|
74984
|
+
try {
|
|
74985
|
+
import_fs74.default.unlinkSync(flag);
|
|
74986
|
+
} catch {
|
|
74987
|
+
}
|
|
74988
|
+
return null;
|
|
74989
|
+
}
|
|
74990
|
+
if (err2.code !== "EEXIST") return null;
|
|
74991
|
+
return levelChange(dir2, seen, flag, level);
|
|
74970
74992
|
}
|
|
74971
74993
|
removeOldFlags(dir2, seen);
|
|
74972
|
-
return
|
|
74994
|
+
return "first";
|
|
74995
|
+
}
|
|
74996
|
+
function levelChange(dir2, seen, flag, level) {
|
|
74997
|
+
try {
|
|
74998
|
+
const told = readFlag(flag);
|
|
74999
|
+
if (told === null) return null;
|
|
75000
|
+
if (told === level) return null;
|
|
75001
|
+
if (!isSameOwnDir(dir2, seen)) return null;
|
|
75002
|
+
atomicWriteSync(flag, level, { mode: 384 });
|
|
75003
|
+
return told === "" ? null : "changed";
|
|
75004
|
+
} catch {
|
|
75005
|
+
return null;
|
|
75006
|
+
}
|
|
75007
|
+
}
|
|
75008
|
+
function readFlag(flag) {
|
|
75009
|
+
const c = import_fs74.default.constants;
|
|
75010
|
+
const fd = import_fs74.default.openSync(flag, c.O_RDONLY | (c.O_NOFOLLOW ?? 0) | (c.O_NONBLOCK ?? 0));
|
|
75011
|
+
try {
|
|
75012
|
+
const st = import_fs74.default.fstatSync(fd);
|
|
75013
|
+
if (!st.isFile() || st.nlink !== 1 || st.size > FLAG_MAX_BYTES) return null;
|
|
75014
|
+
const buf = Buffer.alloc(FLAG_MAX_BYTES);
|
|
75015
|
+
const n = import_fs74.default.readSync(fd, buf, 0, FLAG_MAX_BYTES, 0);
|
|
75016
|
+
return buf.toString("utf8", 0, n).trim();
|
|
75017
|
+
} finally {
|
|
75018
|
+
import_fs74.default.closeSync(fd);
|
|
75019
|
+
}
|
|
74973
75020
|
}
|
|
74974
75021
|
function removeOldFlags(dir2, seen) {
|
|
74975
75022
|
const cutoff = Date.now() - FLAG_TTL_MS;
|
|
@@ -75526,9 +75573,10 @@ RAW: ${raw}
|
|
|
75526
75573
|
}
|
|
75527
75574
|
const isSubagentCall = typeof payload.agent_id === "string" && payload.agent_id !== "";
|
|
75528
75575
|
const allowExit = (checkedBy) => {
|
|
75529
|
-
|
|
75576
|
+
const notice = checkedBy !== "paused" && agent === "Claude Code" && !isSubagentCall && sessionNoticeEnabled() ? claimSessionNotice(safeSessionId, import_os62.default.homedir(), levelOf(config.settings.mode)) : null;
|
|
75577
|
+
if (notice) {
|
|
75530
75578
|
try {
|
|
75531
|
-
import_fs75.default.writeSync(1, sessionNoticeOutput(config.settings.mode) + "\n");
|
|
75579
|
+
import_fs75.default.writeSync(1, sessionNoticeOutput(config.settings.mode, notice) + "\n");
|
|
75532
75580
|
} catch {
|
|
75533
75581
|
}
|
|
75534
75582
|
}
|
package/dist/hook.js
CHANGED
|
@@ -24161,7 +24161,7 @@ function recordAndCheck(tool, args, threshold = 3, windowMs = 12e4) {
|
|
|
24161
24161
|
init_cjs_shims();
|
|
24162
24162
|
init_dist();
|
|
24163
24163
|
var USER_LINE_ICON = "\u{1F6E1}\uFE0F";
|
|
24164
|
-
var QUOTE_INSTRUCTION = "Start your reply with the line above, exactly as written, on its own line.";
|
|
24164
|
+
var QUOTE_INSTRUCTION = "Start your reply about this blocked action with the line above, exactly as written, on its own line. Leave it out of later replies.";
|
|
24165
24165
|
var USER_LINE_PART_MAX = 160;
|
|
24166
24166
|
var ONE_LINE_INPUT_MAX = 1e3;
|
|
24167
24167
|
var PICTOGRAPHS = /[\p{Extended_Pictographic}\u200D\uFE0F]/gu;
|
|
@@ -26487,23 +26487,27 @@ var LEVEL_NAMES = {
|
|
|
26487
26487
|
strict: "Strict",
|
|
26488
26488
|
"block-all": "Block all"
|
|
26489
26489
|
};
|
|
26490
|
-
var
|
|
26490
|
+
var SESSION_NOTICE_NOTE = "node9 shows the user this line itself. Do not mention it unless the user asks about node9.";
|
|
26491
26491
|
var FLAG_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
26492
26492
|
var SAFE_SESSION_ID = /^[A-Za-z0-9_-]{1,128}$/;
|
|
26493
|
-
function sessionNoticeLine(mode) {
|
|
26493
|
+
function sessionNoticeLine(mode, kind = "first") {
|
|
26494
26494
|
const level = levelOf(mode);
|
|
26495
|
+
const name = LEVEL_NAMES[level];
|
|
26496
|
+
if (kind === "changed") {
|
|
26497
|
+
return level === "audit" ? `${ICON} Node9 level changed to Audit: actions are logged, nothing is blocked.` : `${ICON} Node9 level changed to ${name}. Every action in this session is checked.`;
|
|
26498
|
+
}
|
|
26495
26499
|
if (level === "audit") {
|
|
26496
26500
|
return `${ICON} Node9 is in Audit mode: actions are logged, nothing is blocked.`;
|
|
26497
26501
|
}
|
|
26498
|
-
return `${ICON} Node9 is on (${
|
|
26502
|
+
return `${ICON} Node9 is on (${name}). Every action in this session is checked.`;
|
|
26499
26503
|
}
|
|
26500
|
-
function sessionNoticeOutput(mode) {
|
|
26501
|
-
const line = sessionNoticeLine(mode);
|
|
26504
|
+
function sessionNoticeOutput(mode, kind = "first") {
|
|
26505
|
+
const line = sessionNoticeLine(mode, kind);
|
|
26502
26506
|
return JSON.stringify({
|
|
26503
26507
|
hookSpecificOutput: {
|
|
26504
26508
|
hookEventName: "PreToolUse",
|
|
26505
26509
|
additionalContext: `${line}
|
|
26506
|
-
${
|
|
26510
|
+
${SESSION_NOTICE_NOTE}`
|
|
26507
26511
|
},
|
|
26508
26512
|
systemMessage: line
|
|
26509
26513
|
});
|
|
@@ -26512,19 +26516,61 @@ function sessionNoticeEnabled(env = process.env) {
|
|
|
26512
26516
|
if (env.NODE9_SESSION_NOTICE === "1") return true;
|
|
26513
26517
|
return env.NODE9_TESTING !== "1";
|
|
26514
26518
|
}
|
|
26515
|
-
|
|
26516
|
-
|
|
26519
|
+
var FLAG_MAX_BYTES = 32;
|
|
26520
|
+
function claimSessionNotice(sessionId, home = import_os26.default.homedir(), level = "standard") {
|
|
26521
|
+
if (!sessionId || !SAFE_SESSION_ID.test(sessionId)) return null;
|
|
26517
26522
|
const dir2 = import_path36.default.join(home, ".node9", "notice-sessions");
|
|
26518
26523
|
const seen = ensureOwnDir(dir2);
|
|
26519
|
-
if (!seen) return
|
|
26524
|
+
if (!seen) return null;
|
|
26525
|
+
const flag = import_path36.default.join(dir2, sessionId + SESSION_FLAG_SUFFIX);
|
|
26526
|
+
let created = false;
|
|
26520
26527
|
try {
|
|
26521
|
-
if (!isSameOwnDir(dir2, seen)) return
|
|
26522
|
-
import_fs34.default.
|
|
26523
|
-
|
|
26524
|
-
|
|
26528
|
+
if (!isSameOwnDir(dir2, seen)) return null;
|
|
26529
|
+
const fd = import_fs34.default.openSync(flag, "wx", 384);
|
|
26530
|
+
created = true;
|
|
26531
|
+
try {
|
|
26532
|
+
import_fs34.default.writeSync(fd, level);
|
|
26533
|
+
} finally {
|
|
26534
|
+
import_fs34.default.closeSync(fd);
|
|
26535
|
+
}
|
|
26536
|
+
} catch (err) {
|
|
26537
|
+
if (created) {
|
|
26538
|
+
try {
|
|
26539
|
+
import_fs34.default.unlinkSync(flag);
|
|
26540
|
+
} catch {
|
|
26541
|
+
}
|
|
26542
|
+
return null;
|
|
26543
|
+
}
|
|
26544
|
+
if (err.code !== "EEXIST") return null;
|
|
26545
|
+
return levelChange(dir2, seen, flag, level);
|
|
26525
26546
|
}
|
|
26526
26547
|
removeOldFlags(dir2, seen);
|
|
26527
|
-
return
|
|
26548
|
+
return "first";
|
|
26549
|
+
}
|
|
26550
|
+
function levelChange(dir2, seen, flag, level) {
|
|
26551
|
+
try {
|
|
26552
|
+
const told = readFlag(flag);
|
|
26553
|
+
if (told === null) return null;
|
|
26554
|
+
if (told === level) return null;
|
|
26555
|
+
if (!isSameOwnDir(dir2, seen)) return null;
|
|
26556
|
+
atomicWriteSync(flag, level, { mode: 384 });
|
|
26557
|
+
return told === "" ? null : "changed";
|
|
26558
|
+
} catch {
|
|
26559
|
+
return null;
|
|
26560
|
+
}
|
|
26561
|
+
}
|
|
26562
|
+
function readFlag(flag) {
|
|
26563
|
+
const c = import_fs34.default.constants;
|
|
26564
|
+
const fd = import_fs34.default.openSync(flag, c.O_RDONLY | (c.O_NOFOLLOW ?? 0) | (c.O_NONBLOCK ?? 0));
|
|
26565
|
+
try {
|
|
26566
|
+
const st = import_fs34.default.fstatSync(fd);
|
|
26567
|
+
if (!st.isFile() || st.nlink !== 1 || st.size > FLAG_MAX_BYTES) return null;
|
|
26568
|
+
const buf = Buffer.alloc(FLAG_MAX_BYTES);
|
|
26569
|
+
const n = import_fs34.default.readSync(fd, buf, 0, FLAG_MAX_BYTES, 0);
|
|
26570
|
+
return buf.toString("utf8", 0, n).trim();
|
|
26571
|
+
} finally {
|
|
26572
|
+
import_fs34.default.closeSync(fd);
|
|
26573
|
+
}
|
|
26528
26574
|
}
|
|
26529
26575
|
function removeOldFlags(dir2, seen) {
|
|
26530
26576
|
const cutoff = Date.now() - FLAG_TTL_MS;
|
|
@@ -27081,9 +27127,10 @@ RAW: ${raw}
|
|
|
27081
27127
|
}
|
|
27082
27128
|
const isSubagentCall = typeof payload.agent_id === "string" && payload.agent_id !== "";
|
|
27083
27129
|
const allowExit = (checkedBy) => {
|
|
27084
|
-
|
|
27130
|
+
const notice = checkedBy !== "paused" && agent === "Claude Code" && !isSubagentCall && sessionNoticeEnabled() ? claimSessionNotice(safeSessionId, import_os27.default.homedir(), levelOf(config.settings.mode)) : null;
|
|
27131
|
+
if (notice) {
|
|
27085
27132
|
try {
|
|
27086
|
-
import_fs35.default.writeSync(1, sessionNoticeOutput(config.settings.mode) + "\n");
|
|
27133
|
+
import_fs35.default.writeSync(1, sessionNoticeOutput(config.settings.mode, notice) + "\n");
|
|
27087
27134
|
} catch {
|
|
27088
27135
|
}
|
|
27089
27136
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@node9/proxy",
|
|
3
|
-
"version": "2.48.
|
|
3
|
+
"version": "2.48.1",
|
|
4
4
|
"description": "Access control for AI agents. Set what Claude Code, Codex, Gemini, Cursor and any MCP server are allowed to do, review risky actions before they run, and keep every action on the record.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|