@node9/proxy 2.47.1 → 2.48.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-main.js +928 -666
- package/dist/dashboard.mjs +1 -0
- package/dist/hook.js +376 -123
- package/dist/index.js +17 -5
- package/dist/index.mjs +17 -5
- package/package.json +1 -1
- package/dist/cli-main.d.mts +0 -1
- package/dist/cli-main.d.ts +0 -1
- package/dist/cli-main.mjs +0 -90543
package/dist/cli-main.js
CHANGED
|
@@ -19279,8 +19279,8 @@ var init_audit = __esm({
|
|
|
19279
19279
|
// src/config-schema.ts
|
|
19280
19280
|
function formatIssues(issues) {
|
|
19281
19281
|
const lines = issues.map((issue) => {
|
|
19282
|
-
const
|
|
19283
|
-
return ` \u2022 ${
|
|
19282
|
+
const path110 = issue.path.length > 0 ? issue.path.map(String).join(".") : "root";
|
|
19283
|
+
return ` \u2022 ${path110}: ${issue.message}`;
|
|
19284
19284
|
});
|
|
19285
19285
|
return `Invalid config:
|
|
19286
19286
|
${lines.join("\n")}`;
|
|
@@ -19293,9 +19293,9 @@ function prunePaths(root, paths) {
|
|
|
19293
19293
|
const yi = y[y.length - 1];
|
|
19294
19294
|
return typeof xi === "number" && typeof yi === "number" ? yi - xi : 0;
|
|
19295
19295
|
});
|
|
19296
|
-
for (const
|
|
19296
|
+
for (const path110 of ordered) {
|
|
19297
19297
|
let cur = root;
|
|
19298
|
-
for (const key of
|
|
19298
|
+
for (const key of path110.slice(0, -1)) {
|
|
19299
19299
|
if (cur === null || typeof cur !== "object") {
|
|
19300
19300
|
cur = void 0;
|
|
19301
19301
|
break;
|
|
@@ -19303,7 +19303,7 @@ function prunePaths(root, paths) {
|
|
|
19303
19303
|
cur = cur[key];
|
|
19304
19304
|
}
|
|
19305
19305
|
if (cur === null || typeof cur !== "object") continue;
|
|
19306
|
-
const last =
|
|
19306
|
+
const last = path110[path110.length - 1];
|
|
19307
19307
|
if (Array.isArray(cur)) {
|
|
19308
19308
|
const i = Number(last);
|
|
19309
19309
|
if (Number.isInteger(i) && i >= 0 && i < cur.length) {
|
|
@@ -19339,7 +19339,7 @@ function sanitizeConfig(raw) {
|
|
|
19339
19339
|
return issue.keys.map((k) => [...at, k]);
|
|
19340
19340
|
}
|
|
19341
19341
|
return [at.slice(0, -level || void 0)];
|
|
19342
|
-
}).filter((
|
|
19342
|
+
}).filter((path110) => path110.length > 0);
|
|
19343
19343
|
if (paths.length === 0 || !prunePaths(working, paths)) break;
|
|
19344
19344
|
}
|
|
19345
19345
|
if (ConfigFileSchema.safeParse(working).success) break;
|
|
@@ -20933,13 +20933,13 @@ function getConfig(cwd) {
|
|
|
20933
20933
|
}
|
|
20934
20934
|
if (Array.isArray(mc.jailPaths)) {
|
|
20935
20935
|
for (const jp of mc.jailPaths) {
|
|
20936
|
-
const
|
|
20937
|
-
if (!
|
|
20936
|
+
const path110 = typeof jp?.path === "string" ? jp.path.trim() : "";
|
|
20937
|
+
if (!path110) continue;
|
|
20938
20938
|
const verdict = jp?.verdict === "review" ? "review" : "block";
|
|
20939
|
-
for (const r of pathRules(
|
|
20939
|
+
for (const r of pathRules(path110, verdict, "org-managed jail")) {
|
|
20940
20940
|
mergedPolicy.smartRules.push({ ...r, name: `org:${r.name}` });
|
|
20941
20941
|
}
|
|
20942
|
-
mergedPolicy.managedJailPaths.push({ path:
|
|
20942
|
+
mergedPolicy.managedJailPaths.push({ path: path110, verdict });
|
|
20943
20943
|
}
|
|
20944
20944
|
}
|
|
20945
20945
|
if (Array.isArray(mc.trustedHosts)) {
|
|
@@ -24007,19 +24007,29 @@ var init_decision_record = __esm({
|
|
|
24007
24007
|
});
|
|
24008
24008
|
|
|
24009
24009
|
// src/auth/daemon.ts
|
|
24010
|
-
function notifyActivitySocket(data) {
|
|
24010
|
+
function notifyActivitySocket(data, opts = {}) {
|
|
24011
24011
|
if (forecastRun()) return Promise.resolve(false);
|
|
24012
24012
|
return new Promise((resolve2) => {
|
|
24013
|
+
let settled = false;
|
|
24014
|
+
let sock = null;
|
|
24015
|
+
const finish = (ok2) => {
|
|
24016
|
+
if (settled) return;
|
|
24017
|
+
settled = true;
|
|
24018
|
+
clearTimeout(timer);
|
|
24019
|
+
if (!ok2) sock?.destroy();
|
|
24020
|
+
resolve2(ok2);
|
|
24021
|
+
};
|
|
24022
|
+
const timer = setTimeout(() => finish(false), opts.timeoutMs ?? ACTIVITY_SOCKET_TIMEOUT_MS);
|
|
24013
24023
|
try {
|
|
24014
24024
|
const payload = JSON.stringify(data);
|
|
24015
|
-
|
|
24025
|
+
sock = import_net4.default.createConnection(opts.socketPath ?? ACTIVITY_SOCKET_PATH);
|
|
24016
24026
|
sock.on("connect", () => {
|
|
24017
|
-
sock.on("close", () =>
|
|
24027
|
+
sock.on("close", () => finish(true));
|
|
24018
24028
|
sock.end(payload);
|
|
24019
24029
|
});
|
|
24020
|
-
sock.on("error", () =>
|
|
24030
|
+
sock.on("error", () => finish(false));
|
|
24021
24031
|
} catch {
|
|
24022
|
-
|
|
24032
|
+
finish(false);
|
|
24023
24033
|
}
|
|
24024
24034
|
});
|
|
24025
24035
|
}
|
|
@@ -24554,7 +24564,7 @@ async function resolveViaDaemon(id, decision, internalToken, source, record2) {
|
|
|
24554
24564
|
const winner = parseDecisionRecord(body?.record);
|
|
24555
24565
|
return winner && typeof body?.won === "boolean" ? { won: body.won, record: winner } : null;
|
|
24556
24566
|
}
|
|
24557
|
-
var import_fs15, import_http, import_net4, import_path15, import_os11, ACTIVITY_SOCKET_PATH, DEFAULT_DAEMON_PORT, DAEMON_PORT, DAEMON_HOST;
|
|
24567
|
+
var import_fs15, import_http, import_net4, import_path15, import_os11, ACTIVITY_SOCKET_PATH, ACTIVITY_SOCKET_TIMEOUT_MS, DEFAULT_DAEMON_PORT, DAEMON_PORT, DAEMON_HOST;
|
|
24558
24568
|
var init_daemon = __esm({
|
|
24559
24569
|
"src/auth/daemon.ts"() {
|
|
24560
24570
|
"use strict";
|
|
@@ -24567,6 +24577,7 @@ var init_daemon = __esm({
|
|
|
24567
24577
|
init_forecast_context();
|
|
24568
24578
|
init_decision_record();
|
|
24569
24579
|
ACTIVITY_SOCKET_PATH = process.platform === "win32" ? "\\\\.\\pipe\\node9-activity" : import_path15.default.join(import_os11.default.tmpdir(), "node9-activity.sock");
|
|
24580
|
+
ACTIVITY_SOCKET_TIMEOUT_MS = 500;
|
|
24570
24581
|
DEFAULT_DAEMON_PORT = 7391;
|
|
24571
24582
|
DAEMON_PORT = resolveDaemonPort();
|
|
24572
24583
|
DAEMON_HOST = "127.0.0.1";
|
|
@@ -26712,6 +26723,70 @@ var init_loop_detector = __esm({
|
|
|
26712
26723
|
});
|
|
26713
26724
|
|
|
26714
26725
|
// src/policy/negotiation.ts
|
|
26726
|
+
function oneLine(text) {
|
|
26727
|
+
return stripTerminalEscapes(text.slice(0, ONE_LINE_INPUT_MAX)).replace(/\s*\u2014\s*/g, ", ").replace(/\s+/g, " ").trim();
|
|
26728
|
+
}
|
|
26729
|
+
function bounded(text, max2 = USER_LINE_PART_MAX) {
|
|
26730
|
+
return text.length > max2 ? `${text.slice(0, max2 - 3).trimEnd()}...` : text;
|
|
26731
|
+
}
|
|
26732
|
+
function userLinePart(text) {
|
|
26733
|
+
return bounded(oneLine(text).replace(/[.\s]+$/, ""));
|
|
26734
|
+
}
|
|
26735
|
+
function userLineValue(text, max2 = 80) {
|
|
26736
|
+
const v = bounded(oneLine(text).replace(/`/g, "'"), max2);
|
|
26737
|
+
return v ? `\`${v}\`` : "";
|
|
26738
|
+
}
|
|
26739
|
+
function userLineOf(message) {
|
|
26740
|
+
const first = message.split("\n", 1)[0];
|
|
26741
|
+
return first.startsWith(USER_LINE_ICON) ? first : void 0;
|
|
26742
|
+
}
|
|
26743
|
+
function withUserLine(line, body) {
|
|
26744
|
+
return `${USER_LINE_ICON} ${line}
|
|
26745
|
+
${QUOTE_INSTRUCTION}
|
|
26746
|
+
${body}`;
|
|
26747
|
+
}
|
|
26748
|
+
function blockedLine(context, fallback) {
|
|
26749
|
+
return `Node9 blocked: ${ruleWhat(context?.ruleDescription) || fallback}`;
|
|
26750
|
+
}
|
|
26751
|
+
function firstSentence(text) {
|
|
26752
|
+
const plain = oneLine(text.replace(PICTOGRAPHS, ""));
|
|
26753
|
+
return plain.split(/(?<=[.!?])\s+(?=[A-Z])/)[0] ?? plain;
|
|
26754
|
+
}
|
|
26755
|
+
function withoutLeadingVerdict(text) {
|
|
26756
|
+
return text.replace(/^node9\b\s*:?\s*/i, "").replace(/^blocked\b\s*:?\s*/i, "");
|
|
26757
|
+
}
|
|
26758
|
+
function ruleWhat(description) {
|
|
26759
|
+
if (!description) return "";
|
|
26760
|
+
const s = firstSentence(description).replace(/^node9\s*:\s*/i, "").replace(/^blocked\s*:\s*/i, "");
|
|
26761
|
+
if (!/[\p{L}\p{N}]/u.test(s)) return "";
|
|
26762
|
+
const by = s.match(IS_BLOCKED_BY) ?? s.match(COMMA_BLOCKED_BY);
|
|
26763
|
+
if (by) return userLinePart(`${by[1]} (${by[2]})`);
|
|
26764
|
+
const bare = s.match(IS_BLOCKED);
|
|
26765
|
+
return userLinePart(bare ? bare[1] : s);
|
|
26766
|
+
}
|
|
26767
|
+
function reasonSentence(reason) {
|
|
26768
|
+
if (!reason) return "";
|
|
26769
|
+
const s = withoutLeadingVerdict(firstSentence(reason));
|
|
26770
|
+
if (/^("[^"]*")?\.?$/.test(s)) return "";
|
|
26771
|
+
return userLinePart(s);
|
|
26772
|
+
}
|
|
26773
|
+
function maliciousPackageLine(reason) {
|
|
26774
|
+
if (!reason) return "";
|
|
26775
|
+
const names = [...reason.matchAll(/"([^"]+)"/g)].map((m) => {
|
|
26776
|
+
const spec = m[1];
|
|
26777
|
+
const at = spec.lastIndexOf("@");
|
|
26778
|
+
return at > 0 ? spec.slice(0, at) : spec;
|
|
26779
|
+
});
|
|
26780
|
+
if (names.length === 0) return "";
|
|
26781
|
+
const advisories = [...reason.matchAll(/\b((?:MAL|GHSA|CVE|OSV|PYSEC|RUSTSEC)-[\w-]+)/g)].map(
|
|
26782
|
+
(m) => m[1]
|
|
26783
|
+
);
|
|
26784
|
+
const unique2 = [...new Set(names)];
|
|
26785
|
+
const suffix = advisories.length ? ` (${[...new Set(advisories)].join(", ")})` : "";
|
|
26786
|
+
return userLinePart(
|
|
26787
|
+
unique2.length === 1 ? `${unique2[0]} is a known malicious package${suffix}` : `${unique2.join(", ")} are known malicious packages${suffix}`
|
|
26788
|
+
);
|
|
26789
|
+
}
|
|
26715
26790
|
function buildNegotiationMessage(blockedByLabel, isHumanDecision2, humanReason, recoveryCommand, context) {
|
|
26716
26791
|
if (isHumanDecision2 && context?.redirect && humanReason) {
|
|
26717
26792
|
return `NODE9: The user stopped this action and gave you an instruction.
|
|
@@ -26721,88 +26796,138 @@ INSTRUCTIONS:
|
|
|
26721
26796
|
- Retry the original action only if the instruction says you may.`;
|
|
26722
26797
|
}
|
|
26723
26798
|
if (isHumanDecision2) {
|
|
26724
|
-
return
|
|
26799
|
+
return withUserLine(
|
|
26800
|
+
"Node9: you blocked this action",
|
|
26801
|
+
`NODE9: The human user rejected this action.
|
|
26725
26802
|
REASON: ${humanReason || "No specific reason provided."}
|
|
26726
26803
|
INSTRUCTIONS:
|
|
26727
26804
|
- Do NOT retry this exact command.
|
|
26728
26805
|
- Acknowledge the block to the user and ask if there is an alternative approach.
|
|
26729
|
-
- If you believe this action is critical, explain your reasoning and ask them to run "node9 pause 15m" to proceed
|
|
26806
|
+
- If you believe this action is critical, explain your reasoning and ask them to run "node9 pause 15m" to proceed.`
|
|
26807
|
+
);
|
|
26730
26808
|
}
|
|
26731
26809
|
if (context?.kind === "protected-path") {
|
|
26732
26810
|
const subject = context.path ? `${context.path} is a protected file` : "This file is protected";
|
|
26733
|
-
|
|
26811
|
+
const shown = context.path ? userLineValue(context.path) : "";
|
|
26812
|
+
const line2 = shown ? `Node9 blocked access to ${shown} (protected file)` : "Node9 blocked access to a protected file";
|
|
26813
|
+
return withUserLine(
|
|
26814
|
+
line2,
|
|
26815
|
+
`NODE9: Blocked. ${subject}, and node9 stopped this call to it. The call did not run, so nothing was exposed.
|
|
26734
26816
|
INSTRUCTIONS:
|
|
26735
26817
|
- Do NOT retry, and do NOT reach the file another way (cat, grep, a copy, a script, a redirect).
|
|
26736
26818
|
- If this step needs that file, ask the user to provide what you need or to do the step themselves.
|
|
26737
|
-
- Tell the user node9 protected this file, then ask how to proceed
|
|
26819
|
+
- Tell the user node9 protected this file, then ask how to proceed.`
|
|
26820
|
+
);
|
|
26738
26821
|
}
|
|
26739
26822
|
const label3 = blockedByLabel.toLowerCase();
|
|
26740
26823
|
if (label3.includes("dlp") || label3.includes("secret detected") || label3.includes("credential review")) {
|
|
26741
|
-
return
|
|
26824
|
+
return withUserLine(
|
|
26825
|
+
"Node9 blocked this command: it contains a secret",
|
|
26826
|
+
`NODE9 SECURITY ALERT: A sensitive credential (API key, token, or private key) was found in your tool call arguments.
|
|
26742
26827
|
CRITICAL INSTRUCTION: Do NOT retry this action.
|
|
26743
26828
|
REQUIRED ACTIONS:
|
|
26744
26829
|
1. Remove the hardcoded credential from your command or code.
|
|
26745
26830
|
2. Use an environment variable or a dedicated secrets manager instead.
|
|
26746
26831
|
3. Treat the leaked credential as compromised and rotate it immediately.
|
|
26747
26832
|
Do NOT attempt to bypass this check or pass the credential through another tool.
|
|
26748
|
-
- Tell the user node9 blocked this and why, then ask how to proceed
|
|
26833
|
+
- Tell the user node9 blocked this and why, then ask how to proceed.`
|
|
26834
|
+
);
|
|
26749
26835
|
}
|
|
26750
26836
|
if (label3.includes("package check")) {
|
|
26751
|
-
|
|
26837
|
+
const pkg = maliciousPackageLine(humanReason);
|
|
26838
|
+
return withUserLine(
|
|
26839
|
+
pkg ? `Node9 blocked: ${pkg}` : "Node9 blocked: this package is known to be malicious",
|
|
26840
|
+
`NODE9: Blocked \u2014 ${humanReason || "a package in this command is known to be malicious."}
|
|
26752
26841
|
INSTRUCTIONS:
|
|
26753
26842
|
- Do NOT install this package, and do NOT fetch it another way (a different package manager, a tarball URL, a git URL, a mirror).
|
|
26754
26843
|
- If a dependency is needed, suggest a well-known alternative and let the user choose.
|
|
26755
|
-
- Tell the user node9 blocked this install and name the advisory, then ask how to proceed
|
|
26844
|
+
- Tell the user node9 blocked this install and name the advisory, then ask how to proceed.`
|
|
26845
|
+
);
|
|
26756
26846
|
}
|
|
26757
26847
|
if (label3.includes("sql safety") && label3.includes("delete without where")) {
|
|
26758
|
-
return
|
|
26848
|
+
return withUserLine(
|
|
26849
|
+
blockedLine(context, "DELETE without WHERE would wipe the whole table"),
|
|
26850
|
+
`NODE9: Blocked \u2014 DELETE without WHERE clause would wipe the entire table.
|
|
26759
26851
|
INSTRUCTION: Add a WHERE clause to scope the deletion (e.g. WHERE id = <value>).
|
|
26760
26852
|
Do NOT retry without a WHERE clause.
|
|
26761
|
-
- Tell the user node9 blocked this and why, then ask how to proceed
|
|
26853
|
+
- Tell the user node9 blocked this and why, then ask how to proceed.`
|
|
26854
|
+
);
|
|
26762
26855
|
}
|
|
26763
26856
|
if (label3.includes("sql safety") && label3.includes("update without where")) {
|
|
26764
|
-
return
|
|
26857
|
+
return withUserLine(
|
|
26858
|
+
blockedLine(context, "UPDATE without WHERE would change every row"),
|
|
26859
|
+
`NODE9: Blocked \u2014 UPDATE without WHERE clause would update every row.
|
|
26765
26860
|
INSTRUCTION: Add a WHERE clause to scope the update (e.g. WHERE id = <value>).
|
|
26766
26861
|
Do NOT retry without a WHERE clause.
|
|
26767
|
-
- Tell the user node9 blocked this and why, then ask how to proceed
|
|
26862
|
+
- Tell the user node9 blocked this and why, then ask how to proceed.`
|
|
26863
|
+
);
|
|
26768
26864
|
}
|
|
26769
26865
|
if (label3.includes("dangerous word")) {
|
|
26770
26866
|
const match = blockedByLabel.match(/dangerous word: "([^"]+)"/i);
|
|
26771
26867
|
const word = match?.[1] ?? "a dangerous keyword";
|
|
26772
|
-
return
|
|
26868
|
+
return withUserLine(
|
|
26869
|
+
blockedLine(context, `the command contains ${userLineValue(word)}`),
|
|
26870
|
+
`NODE9: Blocked \u2014 command contains forbidden keyword "${word}".
|
|
26773
26871
|
INSTRUCTION: Do NOT use "${word}". Use a non-destructive alternative.
|
|
26774
26872
|
Do NOT attempt to bypass this with shell tricks or aliases \u2014 it will be blocked again.
|
|
26775
|
-
- Tell the user node9 blocked this and why, then ask how to proceed
|
|
26873
|
+
- Tell the user node9 blocked this and why, then ask how to proceed.`
|
|
26874
|
+
);
|
|
26776
26875
|
}
|
|
26777
26876
|
if (label3.includes("path blocked") || label3.includes("sandbox")) {
|
|
26778
|
-
return
|
|
26877
|
+
return withUserLine(
|
|
26878
|
+
blockedLine(context, "this path is outside the allowed sandbox"),
|
|
26879
|
+
`NODE9: Blocked \u2014 operation targets a path outside the allowed sandbox.
|
|
26779
26880
|
INSTRUCTION: Move your output to an allowed directory such as /tmp/ or the project directory.
|
|
26780
26881
|
Do NOT retry on the same path.
|
|
26781
|
-
- Tell the user node9 blocked this and why, then ask how to proceed
|
|
26882
|
+
- Tell the user node9 blocked this and why, then ask how to proceed.`
|
|
26883
|
+
);
|
|
26782
26884
|
}
|
|
26783
26885
|
if (label3.includes("inline execution")) {
|
|
26784
|
-
return
|
|
26886
|
+
return withUserLine(
|
|
26887
|
+
blockedLine(context, "inline code execution is not allowed"),
|
|
26888
|
+
`NODE9: Blocked \u2014 inline code execution (e.g. bash -c "...") is not allowed.
|
|
26785
26889
|
INSTRUCTION: Use individual tool calls instead of embedding code in a shell string.
|
|
26786
|
-
- Tell the user node9 blocked this and why, then ask how to proceed
|
|
26890
|
+
- Tell the user node9 blocked this and why, then ask how to proceed.`
|
|
26891
|
+
);
|
|
26787
26892
|
}
|
|
26788
26893
|
if (label3.includes("strict mode")) {
|
|
26789
|
-
return
|
|
26790
|
-
|
|
26894
|
+
return withUserLine(
|
|
26895
|
+
"Node9: the Block all level is on, so every action needs your approval",
|
|
26896
|
+
`NODE9: Blocked \u2014 the Block all level is on. All tool calls require explicit human approval.
|
|
26897
|
+
INSTRUCTION: Inform the user this action is pending approval. Wait for them to approve via the dashboard or run "node9 pause".`
|
|
26898
|
+
);
|
|
26791
26899
|
}
|
|
26792
26900
|
if (label3.includes("rule") && label3.includes("default block")) {
|
|
26793
26901
|
const match = blockedByLabel.match(/rule "([^"]+)"/i);
|
|
26794
|
-
const
|
|
26795
|
-
return
|
|
26796
|
-
|
|
26902
|
+
const rule2 = match?.[1] ?? "a policy rule";
|
|
26903
|
+
return withUserLine(
|
|
26904
|
+
blockedLine(context, `${userLineValue(rule2)} is not allowed by policy`),
|
|
26905
|
+
`NODE9: Blocked \u2014 action "${rule2}" is forbidden by security policy.
|
|
26906
|
+
INSTRUCTION: Do NOT use "${rule2}". Find a read-only or non-destructive alternative.
|
|
26797
26907
|
Do NOT attempt to bypass this rule.
|
|
26798
|
-
- Tell the user node9 blocked this and why, then ask how to proceed
|
|
26908
|
+
- Tell the user node9 blocked this and why, then ask how to proceed.`
|
|
26909
|
+
);
|
|
26910
|
+
}
|
|
26911
|
+
const timedOut = label3.includes("approval timeout");
|
|
26912
|
+
const rule = ruleWhat(context?.ruleDescription);
|
|
26913
|
+
let line;
|
|
26914
|
+
if (timedOut) {
|
|
26915
|
+
line = rule ? `Node9 blocked: no one approved this in time (${rule.replace(/ \(([^()]+)\)$/, ", $1")})` : "Node9 blocked: no one approved this in time";
|
|
26916
|
+
} else if (rule) {
|
|
26917
|
+
line = `Node9 blocked: ${rule}`;
|
|
26918
|
+
} else {
|
|
26919
|
+
const why = reasonSentence(humanReason);
|
|
26920
|
+
line = why ? `Node9 blocked: ${why}` : `Node9 blocked this action (${userLinePart(agentFacingLabel(blockedByLabel))})`;
|
|
26799
26921
|
}
|
|
26800
26922
|
const recovery = recoveryCommand ? `
|
|
26801
26923
|
REQUIRED ACTION: Run \`${recoveryCommand}\` first, then retry your original command.` : "\n- Pivot to a non-destructive or read-only alternative.";
|
|
26802
|
-
return
|
|
26924
|
+
return withUserLine(
|
|
26925
|
+
line,
|
|
26926
|
+
`NODE9: Action blocked by security policy [${agentFacingLabel(blockedByLabel)}].
|
|
26803
26927
|
INSTRUCTIONS:
|
|
26804
26928
|
- Do NOT retry this exact command or attempt to bypass the rule.${recovery}
|
|
26805
|
-
- Inform the user which security rule was triggered and ask how to proceed
|
|
26929
|
+
- Inform the user which security rule was triggered and ask how to proceed.`
|
|
26930
|
+
);
|
|
26806
26931
|
}
|
|
26807
26932
|
function buildReviewMessage(blockedByLabel, ruleDescription, reason) {
|
|
26808
26933
|
const why = ruleDescription || (reason && reason !== blockedByLabel ? reason : void 0) || blockedByLabel || "this action needs your review";
|
|
@@ -26817,7 +26942,7 @@ function isHumanDecision(label3, blockedBy, decidedBy) {
|
|
|
26817
26942
|
return l.includes("user") || l.includes("daemon") || l.includes("decision");
|
|
26818
26943
|
}
|
|
26819
26944
|
function agentFacingLabel(label3) {
|
|
26820
|
-
const plain = label3.replace(
|
|
26945
|
+
const plain = label3.replace(PICTOGRAPHS, "").replace(/\bNode9\b/g, "node9").replace(/\s+/g, " ").trim();
|
|
26821
26946
|
return plain || "Security Policy";
|
|
26822
26947
|
}
|
|
26823
26948
|
function asApprovalRequest(description) {
|
|
@@ -26833,11 +26958,20 @@ function asApprovalRequest(description) {
|
|
|
26833
26958
|
}
|
|
26834
26959
|
return description;
|
|
26835
26960
|
}
|
|
26836
|
-
var BLOCKED_BY, DASH_BLOCKED_BY, SHIELD;
|
|
26961
|
+
var USER_LINE_ICON, QUOTE_INSTRUCTION, USER_LINE_PART_MAX, ONE_LINE_INPUT_MAX, PICTOGRAPHS, IS_BLOCKED_BY, IS_BLOCKED, COMMA_BLOCKED_BY, BLOCKED_BY, DASH_BLOCKED_BY, SHIELD;
|
|
26837
26962
|
var init_negotiation = __esm({
|
|
26838
26963
|
"src/policy/negotiation.ts"() {
|
|
26839
26964
|
"use strict";
|
|
26840
26965
|
init_cjs_shims();
|
|
26966
|
+
init_dist();
|
|
26967
|
+
USER_LINE_ICON = "\u{1F6E1}\uFE0F";
|
|
26968
|
+
QUOTE_INSTRUCTION = "Start your reply with the line above, exactly as written, on its own line.";
|
|
26969
|
+
USER_LINE_PART_MAX = 160;
|
|
26970
|
+
ONE_LINE_INPUT_MAX = 1e3;
|
|
26971
|
+
PICTOGRAPHS = /[\p{Extended_Pictographic}\u200D\uFE0F]/gu;
|
|
26972
|
+
IS_BLOCKED_BY = /^(.+?) (?:is|are) blocked by (.+?)\.?$/i;
|
|
26973
|
+
IS_BLOCKED = /^(.+?) (?:is|are) blocked\.?$/i;
|
|
26974
|
+
COMMA_BLOCKED_BY = /^(.+?), blocked by (.+?)\.?$/i;
|
|
26841
26975
|
BLOCKED_BY = " is blocked by ";
|
|
26842
26976
|
DASH_BLOCKED_BY = " \u2014 blocked by ";
|
|
26843
26977
|
SHIELD = " shield";
|
|
@@ -45905,21 +46039,21 @@ function patchConfig(configPath2, patch) {
|
|
|
45905
46039
|
throw err2;
|
|
45906
46040
|
}
|
|
45907
46041
|
}
|
|
45908
|
-
var
|
|
46042
|
+
var import_path86, import_os72, GLOBAL_CONFIG_PATH;
|
|
45909
46043
|
var init_patch = __esm({
|
|
45910
46044
|
"src/config/patch.ts"() {
|
|
45911
46045
|
"use strict";
|
|
45912
46046
|
init_cjs_shims();
|
|
45913
|
-
|
|
45914
|
-
|
|
46047
|
+
import_path86 = __toESM(require("path"));
|
|
46048
|
+
import_os72 = __toESM(require("os"));
|
|
45915
46049
|
init_write();
|
|
45916
|
-
GLOBAL_CONFIG_PATH =
|
|
46050
|
+
GLOBAL_CONFIG_PATH = import_path86.default.join(import_os72.default.homedir(), ".node9", "config.json");
|
|
45917
46051
|
}
|
|
45918
46052
|
});
|
|
45919
46053
|
|
|
45920
46054
|
// src/auth/egress-config.ts
|
|
45921
46055
|
function egressConfigPath() {
|
|
45922
|
-
return
|
|
46056
|
+
return import_path87.default.join(import_os73.default.homedir(), ".node9", "config.json");
|
|
45923
46057
|
}
|
|
45924
46058
|
function readEgressRawConfig() {
|
|
45925
46059
|
return readConfigFileLegacy(egressConfigPath());
|
|
@@ -45979,14 +46113,14 @@ function normalizeEgressHost(host2) {
|
|
|
45979
46113
|
function isValidEgressHost(host2) {
|
|
45980
46114
|
return EGRESS_HOST_RE.test(host2);
|
|
45981
46115
|
}
|
|
45982
|
-
var
|
|
46116
|
+
var import_os73, import_path87, DEFAULT_EGRESS, EGRESS_HOST_RE;
|
|
45983
46117
|
var init_egress_config = __esm({
|
|
45984
46118
|
"src/auth/egress-config.ts"() {
|
|
45985
46119
|
"use strict";
|
|
45986
46120
|
init_cjs_shims();
|
|
45987
46121
|
init_write();
|
|
45988
|
-
|
|
45989
|
-
|
|
46122
|
+
import_os73 = __toESM(require("os"));
|
|
46123
|
+
import_path87 = __toESM(require("path"));
|
|
45990
46124
|
init_dist();
|
|
45991
46125
|
DEFAULT_EGRESS = {
|
|
45992
46126
|
enabled: false,
|
|
@@ -46014,27 +46148,27 @@ __export(local_setup_exports, {
|
|
|
46014
46148
|
runLocalSetup: () => runLocalSetup
|
|
46015
46149
|
});
|
|
46016
46150
|
function configPath() {
|
|
46017
|
-
return
|
|
46151
|
+
return import_path88.default.join(import_os74.default.homedir(), ".node9", "config.json");
|
|
46018
46152
|
}
|
|
46019
46153
|
function combined(values) {
|
|
46020
46154
|
return values.every(Boolean) ? "on" : values.some(Boolean) ? "partial" : "off";
|
|
46021
46155
|
}
|
|
46022
46156
|
function readLocalState(opts = {}) {
|
|
46023
46157
|
const file2 = configPath();
|
|
46024
|
-
if (
|
|
46158
|
+
if (import_fs88.default.existsSync(file2) && !opts.replaceConfig) {
|
|
46025
46159
|
let raw;
|
|
46026
46160
|
try {
|
|
46027
|
-
raw = JSON.parse(
|
|
46161
|
+
raw = JSON.parse(import_fs88.default.readFileSync(file2, "utf8"));
|
|
46028
46162
|
} catch {
|
|
46029
46163
|
raw = void 0;
|
|
46030
46164
|
}
|
|
46031
46165
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) throw invalidConfig();
|
|
46032
46166
|
}
|
|
46033
|
-
const config = getConfig(
|
|
46167
|
+
const config = getConfig(import_path88.default.join(import_os74.default.homedir(), ".node9"));
|
|
46034
46168
|
const active = readActiveShields();
|
|
46035
46169
|
const installed = isDaemonServiceInstalled();
|
|
46036
46170
|
return {
|
|
46037
|
-
fresh: !
|
|
46171
|
+
fresh: !import_fs88.default.existsSync(file2),
|
|
46038
46172
|
managed: config.policySource === "workspace",
|
|
46039
46173
|
shields: combined(DEFAULT_SHIELDS.map((s) => active.includes(s))),
|
|
46040
46174
|
dlp: combined([config.policy.dlp.enabled, config.policy.dlp.pii !== "off"]),
|
|
@@ -46082,7 +46216,7 @@ function diffChoices(state, selected, partial = {}) {
|
|
|
46082
46216
|
}
|
|
46083
46217
|
function setAutostart(enabled) {
|
|
46084
46218
|
const file2 = configPath();
|
|
46085
|
-
const raw = JSON.parse(
|
|
46219
|
+
const raw = JSON.parse(import_fs88.default.readFileSync(file2, "utf8"));
|
|
46086
46220
|
if (raw.settings?.autoStartDaemon === enabled) return;
|
|
46087
46221
|
raw.settings = { ...raw.settings, autoStartDaemon: enabled };
|
|
46088
46222
|
atomicWriteSync(file2, JSON.stringify(raw, null, 2) + "\n", { mode: 384 });
|
|
@@ -46249,14 +46383,14 @@ async function runLocalSetup(opts) {
|
|
|
46249
46383
|
if (interactive && !state.managed && !opts.skipSetup) await askTelemetry(agents, firstInstall);
|
|
46250
46384
|
return collectSummary(applied);
|
|
46251
46385
|
}
|
|
46252
|
-
var
|
|
46386
|
+
var import_fs88, import_os74, import_path88, DEFAULT_SHIELDS;
|
|
46253
46387
|
var init_local_setup = __esm({
|
|
46254
46388
|
"src/cli/local-setup.ts"() {
|
|
46255
46389
|
"use strict";
|
|
46256
46390
|
init_cjs_shims();
|
|
46257
|
-
|
|
46258
|
-
|
|
46259
|
-
|
|
46391
|
+
import_fs88 = __toESM(require("fs"));
|
|
46392
|
+
import_os74 = __toESM(require("os"));
|
|
46393
|
+
import_path88 = __toESM(require("path"));
|
|
46260
46394
|
init_config();
|
|
46261
46395
|
init_patch();
|
|
46262
46396
|
init_keyed_guard();
|
|
@@ -46319,8 +46453,8 @@ async function askTelemetry(agents, firstInstall) {
|
|
|
46319
46453
|
}
|
|
46320
46454
|
}
|
|
46321
46455
|
function ensureConfig(mode, force = false) {
|
|
46322
|
-
const file2 =
|
|
46323
|
-
const firstInstall = !
|
|
46456
|
+
const file2 = import_path89.default.join(import_os75.default.homedir(), ".node9", "config.json");
|
|
46457
|
+
const firstInstall = !import_fs89.default.existsSync(file2);
|
|
46324
46458
|
if (firstInstall || force) {
|
|
46325
46459
|
const body = legacyToV2(
|
|
46326
46460
|
mode !== void 0 && mode !== DEFAULT_CONFIG.settings.mode ? { settings: { mode } } : {}
|
|
@@ -46372,16 +46506,16 @@ function registerInitCommand(program2) {
|
|
|
46372
46506
|
}
|
|
46373
46507
|
);
|
|
46374
46508
|
}
|
|
46375
|
-
var
|
|
46509
|
+
var import_fs89, import_path89, import_os75, import_https6, TELEMETRY_PROMPT;
|
|
46376
46510
|
var init_init = __esm({
|
|
46377
46511
|
"src/cli/commands/init.ts"() {
|
|
46378
46512
|
"use strict";
|
|
46379
46513
|
init_cjs_shims();
|
|
46380
46514
|
init_v2();
|
|
46381
46515
|
init_write();
|
|
46382
|
-
|
|
46383
|
-
|
|
46384
|
-
|
|
46516
|
+
import_fs89 = __toESM(require("fs"));
|
|
46517
|
+
import_path89 = __toESM(require("path"));
|
|
46518
|
+
import_os75 = __toESM(require("os"));
|
|
46385
46519
|
import_https6 = __toESM(require("https"));
|
|
46386
46520
|
init_config();
|
|
46387
46521
|
init_setup();
|
|
@@ -47508,14 +47642,14 @@ var require_util = __commonJS({
|
|
|
47508
47642
|
}
|
|
47509
47643
|
const port = url.port != null ? url.port : url.protocol === "https:" ? 443 : 80;
|
|
47510
47644
|
let origin = url.origin != null ? url.origin : `${url.protocol || ""}//${url.hostname || ""}:${port}`;
|
|
47511
|
-
let
|
|
47645
|
+
let path110 = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`;
|
|
47512
47646
|
if (origin[origin.length - 1] === "/") {
|
|
47513
47647
|
origin = origin.slice(0, origin.length - 1);
|
|
47514
47648
|
}
|
|
47515
|
-
if (
|
|
47516
|
-
|
|
47649
|
+
if (path110 && path110[0] !== "/") {
|
|
47650
|
+
path110 = `/${path110}`;
|
|
47517
47651
|
}
|
|
47518
|
-
return new URL(`${origin}${
|
|
47652
|
+
return new URL(`${origin}${path110}`);
|
|
47519
47653
|
}
|
|
47520
47654
|
if (!isHttpOrHttpsPrefixed(url.origin || url.protocol)) {
|
|
47521
47655
|
throw new InvalidArgumentError("Invalid URL protocol: the URL must start with `http:` or `https:`.");
|
|
@@ -48338,9 +48472,9 @@ var require_diagnostics = __commonJS({
|
|
|
48338
48472
|
"undici:client:sendHeaders",
|
|
48339
48473
|
(evt) => {
|
|
48340
48474
|
const {
|
|
48341
|
-
request: { method, path:
|
|
48475
|
+
request: { method, path: path110, origin }
|
|
48342
48476
|
} = evt;
|
|
48343
|
-
debugLog2("sending request to %s %s%s", method, origin,
|
|
48477
|
+
debugLog2("sending request to %s %s%s", method, origin, path110);
|
|
48344
48478
|
}
|
|
48345
48479
|
);
|
|
48346
48480
|
}
|
|
@@ -48358,14 +48492,14 @@ var require_diagnostics = __commonJS({
|
|
|
48358
48492
|
"undici:request:headers",
|
|
48359
48493
|
(evt) => {
|
|
48360
48494
|
const {
|
|
48361
|
-
request: { method, path:
|
|
48495
|
+
request: { method, path: path110, origin },
|
|
48362
48496
|
response: { statusCode }
|
|
48363
48497
|
} = evt;
|
|
48364
48498
|
debugLog2(
|
|
48365
48499
|
"received response to %s %s%s - HTTP %d",
|
|
48366
48500
|
method,
|
|
48367
48501
|
origin,
|
|
48368
|
-
|
|
48502
|
+
path110,
|
|
48369
48503
|
statusCode
|
|
48370
48504
|
);
|
|
48371
48505
|
}
|
|
@@ -48374,23 +48508,23 @@ var require_diagnostics = __commonJS({
|
|
|
48374
48508
|
"undici:request:trailers",
|
|
48375
48509
|
(evt) => {
|
|
48376
48510
|
const {
|
|
48377
|
-
request: { method, path:
|
|
48511
|
+
request: { method, path: path110, origin }
|
|
48378
48512
|
} = evt;
|
|
48379
|
-
debugLog2("trailers received from %s %s%s", method, origin,
|
|
48513
|
+
debugLog2("trailers received from %s %s%s", method, origin, path110);
|
|
48380
48514
|
}
|
|
48381
48515
|
);
|
|
48382
48516
|
diagnosticsChannel.subscribe(
|
|
48383
48517
|
"undici:request:error",
|
|
48384
48518
|
(evt) => {
|
|
48385
48519
|
const {
|
|
48386
|
-
request: { method, path:
|
|
48520
|
+
request: { method, path: path110, origin },
|
|
48387
48521
|
error
|
|
48388
48522
|
} = evt;
|
|
48389
48523
|
debugLog2(
|
|
48390
48524
|
"request to %s %s%s errored - %s",
|
|
48391
48525
|
method,
|
|
48392
48526
|
origin,
|
|
48393
|
-
|
|
48527
|
+
path110,
|
|
48394
48528
|
error.message
|
|
48395
48529
|
);
|
|
48396
48530
|
}
|
|
@@ -48506,7 +48640,7 @@ var require_request = __commonJS({
|
|
|
48506
48640
|
var kHandler = /* @__PURE__ */ Symbol("handler");
|
|
48507
48641
|
var Request = class {
|
|
48508
48642
|
constructor(origin, {
|
|
48509
|
-
path:
|
|
48643
|
+
path: path110,
|
|
48510
48644
|
method,
|
|
48511
48645
|
body,
|
|
48512
48646
|
headers,
|
|
@@ -48523,11 +48657,11 @@ var require_request = __commonJS({
|
|
|
48523
48657
|
maxRedirections,
|
|
48524
48658
|
typeOfService
|
|
48525
48659
|
}, handler) {
|
|
48526
|
-
if (typeof
|
|
48660
|
+
if (typeof path110 !== "string") {
|
|
48527
48661
|
throw new InvalidArgumentError("path must be a string");
|
|
48528
|
-
} else if (
|
|
48662
|
+
} else if (path110[0] !== "/" && !(path110.startsWith("http://") || path110.startsWith("https://")) && method !== "CONNECT") {
|
|
48529
48663
|
throw new InvalidArgumentError("path must be an absolute URL or start with a slash");
|
|
48530
|
-
} else if (invalidPathRegex.test(
|
|
48664
|
+
} else if (invalidPathRegex.test(path110)) {
|
|
48531
48665
|
throw new InvalidArgumentError("invalid request path");
|
|
48532
48666
|
}
|
|
48533
48667
|
if (typeof method !== "string") {
|
|
@@ -48602,7 +48736,7 @@ var require_request = __commonJS({
|
|
|
48602
48736
|
this.completed = false;
|
|
48603
48737
|
this.aborted = false;
|
|
48604
48738
|
this.upgrade = upgrade || null;
|
|
48605
|
-
this.path = query ? serializePathWithQuery(
|
|
48739
|
+
this.path = query ? serializePathWithQuery(path110, query) : path110;
|
|
48606
48740
|
this.origin = origin;
|
|
48607
48741
|
this.protocol = getProtocolFromUrlString(origin);
|
|
48608
48742
|
this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent;
|
|
@@ -53849,7 +53983,7 @@ var require_client_h1 = __commonJS({
|
|
|
53849
53983
|
return method !== "GET" && method !== "HEAD" && method !== "OPTIONS" && method !== "TRACE" && method !== "CONNECT";
|
|
53850
53984
|
}
|
|
53851
53985
|
function writeH1(client, request2) {
|
|
53852
|
-
const { method, path:
|
|
53986
|
+
const { method, path: path110, host: host2, upgrade, blocking, reset } = request2;
|
|
53853
53987
|
let { body, headers, contentLength } = request2;
|
|
53854
53988
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH" || method === "QUERY" || method === "PROPFIND" || method === "PROPPATCH";
|
|
53855
53989
|
if (util.isFormDataLike(body)) {
|
|
@@ -53927,7 +54061,7 @@ var require_client_h1 = __commonJS({
|
|
|
53927
54061
|
if (socket.setTypeOfService) {
|
|
53928
54062
|
socket.setTypeOfService(request2.typeOfService);
|
|
53929
54063
|
}
|
|
53930
|
-
let header = `${method} ${
|
|
54064
|
+
let header = `${method} ${path110} HTTP/1.1\r
|
|
53931
54065
|
`;
|
|
53932
54066
|
if (typeof host2 === "string") {
|
|
53933
54067
|
header += `host: ${host2}\r
|
|
@@ -54605,7 +54739,7 @@ var require_client_h2 = __commonJS({
|
|
|
54605
54739
|
const headersTimeout = request2.headersTimeout ?? client[kHeadersTimeout];
|
|
54606
54740
|
const bodyTimeout = request2.bodyTimeout ?? client[kBodyTimeout];
|
|
54607
54741
|
const session = client[kHTTP2Session];
|
|
54608
|
-
const { method, path:
|
|
54742
|
+
const { method, path: path110, host: host2, upgrade, expectContinue, signal, protocol, headers: reqHeaders } = request2;
|
|
54609
54743
|
let { body } = request2;
|
|
54610
54744
|
if (upgrade != null && upgrade !== "websocket") {
|
|
54611
54745
|
util.errorRequest(client, request2, new InvalidArgumentError(`Custom upgrade "${upgrade}" not supported over HTTP/2`));
|
|
@@ -54674,7 +54808,7 @@ var require_client_h2 = __commonJS({
|
|
|
54674
54808
|
}
|
|
54675
54809
|
headers[HTTP2_HEADER_METHOD] = "CONNECT";
|
|
54676
54810
|
headers[HTTP2_HEADER_PROTOCOL] = "websocket";
|
|
54677
|
-
headers[HTTP2_HEADER_PATH] =
|
|
54811
|
+
headers[HTTP2_HEADER_PATH] = path110;
|
|
54678
54812
|
if (protocol === "ws:" || protocol === "wss:") {
|
|
54679
54813
|
headers[HTTP2_HEADER_SCHEME] = protocol === "ws:" ? "http" : "https";
|
|
54680
54814
|
} else {
|
|
@@ -54726,7 +54860,7 @@ var require_client_h2 = __commonJS({
|
|
|
54726
54860
|
stream.setTimeout(headersTimeout);
|
|
54727
54861
|
return true;
|
|
54728
54862
|
}
|
|
54729
|
-
headers[HTTP2_HEADER_PATH] =
|
|
54863
|
+
headers[HTTP2_HEADER_PATH] = path110;
|
|
54730
54864
|
headers[HTTP2_HEADER_SCHEME] = protocol === "http:" ? "http" : "https";
|
|
54731
54865
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
|
|
54732
54866
|
if (body && typeof body.read === "function") {
|
|
@@ -57093,10 +57227,10 @@ var require_proxy_agent = __commonJS({
|
|
|
57093
57227
|
};
|
|
57094
57228
|
const {
|
|
57095
57229
|
origin,
|
|
57096
|
-
path:
|
|
57230
|
+
path: path110 = "/",
|
|
57097
57231
|
headers = {}
|
|
57098
57232
|
} = opts;
|
|
57099
|
-
opts.path = origin +
|
|
57233
|
+
opts.path = origin + path110;
|
|
57100
57234
|
if (!("host" in headers) && !("Host" in headers)) {
|
|
57101
57235
|
const { host: host2 } = new URL(origin);
|
|
57102
57236
|
headers.host = host2;
|
|
@@ -59271,20 +59405,20 @@ var require_mock_utils = __commonJS({
|
|
|
59271
59405
|
}
|
|
59272
59406
|
return normalizedQp;
|
|
59273
59407
|
}
|
|
59274
|
-
function safeUrl(
|
|
59275
|
-
if (typeof
|
|
59276
|
-
return
|
|
59408
|
+
function safeUrl(path110) {
|
|
59409
|
+
if (typeof path110 !== "string") {
|
|
59410
|
+
return path110;
|
|
59277
59411
|
}
|
|
59278
|
-
const pathSegments =
|
|
59412
|
+
const pathSegments = path110.split("?", 3);
|
|
59279
59413
|
if (pathSegments.length !== 2) {
|
|
59280
|
-
return
|
|
59414
|
+
return path110;
|
|
59281
59415
|
}
|
|
59282
59416
|
const qp = new URLSearchParams(pathSegments.pop());
|
|
59283
59417
|
qp.sort();
|
|
59284
59418
|
return [...pathSegments, qp.toString()].join("?");
|
|
59285
59419
|
}
|
|
59286
|
-
function matchKey(mockDispatch2, { path:
|
|
59287
|
-
const pathMatch = matchValue(mockDispatch2.path,
|
|
59420
|
+
function matchKey(mockDispatch2, { path: path110, method, body, headers }) {
|
|
59421
|
+
const pathMatch = matchValue(mockDispatch2.path, path110);
|
|
59288
59422
|
const methodMatch = matchValue(mockDispatch2.method, method);
|
|
59289
59423
|
const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body) : true;
|
|
59290
59424
|
const headersMatch = matchHeaders(mockDispatch2, headers);
|
|
@@ -59309,8 +59443,8 @@ var require_mock_utils = __commonJS({
|
|
|
59309
59443
|
const basePath = key.query ? serializePathWithQuery(key.path, key.query) : key.path;
|
|
59310
59444
|
const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath;
|
|
59311
59445
|
const resolvedPathWithoutTrailingSlash = removeTrailingSlash(resolvedPath);
|
|
59312
|
-
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path:
|
|
59313
|
-
return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(
|
|
59446
|
+
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path110, ignoreTrailingSlash }) => {
|
|
59447
|
+
return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(path110)), resolvedPathWithoutTrailingSlash) : matchValue(safeUrl(path110), resolvedPath);
|
|
59314
59448
|
});
|
|
59315
59449
|
if (matchedMockDispatches.length === 0) {
|
|
59316
59450
|
throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`);
|
|
@@ -59349,19 +59483,19 @@ var require_mock_utils = __commonJS({
|
|
|
59349
59483
|
mockDispatches.splice(index, 1);
|
|
59350
59484
|
}
|
|
59351
59485
|
}
|
|
59352
|
-
function removeTrailingSlash(
|
|
59353
|
-
while (
|
|
59354
|
-
|
|
59486
|
+
function removeTrailingSlash(path110) {
|
|
59487
|
+
while (path110.endsWith("/")) {
|
|
59488
|
+
path110 = path110.slice(0, -1);
|
|
59355
59489
|
}
|
|
59356
|
-
if (
|
|
59357
|
-
|
|
59490
|
+
if (path110.length === 0) {
|
|
59491
|
+
path110 = "/";
|
|
59358
59492
|
}
|
|
59359
|
-
return
|
|
59493
|
+
return path110;
|
|
59360
59494
|
}
|
|
59361
59495
|
function buildKey(opts) {
|
|
59362
|
-
const { path:
|
|
59496
|
+
const { path: path110, method, body, headers, query } = opts;
|
|
59363
59497
|
return {
|
|
59364
|
-
path:
|
|
59498
|
+
path: path110,
|
|
59365
59499
|
method,
|
|
59366
59500
|
body,
|
|
59367
59501
|
headers,
|
|
@@ -60056,10 +60190,10 @@ var require_pending_interceptors_formatter = __commonJS({
|
|
|
60056
60190
|
}
|
|
60057
60191
|
format(pendingInterceptors) {
|
|
60058
60192
|
const withPrettyHeaders = pendingInterceptors.map(
|
|
60059
|
-
({ method, path:
|
|
60193
|
+
({ method, path: path110, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
|
|
60060
60194
|
Method: method,
|
|
60061
60195
|
Origin: origin,
|
|
60062
|
-
Path:
|
|
60196
|
+
Path: path110,
|
|
60063
60197
|
"Status code": statusCode,
|
|
60064
60198
|
Persistent: persist ? PERSISTENT : NOT_PERSISTENT,
|
|
60065
60199
|
Invocations: timesInvoked,
|
|
@@ -60142,9 +60276,9 @@ var require_mock_agent = __commonJS({
|
|
|
60142
60276
|
const acceptNonStandardSearchParameters = this[kMockAgentAcceptsNonStandardSearchParameters];
|
|
60143
60277
|
const dispatchOpts = { ...opts };
|
|
60144
60278
|
if (acceptNonStandardSearchParameters && dispatchOpts.path) {
|
|
60145
|
-
const [
|
|
60279
|
+
const [path110, searchParams] = dispatchOpts.path.split("?");
|
|
60146
60280
|
const normalizedSearchParams = normalizeSearchParams(searchParams, acceptNonStandardSearchParameters);
|
|
60147
|
-
dispatchOpts.path = `${
|
|
60281
|
+
dispatchOpts.path = `${path110}?${normalizedSearchParams}`;
|
|
60148
60282
|
}
|
|
60149
60283
|
return this[kAgent].dispatch(dispatchOpts, handler);
|
|
60150
60284
|
}
|
|
@@ -60547,12 +60681,12 @@ var require_snapshot_recorder = __commonJS({
|
|
|
60547
60681
|
* @return {Promise<void>} - Resolves when snapshots are loaded
|
|
60548
60682
|
*/
|
|
60549
60683
|
async loadSnapshots(filePath) {
|
|
60550
|
-
const
|
|
60551
|
-
if (!
|
|
60684
|
+
const path110 = filePath || this.#snapshotPath;
|
|
60685
|
+
if (!path110) {
|
|
60552
60686
|
throw new InvalidArgumentError("Snapshot path is required");
|
|
60553
60687
|
}
|
|
60554
60688
|
try {
|
|
60555
|
-
const data = await readFile(resolve2(
|
|
60689
|
+
const data = await readFile(resolve2(path110), "utf8");
|
|
60556
60690
|
const parsed = JSON.parse(data);
|
|
60557
60691
|
if (Array.isArray(parsed)) {
|
|
60558
60692
|
this.#snapshots.clear();
|
|
@@ -60566,7 +60700,7 @@ var require_snapshot_recorder = __commonJS({
|
|
|
60566
60700
|
if (error.code === "ENOENT") {
|
|
60567
60701
|
this.#snapshots.clear();
|
|
60568
60702
|
} else {
|
|
60569
|
-
throw new UndiciError(`Failed to load snapshots from ${
|
|
60703
|
+
throw new UndiciError(`Failed to load snapshots from ${path110}`, { cause: error });
|
|
60570
60704
|
}
|
|
60571
60705
|
}
|
|
60572
60706
|
}
|
|
@@ -60577,11 +60711,11 @@ var require_snapshot_recorder = __commonJS({
|
|
|
60577
60711
|
* @returns {Promise<void>} - Resolves when snapshots are saved
|
|
60578
60712
|
*/
|
|
60579
60713
|
async saveSnapshots(filePath) {
|
|
60580
|
-
const
|
|
60581
|
-
if (!
|
|
60714
|
+
const path110 = filePath || this.#snapshotPath;
|
|
60715
|
+
if (!path110) {
|
|
60582
60716
|
throw new InvalidArgumentError("Snapshot path is required");
|
|
60583
60717
|
}
|
|
60584
|
-
const resolvedPath = resolve2(
|
|
60718
|
+
const resolvedPath = resolve2(path110);
|
|
60585
60719
|
await mkdir(dirname3(resolvedPath), { recursive: true });
|
|
60586
60720
|
const data = Array.from(this.#snapshots.entries()).map(([hash2, snapshot]) => ({
|
|
60587
60721
|
hash: hash2,
|
|
@@ -61222,15 +61356,15 @@ var require_redirect_handler = __commonJS({
|
|
|
61222
61356
|
}
|
|
61223
61357
|
this.history[kRedirectCacheControl].push(headers["cache-control"]);
|
|
61224
61358
|
const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin)));
|
|
61225
|
-
const
|
|
61226
|
-
const redirectUrlString = `${origin}${
|
|
61359
|
+
const path110 = search ? `${pathname}${search}` : pathname;
|
|
61360
|
+
const redirectUrlString = `${origin}${path110}`;
|
|
61227
61361
|
for (const historyUrl of this.history) {
|
|
61228
61362
|
if (historyUrl.toString() === redirectUrlString) {
|
|
61229
61363
|
throw new InvalidArgumentError(`Redirect loop detected. Cannot redirect to ${origin}. This typically happens when using a Client or Pool with cross-origin redirects. Use an Agent for cross-origin redirects.`);
|
|
61230
61364
|
}
|
|
61231
61365
|
}
|
|
61232
61366
|
this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin);
|
|
61233
|
-
this.opts.path =
|
|
61367
|
+
this.opts.path = path110;
|
|
61234
61368
|
this.opts.origin = origin;
|
|
61235
61369
|
this.opts.query = null;
|
|
61236
61370
|
}
|
|
@@ -63006,10 +63140,10 @@ var require_cache_handler = __commonJS({
|
|
|
63006
63140
|
}
|
|
63007
63141
|
return locationUrl.pathname + locationUrl.search;
|
|
63008
63142
|
}
|
|
63009
|
-
function deleteCachedUri(store, cacheKey,
|
|
63143
|
+
function deleteCachedUri(store, cacheKey, path110) {
|
|
63010
63144
|
deleteCachedValue(store, {
|
|
63011
63145
|
...cacheKey,
|
|
63012
|
-
path:
|
|
63146
|
+
path: path110
|
|
63013
63147
|
});
|
|
63014
63148
|
for (let i = 0; i < util.safeHTTPMethods.length; i++) {
|
|
63015
63149
|
const method = util.safeHTTPMethods[i];
|
|
@@ -63017,7 +63151,7 @@ var require_cache_handler = __commonJS({
|
|
|
63017
63151
|
deleteCachedValue(store, {
|
|
63018
63152
|
...cacheKey,
|
|
63019
63153
|
method,
|
|
63020
|
-
path:
|
|
63154
|
+
path: path110
|
|
63021
63155
|
});
|
|
63022
63156
|
}
|
|
63023
63157
|
}
|
|
@@ -63028,9 +63162,9 @@ var require_cache_handler = __commonJS({
|
|
|
63028
63162
|
}
|
|
63029
63163
|
const values = Array.isArray(headerValue) ? headerValue : [headerValue];
|
|
63030
63164
|
for (let i = 0; i < values.length; i++) {
|
|
63031
|
-
const
|
|
63032
|
-
if (
|
|
63033
|
-
deleteCachedUri(store, cacheKey,
|
|
63165
|
+
const path110 = getSameOriginPath(cacheKey, values[i]);
|
|
63166
|
+
if (path110 !== void 0) {
|
|
63167
|
+
deleteCachedUri(store, cacheKey, path110);
|
|
63034
63168
|
}
|
|
63035
63169
|
}
|
|
63036
63170
|
}
|
|
@@ -68253,11 +68387,11 @@ var require_fetch = __commonJS({
|
|
|
68253
68387
|
function dispatch({ body }) {
|
|
68254
68388
|
const url = requestCurrentURL(request2);
|
|
68255
68389
|
const agent = fetchParams.controller.dispatcher;
|
|
68256
|
-
const
|
|
68390
|
+
const path110 = url.pathname + url.search;
|
|
68257
68391
|
const hasTrailingQuestionMark = url.search.length === 0 && url.href[url.href.length - url.hash.length - 1] === "?";
|
|
68258
68392
|
return new Promise((resolve2, reject) => agent.dispatch(
|
|
68259
68393
|
{
|
|
68260
|
-
path: hasTrailingQuestionMark ? `${
|
|
68394
|
+
path: hasTrailingQuestionMark ? `${path110}?` : path110,
|
|
68261
68395
|
origin: url.origin,
|
|
68262
68396
|
method: request2.method,
|
|
68263
68397
|
body: agent.isMockActive ? request2.body && (request2.body.source || request2.body.stream) : body,
|
|
@@ -69209,9 +69343,9 @@ var require_util4 = __commonJS({
|
|
|
69209
69343
|
}
|
|
69210
69344
|
}
|
|
69211
69345
|
}
|
|
69212
|
-
function validateCookiePath(
|
|
69213
|
-
for (let i = 0; i <
|
|
69214
|
-
const code2 =
|
|
69346
|
+
function validateCookiePath(path110) {
|
|
69347
|
+
for (let i = 0; i < path110.length; ++i) {
|
|
69348
|
+
const code2 = path110.charCodeAt(i);
|
|
69215
69349
|
if (code2 < 32 || // exclude CTLs (0-31)
|
|
69216
69350
|
code2 > 126 || // exclude DEL and non-ascii
|
|
69217
69351
|
code2 === 59) {
|
|
@@ -72664,11 +72798,11 @@ var require_undici = __commonJS({
|
|
|
72664
72798
|
if (typeof opts.path !== "string") {
|
|
72665
72799
|
throw new InvalidArgumentError("invalid opts.path");
|
|
72666
72800
|
}
|
|
72667
|
-
let
|
|
72801
|
+
let path110 = opts.path;
|
|
72668
72802
|
if (!opts.path.startsWith("/")) {
|
|
72669
|
-
|
|
72803
|
+
path110 = `/${path110}`;
|
|
72670
72804
|
}
|
|
72671
|
-
url = new URL(util.parseOrigin(url).origin +
|
|
72805
|
+
url = new URL(util.parseOrigin(url).origin + path110);
|
|
72672
72806
|
} else {
|
|
72673
72807
|
if (!opts) {
|
|
72674
72808
|
opts = typeof url === "object" ? url : {};
|
|
@@ -72790,10 +72924,10 @@ function readFirstRunEnv() {
|
|
|
72790
72924
|
stdinTTY: !!process.stdin.isTTY,
|
|
72791
72925
|
stdoutTTY: !!process.stdout.isTTY,
|
|
72792
72926
|
ci: isCI() || process.env.NODE9_NONINTERACTIVE === "1",
|
|
72793
|
-
hasConfig:
|
|
72927
|
+
hasConfig: import_fs103.default.existsSync(import_path102.default.join(import_os83.default.homedir(), ".node9/config.json")),
|
|
72794
72928
|
// Any stored profile means this is not a never-configured machine. Treat
|
|
72795
72929
|
// malformed credential files conservatively and leave repair to explicit setup.
|
|
72796
|
-
hasCredentials: !!getCredentials() ||
|
|
72930
|
+
hasCredentials: !!getCredentials() || import_fs103.default.existsSync(import_path102.default.join(import_os83.default.homedir(), ".node9/credentials.json"))
|
|
72797
72931
|
};
|
|
72798
72932
|
}
|
|
72799
72933
|
function shouldOfferFirstRun(env) {
|
|
@@ -72898,14 +73032,14 @@ async function runSetupWizard(opts) {
|
|
|
72898
73032
|
process.exitCode = 130;
|
|
72899
73033
|
}
|
|
72900
73034
|
}
|
|
72901
|
-
var
|
|
73035
|
+
var import_fs103, import_os83, import_path102;
|
|
72902
73036
|
var init_first_run = __esm({
|
|
72903
73037
|
"src/cli/first-run.ts"() {
|
|
72904
73038
|
"use strict";
|
|
72905
73039
|
init_cjs_shims();
|
|
72906
|
-
|
|
72907
|
-
|
|
72908
|
-
|
|
73040
|
+
import_fs103 = __toESM(require("fs"));
|
|
73041
|
+
import_os83 = __toESM(require("os"));
|
|
73042
|
+
import_path102 = __toESM(require("path"));
|
|
72909
73043
|
init_config();
|
|
72910
73044
|
init_agent_wiring();
|
|
72911
73045
|
init_browser_login();
|
|
@@ -72951,20 +73085,20 @@ function getModelContextLimit(model) {
|
|
|
72951
73085
|
return 2e5;
|
|
72952
73086
|
}
|
|
72953
73087
|
function readSessionUsage() {
|
|
72954
|
-
const projectsDir =
|
|
72955
|
-
if (!
|
|
73088
|
+
const projectsDir = import_path103.default.join(import_os84.default.homedir(), ".claude", "projects");
|
|
73089
|
+
if (!import_fs104.default.existsSync(projectsDir)) return null;
|
|
72956
73090
|
let latestFile = null;
|
|
72957
73091
|
let latestMtime = 0;
|
|
72958
73092
|
try {
|
|
72959
|
-
for (const dir2 of
|
|
72960
|
-
const dirPath =
|
|
73093
|
+
for (const dir2 of import_fs104.default.readdirSync(projectsDir)) {
|
|
73094
|
+
const dirPath = import_path103.default.join(projectsDir, dir2);
|
|
72961
73095
|
try {
|
|
72962
|
-
if (!
|
|
72963
|
-
for (const file2 of
|
|
73096
|
+
if (!import_fs104.default.statSync(dirPath).isDirectory()) continue;
|
|
73097
|
+
for (const file2 of import_fs104.default.readdirSync(dirPath)) {
|
|
72964
73098
|
if (!file2.endsWith(".jsonl") || file2.startsWith("agent-")) continue;
|
|
72965
|
-
const filePath =
|
|
73099
|
+
const filePath = import_path103.default.join(dirPath, file2);
|
|
72966
73100
|
try {
|
|
72967
|
-
const mtime =
|
|
73101
|
+
const mtime = import_fs104.default.statSync(filePath).mtimeMs;
|
|
72968
73102
|
if (mtime > latestMtime) {
|
|
72969
73103
|
latestMtime = mtime;
|
|
72970
73104
|
latestFile = filePath;
|
|
@@ -72979,7 +73113,7 @@ function readSessionUsage() {
|
|
|
72979
73113
|
}
|
|
72980
73114
|
if (!latestFile) return null;
|
|
72981
73115
|
try {
|
|
72982
|
-
const lines =
|
|
73116
|
+
const lines = import_fs104.default.readFileSync(latestFile, "utf-8").split("\n");
|
|
72983
73117
|
let lastModel = "";
|
|
72984
73118
|
let lastInput = 0;
|
|
72985
73119
|
let lastOutput = 0;
|
|
@@ -73040,7 +73174,7 @@ function formatBase(activity) {
|
|
|
73040
73174
|
const time = new Date(activity.ts).toLocaleTimeString([], { hour12: false });
|
|
73041
73175
|
const icon = getIcon(activity.tool);
|
|
73042
73176
|
const toolName = activity.tool.slice(0, 16).padEnd(16);
|
|
73043
|
-
const argsStr = JSON.stringify(activity.args ?? {}).replace(/\s+/g, " ").replaceAll(
|
|
73177
|
+
const argsStr = JSON.stringify(activity.args ?? {}).replace(/\s+/g, " ").replaceAll(import_os84.default.homedir(), "~");
|
|
73044
73178
|
const argsPreview = argsStr.length > 70 ? argsStr.slice(0, 70) + "\u2026" : argsStr;
|
|
73045
73179
|
return `${import_chalk49.default.gray(time)} ${icon} ${agentLabel(activity.agent, activity.mcpServer, activity.sessionId)}${import_chalk49.default.white.bold(toolName)} ${import_chalk49.default.dim(argsPreview)}`;
|
|
73046
73180
|
}
|
|
@@ -73079,9 +73213,9 @@ function renderPending(activity) {
|
|
|
73079
73213
|
}
|
|
73080
73214
|
async function ensureDaemon() {
|
|
73081
73215
|
let pidPort = null;
|
|
73082
|
-
if (
|
|
73216
|
+
if (import_fs104.default.existsSync(PID_FILE)) {
|
|
73083
73217
|
try {
|
|
73084
|
-
const { port } = JSON.parse(
|
|
73218
|
+
const { port } = JSON.parse(import_fs104.default.readFileSync(PID_FILE, "utf-8"));
|
|
73085
73219
|
pidPort = port;
|
|
73086
73220
|
} catch {
|
|
73087
73221
|
console.error(import_chalk49.default.dim("\u26A0\uFE0F Could not read PID file; falling back to default port."));
|
|
@@ -73107,7 +73241,7 @@ async function ensureDaemon() {
|
|
|
73107
73241
|
child.unref();
|
|
73108
73242
|
if (startupFd !== void 0) {
|
|
73109
73243
|
try {
|
|
73110
|
-
|
|
73244
|
+
import_fs104.default.closeSync(startupFd);
|
|
73111
73245
|
} catch {
|
|
73112
73246
|
}
|
|
73113
73247
|
}
|
|
@@ -73477,8 +73611,8 @@ async function startTail(options = {}) {
|
|
|
73477
73611
|
);
|
|
73478
73612
|
}).catch((err2) => {
|
|
73479
73613
|
try {
|
|
73480
|
-
|
|
73481
|
-
|
|
73614
|
+
import_fs104.default.appendFileSync(
|
|
73615
|
+
import_path103.default.join(import_os84.default.homedir(), ".node9", "hook-debug.log"),
|
|
73482
73616
|
`[tail] POST /decision failed: ${String(err2)}
|
|
73483
73617
|
`
|
|
73484
73618
|
);
|
|
@@ -73544,9 +73678,9 @@ async function startTail(options = {}) {
|
|
|
73544
73678
|
};
|
|
73545
73679
|
process.stdin.on("keypress", onKeypress);
|
|
73546
73680
|
}
|
|
73547
|
-
const auditLog =
|
|
73681
|
+
const auditLog = import_path103.default.join(import_os84.default.homedir(), ".node9", "audit.log");
|
|
73548
73682
|
try {
|
|
73549
|
-
const unackedDlp =
|
|
73683
|
+
const unackedDlp = import_fs104.default.readFileSync(auditLog, "utf-8").split("\n").filter((l) => l.includes('"response-dlp"')).length;
|
|
73550
73684
|
if (unackedDlp > 0) {
|
|
73551
73685
|
console.log("");
|
|
73552
73686
|
console.log(
|
|
@@ -73586,7 +73720,7 @@ async function startTail(options = {}) {
|
|
|
73586
73720
|
if (stallWarned) return;
|
|
73587
73721
|
if (Date.now() - lastActivityFromDaemon < STALL_THRESHOLD_MS) return;
|
|
73588
73722
|
try {
|
|
73589
|
-
const auditMtime =
|
|
73723
|
+
const auditMtime = import_fs104.default.statSync(auditLog).mtimeMs;
|
|
73590
73724
|
if (Date.now() - auditMtime >= STALL_THRESHOLD_MS) return;
|
|
73591
73725
|
console.log("");
|
|
73592
73726
|
console.log(
|
|
@@ -73758,7 +73892,7 @@ async function startTail(options = {}) {
|
|
|
73758
73892
|
process.exit(1);
|
|
73759
73893
|
});
|
|
73760
73894
|
}
|
|
73761
|
-
var import_http6, import_chalk49,
|
|
73895
|
+
var import_http6, import_chalk49, import_fs104, import_os84, import_path103, import_readline5, import_child_process17, PID_FILE, ICONS, MODEL_CONTEXT_LIMITS, RESET, BOLD, RED, YELLOW, CYAN, GRAY, GREEN, HIDE_CURSOR, SHOW_CURSOR, ERASE_DOWN, pendingShownForId, pendingWrappedLines, DIVIDER;
|
|
73762
73896
|
var init_tail = __esm({
|
|
73763
73897
|
"src/tui/tail.ts"() {
|
|
73764
73898
|
"use strict";
|
|
@@ -73766,16 +73900,16 @@ var init_tail = __esm({
|
|
|
73766
73900
|
import_http6 = __toESM(require("http"));
|
|
73767
73901
|
init_write();
|
|
73768
73902
|
import_chalk49 = __toESM(require("chalk"));
|
|
73769
|
-
|
|
73770
|
-
|
|
73771
|
-
|
|
73903
|
+
import_fs104 = __toESM(require("fs"));
|
|
73904
|
+
import_os84 = __toESM(require("os"));
|
|
73905
|
+
import_path103 = __toESM(require("path"));
|
|
73772
73906
|
import_readline5 = __toESM(require("readline"));
|
|
73773
73907
|
import_child_process17 = require("child_process");
|
|
73774
73908
|
init_startup_log();
|
|
73775
73909
|
init_daemon3();
|
|
73776
73910
|
init_daemon();
|
|
73777
73911
|
init_safe_text();
|
|
73778
|
-
PID_FILE =
|
|
73912
|
+
PID_FILE = import_path103.default.join(import_os84.default.homedir(), ".node9", "daemon.pid");
|
|
73779
73913
|
ICONS = {
|
|
73780
73914
|
bash: "\u{1F4BB}",
|
|
73781
73915
|
shell: "\u{1F4BB}",
|
|
@@ -73897,9 +74031,9 @@ function formatTimeLeft(resetsAt) {
|
|
|
73897
74031
|
return ` (${m}m left)`;
|
|
73898
74032
|
}
|
|
73899
74033
|
function safeReadJson(filePath) {
|
|
73900
|
-
if (!
|
|
74034
|
+
if (!import_fs105.default.existsSync(filePath)) return null;
|
|
73901
74035
|
try {
|
|
73902
|
-
return JSON.parse(
|
|
74036
|
+
return JSON.parse(import_fs105.default.readFileSync(filePath, "utf-8"));
|
|
73903
74037
|
} catch {
|
|
73904
74038
|
return null;
|
|
73905
74039
|
}
|
|
@@ -73920,12 +74054,12 @@ function countHooksInFile(filePath) {
|
|
|
73920
74054
|
return Object.keys(cfg.hooks).length;
|
|
73921
74055
|
}
|
|
73922
74056
|
function countRulesInDir(rulesDir) {
|
|
73923
|
-
if (!
|
|
74057
|
+
if (!import_fs105.default.existsSync(rulesDir)) return 0;
|
|
73924
74058
|
let count = 0;
|
|
73925
74059
|
try {
|
|
73926
|
-
for (const entry of
|
|
74060
|
+
for (const entry of import_fs105.default.readdirSync(rulesDir, { withFileTypes: true })) {
|
|
73927
74061
|
if (entry.isDirectory()) {
|
|
73928
|
-
count += countRulesInDir(
|
|
74062
|
+
count += countRulesInDir(import_path104.default.join(rulesDir, entry.name));
|
|
73929
74063
|
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
73930
74064
|
count++;
|
|
73931
74065
|
}
|
|
@@ -73936,46 +74070,46 @@ function countRulesInDir(rulesDir) {
|
|
|
73936
74070
|
}
|
|
73937
74071
|
function isSamePath(a, b) {
|
|
73938
74072
|
try {
|
|
73939
|
-
return
|
|
74073
|
+
return import_path104.default.resolve(a) === import_path104.default.resolve(b);
|
|
73940
74074
|
} catch {
|
|
73941
74075
|
return false;
|
|
73942
74076
|
}
|
|
73943
74077
|
}
|
|
73944
74078
|
function countConfigs(cwd) {
|
|
73945
|
-
const homeDir2 =
|
|
73946
|
-
const claudeDir =
|
|
74079
|
+
const homeDir2 = import_os85.default.homedir();
|
|
74080
|
+
const claudeDir = import_path104.default.join(homeDir2, ".claude");
|
|
73947
74081
|
let claudeMdCount = 0;
|
|
73948
74082
|
let rulesCount = 0;
|
|
73949
74083
|
let hooksCount = 0;
|
|
73950
74084
|
const userMcpServers = /* @__PURE__ */ new Set();
|
|
73951
74085
|
const projectMcpServers = /* @__PURE__ */ new Set();
|
|
73952
|
-
if (
|
|
73953
|
-
rulesCount += countRulesInDir(
|
|
73954
|
-
const userSettings =
|
|
74086
|
+
if (import_fs105.default.existsSync(import_path104.default.join(claudeDir, "CLAUDE.md"))) claudeMdCount++;
|
|
74087
|
+
rulesCount += countRulesInDir(import_path104.default.join(claudeDir, "rules"));
|
|
74088
|
+
const userSettings = import_path104.default.join(claudeDir, "settings.json");
|
|
73955
74089
|
for (const name of getMcpServerNames(userSettings)) userMcpServers.add(name);
|
|
73956
74090
|
hooksCount += countHooksInFile(userSettings);
|
|
73957
|
-
const userClaudeJson =
|
|
74091
|
+
const userClaudeJson = import_path104.default.join(homeDir2, ".claude.json");
|
|
73958
74092
|
for (const name of getMcpServerNames(userClaudeJson)) userMcpServers.add(name);
|
|
73959
74093
|
for (const name of getDisabledMcpServers(userClaudeJson, "disabledMcpServers")) {
|
|
73960
74094
|
userMcpServers.delete(name);
|
|
73961
74095
|
}
|
|
73962
74096
|
if (cwd) {
|
|
73963
|
-
if (
|
|
73964
|
-
if (
|
|
73965
|
-
const projectClaudeDir =
|
|
74097
|
+
if (import_fs105.default.existsSync(import_path104.default.join(cwd, "CLAUDE.md"))) claudeMdCount++;
|
|
74098
|
+
if (import_fs105.default.existsSync(import_path104.default.join(cwd, "CLAUDE.local.md"))) claudeMdCount++;
|
|
74099
|
+
const projectClaudeDir = import_path104.default.join(cwd, ".claude");
|
|
73966
74100
|
const overlapsUserScope = isSamePath(projectClaudeDir, claudeDir);
|
|
73967
74101
|
if (!overlapsUserScope) {
|
|
73968
|
-
if (
|
|
73969
|
-
rulesCount += countRulesInDir(
|
|
73970
|
-
const projSettings =
|
|
74102
|
+
if (import_fs105.default.existsSync(import_path104.default.join(projectClaudeDir, "CLAUDE.md"))) claudeMdCount++;
|
|
74103
|
+
rulesCount += countRulesInDir(import_path104.default.join(projectClaudeDir, "rules"));
|
|
74104
|
+
const projSettings = import_path104.default.join(projectClaudeDir, "settings.json");
|
|
73971
74105
|
for (const name of getMcpServerNames(projSettings)) projectMcpServers.add(name);
|
|
73972
74106
|
hooksCount += countHooksInFile(projSettings);
|
|
73973
74107
|
}
|
|
73974
|
-
if (
|
|
73975
|
-
const localSettings =
|
|
74108
|
+
if (import_fs105.default.existsSync(import_path104.default.join(projectClaudeDir, "CLAUDE.local.md"))) claudeMdCount++;
|
|
74109
|
+
const localSettings = import_path104.default.join(projectClaudeDir, "settings.local.json");
|
|
73976
74110
|
for (const name of getMcpServerNames(localSettings)) projectMcpServers.add(name);
|
|
73977
74111
|
hooksCount += countHooksInFile(localSettings);
|
|
73978
|
-
const mcpJsonServers = getMcpServerNames(
|
|
74112
|
+
const mcpJsonServers = getMcpServerNames(import_path104.default.join(cwd, ".mcp.json"));
|
|
73979
74113
|
const disabledMcpJson = getDisabledMcpServers(localSettings, "disabledMcpjsonServers");
|
|
73980
74114
|
for (const name of disabledMcpJson) mcpJsonServers.delete(name);
|
|
73981
74115
|
for (const name of mcpJsonServers) projectMcpServers.add(name);
|
|
@@ -74008,12 +74142,12 @@ function readActiveShieldsHud() {
|
|
|
74008
74142
|
return shieldsCache.value;
|
|
74009
74143
|
}
|
|
74010
74144
|
try {
|
|
74011
|
-
const shieldsPath =
|
|
74012
|
-
if (!
|
|
74145
|
+
const shieldsPath = import_path104.default.join(import_os85.default.homedir(), ".node9", "shields.json");
|
|
74146
|
+
if (!import_fs105.default.existsSync(shieldsPath)) {
|
|
74013
74147
|
shieldsCache = { value: [], ts: now };
|
|
74014
74148
|
return [];
|
|
74015
74149
|
}
|
|
74016
|
-
const parsed = JSON.parse(
|
|
74150
|
+
const parsed = JSON.parse(import_fs105.default.readFileSync(shieldsPath, "utf-8"));
|
|
74017
74151
|
if (!Array.isArray(parsed.active)) {
|
|
74018
74152
|
shieldsCache = { value: [], ts: now };
|
|
74019
74153
|
return [];
|
|
@@ -74115,17 +74249,17 @@ function renderContextLine(stdin) {
|
|
|
74115
74249
|
async function main() {
|
|
74116
74250
|
try {
|
|
74117
74251
|
const [stdin, daemonStatus2] = await Promise.all([readStdin(), queryDaemon()]);
|
|
74118
|
-
if (
|
|
74252
|
+
if (import_fs105.default.existsSync(import_path104.default.join(import_os85.default.homedir(), ".node9", "hud-debug"))) {
|
|
74119
74253
|
try {
|
|
74120
|
-
const logPath =
|
|
74254
|
+
const logPath = import_path104.default.join(import_os85.default.homedir(), ".node9", "hud-debug.log");
|
|
74121
74255
|
const MAX_LOG_SIZE = 10 * 1024 * 1024;
|
|
74122
74256
|
let size = 0;
|
|
74123
74257
|
try {
|
|
74124
|
-
size =
|
|
74258
|
+
size = import_fs105.default.statSync(logPath).size;
|
|
74125
74259
|
} catch {
|
|
74126
74260
|
}
|
|
74127
74261
|
if (size < MAX_LOG_SIZE) {
|
|
74128
|
-
|
|
74262
|
+
import_fs105.default.appendFileSync(
|
|
74129
74263
|
logPath,
|
|
74130
74264
|
JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), stdin }) + "\n"
|
|
74131
74265
|
);
|
|
@@ -74146,11 +74280,11 @@ async function main() {
|
|
|
74146
74280
|
try {
|
|
74147
74281
|
const cwd = stdin.cwd ?? process.cwd();
|
|
74148
74282
|
for (const configPath2 of [
|
|
74149
|
-
|
|
74150
|
-
|
|
74283
|
+
import_path104.default.join(cwd, "node9.config.json"),
|
|
74284
|
+
import_path104.default.join(import_os85.default.homedir(), ".node9", "config.json")
|
|
74151
74285
|
]) {
|
|
74152
|
-
if (!
|
|
74153
|
-
const cfg = JSON.parse(
|
|
74286
|
+
if (!import_fs105.default.existsSync(configPath2)) continue;
|
|
74287
|
+
const cfg = JSON.parse(import_fs105.default.readFileSync(configPath2, "utf-8"));
|
|
74154
74288
|
const hud = cfg.settings?.hud;
|
|
74155
74289
|
if (hud && "showEnvironmentCounts" in hud) return hud.showEnvironmentCounts !== false;
|
|
74156
74290
|
}
|
|
@@ -74168,14 +74302,14 @@ async function main() {
|
|
|
74168
74302
|
renderOffline();
|
|
74169
74303
|
}
|
|
74170
74304
|
}
|
|
74171
|
-
var
|
|
74305
|
+
var import_fs105, import_path104, import_os85, import_http7, RESET2, BOLD2, DIM, RED2, GREEN2, YELLOW2, BLUE, MAGENTA, CYAN2, WHITE, BAR_FILLED, BAR_EMPTY, BAR_WIDTH, shieldsCache, SHIELDS_CACHE_TTL_MS;
|
|
74172
74306
|
var init_hud = __esm({
|
|
74173
74307
|
"src/cli/hud.ts"() {
|
|
74174
74308
|
"use strict";
|
|
74175
74309
|
init_cjs_shims();
|
|
74176
|
-
|
|
74177
|
-
|
|
74178
|
-
|
|
74310
|
+
import_fs105 = __toESM(require("fs"));
|
|
74311
|
+
import_path104 = __toESM(require("path"));
|
|
74312
|
+
import_os85 = __toESM(require("os"));
|
|
74179
74313
|
import_http7 = __toESM(require("http"));
|
|
74180
74314
|
init_daemon();
|
|
74181
74315
|
init_dist();
|
|
@@ -74240,9 +74374,9 @@ init_agent_wiring();
|
|
|
74240
74374
|
init_credentials();
|
|
74241
74375
|
init_daemon3();
|
|
74242
74376
|
var import_chalk50 = __toESM(require("chalk"));
|
|
74243
|
-
var
|
|
74244
|
-
var
|
|
74245
|
-
var
|
|
74377
|
+
var import_fs106 = __toESM(require("fs"));
|
|
74378
|
+
var import_path105 = __toESM(require("path"));
|
|
74379
|
+
var import_os86 = __toESM(require("os"));
|
|
74246
74380
|
var import_prompts4 = require("@inquirer/prompts");
|
|
74247
74381
|
|
|
74248
74382
|
// src/utils/duration.ts
|
|
@@ -74330,7 +74464,8 @@ async function runProxy(targetCommand) {
|
|
|
74330
74464
|
{
|
|
74331
74465
|
kind: result.blockKind,
|
|
74332
74466
|
path: result.blockedPath,
|
|
74333
|
-
redirect: !!result.redirect
|
|
74467
|
+
redirect: !!result.redirect,
|
|
74468
|
+
ruleDescription: result.ruleDescription
|
|
74334
74469
|
}
|
|
74335
74470
|
);
|
|
74336
74471
|
const errorResponse = {
|
|
@@ -74450,10 +74585,10 @@ function buildExplainJsonError(message) {
|
|
|
74450
74585
|
// src/cli/commands/check.ts
|
|
74451
74586
|
init_cjs_shims();
|
|
74452
74587
|
var import_chalk14 = __toESM(require("chalk"));
|
|
74453
|
-
var
|
|
74588
|
+
var import_fs75 = __toESM(require("fs"));
|
|
74454
74589
|
var import_child_process9 = require("child_process");
|
|
74455
|
-
var
|
|
74456
|
-
var
|
|
74590
|
+
var import_path75 = __toESM(require("path"));
|
|
74591
|
+
var import_os62 = __toESM(require("os"));
|
|
74457
74592
|
init_orchestrator();
|
|
74458
74593
|
init_state();
|
|
74459
74594
|
init_daemon();
|
|
@@ -74739,6 +74874,112 @@ function discardPendingReview(key, now = Date.now()) {
|
|
|
74739
74874
|
// src/cli/commands/check.ts
|
|
74740
74875
|
init_hook_payload();
|
|
74741
74876
|
init_safe_text();
|
|
74877
|
+
init_atomic_write();
|
|
74878
|
+
|
|
74879
|
+
// src/utils/own-dir.ts
|
|
74880
|
+
init_cjs_shims();
|
|
74881
|
+
var import_fs73 = __toESM(require("fs"));
|
|
74882
|
+
var import_path73 = __toESM(require("path"));
|
|
74883
|
+
var SESSION_FLAG_SUFFIX = ".node9-flag";
|
|
74884
|
+
var SESSION_FLAG_NAME = /^[A-Za-z0-9_-]{1,128}\.node9-flag$/;
|
|
74885
|
+
function isSessionFlagName(name) {
|
|
74886
|
+
return SESSION_FLAG_NAME.test(name);
|
|
74887
|
+
}
|
|
74888
|
+
function ownRealDir(st) {
|
|
74889
|
+
if (st.isSymbolicLink() || !st.isDirectory()) return false;
|
|
74890
|
+
return typeof process.getuid !== "function" || st.uid === process.getuid();
|
|
74891
|
+
}
|
|
74892
|
+
function ensureOwnDir(dir2) {
|
|
74893
|
+
try {
|
|
74894
|
+
import_fs73.default.mkdirSync(dir2, { recursive: true, mode: 448 });
|
|
74895
|
+
const st = import_fs73.default.lstatSync(dir2);
|
|
74896
|
+
return ownRealDir(st) ? { dev: st.dev, ino: st.ino } : null;
|
|
74897
|
+
} catch {
|
|
74898
|
+
return null;
|
|
74899
|
+
}
|
|
74900
|
+
}
|
|
74901
|
+
function isSameOwnDir(dir2, seen) {
|
|
74902
|
+
try {
|
|
74903
|
+
const st = import_fs73.default.lstatSync(dir2);
|
|
74904
|
+
return ownRealDir(st) && st.dev === seen.dev && st.ino === seen.ino;
|
|
74905
|
+
} catch {
|
|
74906
|
+
return false;
|
|
74907
|
+
}
|
|
74908
|
+
}
|
|
74909
|
+
function removeOldFlag(dir2, seen, name, cutoffMs) {
|
|
74910
|
+
if (!isSessionFlagName(name)) return;
|
|
74911
|
+
const p = import_path73.default.join(dir2, name);
|
|
74912
|
+
try {
|
|
74913
|
+
const st = import_fs73.default.lstatSync(p);
|
|
74914
|
+
if (!st.isFile() || st.mtimeMs >= cutoffMs) return;
|
|
74915
|
+
if (!isSameOwnDir(dir2, seen)) return;
|
|
74916
|
+
import_fs73.default.unlinkSync(p);
|
|
74917
|
+
} catch {
|
|
74918
|
+
}
|
|
74919
|
+
}
|
|
74920
|
+
|
|
74921
|
+
// src/notices/session-notice.ts
|
|
74922
|
+
init_cjs_shims();
|
|
74923
|
+
var import_fs74 = __toESM(require("fs"));
|
|
74924
|
+
var import_os61 = __toESM(require("os"));
|
|
74925
|
+
var import_path74 = __toESM(require("path"));
|
|
74926
|
+
init_dist();
|
|
74927
|
+
var ICON2 = "\u{1F6E1}\uFE0F";
|
|
74928
|
+
var LEVEL_NAMES = {
|
|
74929
|
+
audit: "Audit",
|
|
74930
|
+
soft: "Soft",
|
|
74931
|
+
standard: "Standard",
|
|
74932
|
+
strict: "Strict",
|
|
74933
|
+
"block-all": "Block all"
|
|
74934
|
+
};
|
|
74935
|
+
var SESSION_NOTICE_INSTRUCTION = "Start your next reply to the user with the line above, exactly as written, on its own line.";
|
|
74936
|
+
var FLAG_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
74937
|
+
var SAFE_SESSION_ID = /^[A-Za-z0-9_-]{1,128}$/;
|
|
74938
|
+
function sessionNoticeLine(mode) {
|
|
74939
|
+
const level = levelOf(mode);
|
|
74940
|
+
if (level === "audit") {
|
|
74941
|
+
return `${ICON2} Node9 is in Audit mode: actions are logged, nothing is blocked.`;
|
|
74942
|
+
}
|
|
74943
|
+
return `${ICON2} Node9 is on (${LEVEL_NAMES[level]}). Every action in this session is checked.`;
|
|
74944
|
+
}
|
|
74945
|
+
function sessionNoticeOutput(mode) {
|
|
74946
|
+
const line = sessionNoticeLine(mode);
|
|
74947
|
+
return JSON.stringify({
|
|
74948
|
+
hookSpecificOutput: {
|
|
74949
|
+
hookEventName: "PreToolUse",
|
|
74950
|
+
additionalContext: `${line}
|
|
74951
|
+
${SESSION_NOTICE_INSTRUCTION}`
|
|
74952
|
+
},
|
|
74953
|
+
systemMessage: line
|
|
74954
|
+
});
|
|
74955
|
+
}
|
|
74956
|
+
function sessionNoticeEnabled(env = process.env) {
|
|
74957
|
+
if (env.NODE9_SESSION_NOTICE === "1") return true;
|
|
74958
|
+
return env.NODE9_TESTING !== "1";
|
|
74959
|
+
}
|
|
74960
|
+
function claimSessionNotice(sessionId, home = import_os61.default.homedir()) {
|
|
74961
|
+
if (!sessionId || !SAFE_SESSION_ID.test(sessionId)) return false;
|
|
74962
|
+
const dir2 = import_path74.default.join(home, ".node9", "notice-sessions");
|
|
74963
|
+
const seen = ensureOwnDir(dir2);
|
|
74964
|
+
if (!seen) return false;
|
|
74965
|
+
try {
|
|
74966
|
+
if (!isSameOwnDir(dir2, seen)) return false;
|
|
74967
|
+
import_fs74.default.closeSync(import_fs74.default.openSync(import_path74.default.join(dir2, sessionId + SESSION_FLAG_SUFFIX), "wx"));
|
|
74968
|
+
} catch {
|
|
74969
|
+
return false;
|
|
74970
|
+
}
|
|
74971
|
+
removeOldFlags(dir2, seen);
|
|
74972
|
+
return true;
|
|
74973
|
+
}
|
|
74974
|
+
function removeOldFlags(dir2, seen) {
|
|
74975
|
+
const cutoff = Date.now() - FLAG_TTL_MS;
|
|
74976
|
+
try {
|
|
74977
|
+
for (const name of import_fs74.default.readdirSync(dir2)) removeOldFlag(dir2, seen, name, cutoff);
|
|
74978
|
+
} catch {
|
|
74979
|
+
}
|
|
74980
|
+
}
|
|
74981
|
+
|
|
74982
|
+
// src/cli/commands/check.ts
|
|
74742
74983
|
function detectAiAgent(payload) {
|
|
74743
74984
|
const meta = payload.meta;
|
|
74744
74985
|
if (meta && typeof meta === "object") {
|
|
@@ -74816,9 +75057,9 @@ function registerCheckCommand(program2) {
|
|
|
74816
75057
|
} catch (err2) {
|
|
74817
75058
|
const tempConfig = getConfig();
|
|
74818
75059
|
if (process.env.NODE9_DEBUG === "1" || tempConfig.settings.enableHookLogDebug) {
|
|
74819
|
-
const logPath =
|
|
75060
|
+
const logPath = import_path75.default.join(import_os62.default.homedir(), ".node9", "hook-debug.log");
|
|
74820
75061
|
const errMsg = err2 instanceof Error ? err2.message : String(err2);
|
|
74821
|
-
|
|
75062
|
+
import_fs75.default.appendFileSync(
|
|
74822
75063
|
logPath,
|
|
74823
75064
|
`[${(/* @__PURE__ */ new Date()).toISOString()}] JSON_PARSE_ERROR: ${errMsg}
|
|
74824
75065
|
RAW: ${raw}
|
|
@@ -74831,14 +75072,14 @@ RAW: ${raw}
|
|
|
74831
75072
|
const prompt = typeof payload.prompt === "string" ? payload.prompt : "";
|
|
74832
75073
|
if (process.env.NODE9_DEBUG === "1") {
|
|
74833
75074
|
try {
|
|
74834
|
-
const logPath =
|
|
74835
|
-
if (!
|
|
74836
|
-
|
|
75075
|
+
const logPath = import_path75.default.join(import_os62.default.homedir(), ".node9", "hook-debug.log");
|
|
75076
|
+
if (!import_fs75.default.existsSync(import_path75.default.dirname(logPath)))
|
|
75077
|
+
import_fs75.default.mkdirSync(import_path75.default.dirname(logPath), { recursive: true });
|
|
74837
75078
|
const sanitized = JSON.stringify({
|
|
74838
75079
|
...payload,
|
|
74839
75080
|
prompt: `<redacted, ${prompt.length} bytes>`
|
|
74840
75081
|
});
|
|
74841
|
-
|
|
75082
|
+
import_fs75.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] STDIN: ${sanitized}
|
|
74842
75083
|
`);
|
|
74843
75084
|
} catch {
|
|
74844
75085
|
}
|
|
@@ -74856,7 +75097,7 @@ RAW: ${raw}
|
|
|
74856
75097
|
if (!dlpMatch && !canaryHit) {
|
|
74857
75098
|
try {
|
|
74858
75099
|
const sid = typeof payload.session_id === "string" ? payload.session_id : typeof payload.conversationId === "string" ? payload.conversationId : "";
|
|
74859
|
-
const promptCwd = typeof payload.cwd === "string" &&
|
|
75100
|
+
const promptCwd = typeof payload.cwd === "string" && import_path75.default.isAbsolute(payload.cwd) ? payload.cwd : void 0;
|
|
74860
75101
|
if (sid && getConfig(promptCwd).policy.untrustedContent?.enabled) {
|
|
74861
75102
|
await notifyUserMentions(sid, extractContentDestinations(prompt));
|
|
74862
75103
|
}
|
|
@@ -74897,8 +75138,8 @@ RAW: ${raw}
|
|
|
74897
75138
|
);
|
|
74898
75139
|
const reason = `\u{1F6A8} Node9 DLP: ${shownPattern} detected in prompt (${shownSample}). Prompt was not submitted \u2014 remove the credential and try again.`;
|
|
74899
75140
|
try {
|
|
74900
|
-
const ttyFd =
|
|
74901
|
-
|
|
75141
|
+
const ttyFd = import_fs75.default.openSync("/dev/tty", "w");
|
|
75142
|
+
import_fs75.default.writeSync(
|
|
74902
75143
|
ttyFd,
|
|
74903
75144
|
import_chalk14.default.bgRed.white.bold(`
|
|
74904
75145
|
\u{1F6A8} NODE9 DLP \u2014 PROMPT BLOCKED
|
|
@@ -74908,7 +75149,7 @@ RAW: ${raw}
|
|
|
74908
75149
|
|
|
74909
75150
|
`)
|
|
74910
75151
|
);
|
|
74911
|
-
|
|
75152
|
+
import_fs75.default.closeSync(ttyFd);
|
|
74912
75153
|
} catch {
|
|
74913
75154
|
}
|
|
74914
75155
|
const isCodex = agent2 === "Codex";
|
|
@@ -74927,17 +75168,17 @@ RAW: ${raw}
|
|
|
74927
75168
|
process.exit(2);
|
|
74928
75169
|
}
|
|
74929
75170
|
const payloadCwd = typeof payload.cwd === "string" ? payload.cwd : Array.isArray(payload.workspacePaths) && typeof payload.workspacePaths[0] === "string" ? payload.workspacePaths[0] : void 0;
|
|
74930
|
-
const safeCwdForConfig = typeof payloadCwd === "string" &&
|
|
75171
|
+
const safeCwdForConfig = typeof payloadCwd === "string" && import_path75.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
|
|
74931
75172
|
const config = getConfig(safeCwdForConfig);
|
|
74932
75173
|
const daemonDown = !isDaemonRunning();
|
|
74933
75174
|
if (config.settings.autoStartDaemon && daemonDown && !process.env.NODE9_NO_AUTO_DAEMON) {
|
|
74934
75175
|
try {
|
|
74935
75176
|
const scriptPath = process.argv[1];
|
|
74936
|
-
if (typeof scriptPath !== "string" || !
|
|
75177
|
+
if (typeof scriptPath !== "string" || !import_path75.default.isAbsolute(scriptPath))
|
|
74937
75178
|
throw new Error("node9: argv[1] is not an absolute path");
|
|
74938
|
-
const resolvedScript =
|
|
74939
|
-
const packageDist =
|
|
74940
|
-
if (!resolvedScript.startsWith(packageDist +
|
|
75179
|
+
const resolvedScript = import_fs75.default.realpathSync(scriptPath);
|
|
75180
|
+
const packageDist = import_fs75.default.realpathSync(import_path75.default.resolve(__dirname, "../.."));
|
|
75181
|
+
if (!resolvedScript.startsWith(packageDist + import_path75.default.sep) && resolvedScript !== packageDist)
|
|
74941
75182
|
throw new Error(
|
|
74942
75183
|
`node9: daemon spawn aborted \u2014 argv[1] (${resolvedScript}) is outside package dist (${packageDist})`
|
|
74943
75184
|
);
|
|
@@ -74967,17 +75208,17 @@ RAW: ${raw}
|
|
|
74967
75208
|
} finally {
|
|
74968
75209
|
if (startupFd !== void 0) {
|
|
74969
75210
|
try {
|
|
74970
|
-
|
|
75211
|
+
import_fs75.default.closeSync(startupFd);
|
|
74971
75212
|
} catch {
|
|
74972
75213
|
}
|
|
74973
75214
|
}
|
|
74974
75215
|
}
|
|
74975
75216
|
} catch (spawnErr) {
|
|
74976
|
-
const logPath =
|
|
75217
|
+
const logPath = import_path75.default.join(import_os62.default.homedir(), ".node9", "hook-debug.log");
|
|
74977
75218
|
const msg = spawnErr instanceof Error ? spawnErr.message : String(spawnErr);
|
|
74978
75219
|
recordStartupState("failed", "spawn-aborted", msg);
|
|
74979
75220
|
try {
|
|
74980
|
-
|
|
75221
|
+
import_fs75.default.appendFileSync(
|
|
74981
75222
|
logPath,
|
|
74982
75223
|
`[${(/* @__PURE__ */ new Date()).toISOString()}] daemon-autostart-failed: ${msg}
|
|
74983
75224
|
`
|
|
@@ -74991,10 +75232,10 @@ RAW: ${raw}
|
|
|
74991
75232
|
);
|
|
74992
75233
|
}
|
|
74993
75234
|
if (process.env.NODE9_DEBUG === "1" || config.settings.enableHookLogDebug) {
|
|
74994
|
-
const logPath =
|
|
74995
|
-
if (!
|
|
74996
|
-
|
|
74997
|
-
|
|
75235
|
+
const logPath = import_path75.default.join(import_os62.default.homedir(), ".node9", "hook-debug.log");
|
|
75236
|
+
if (!import_fs75.default.existsSync(import_path75.default.dirname(logPath)))
|
|
75237
|
+
import_fs75.default.mkdirSync(import_path75.default.dirname(logPath), { recursive: true });
|
|
75238
|
+
import_fs75.default.appendFileSync(
|
|
74998
75239
|
logPath,
|
|
74999
75240
|
`[${(/* @__PURE__ */ new Date()).toISOString()}] STDIN: ${JSON.stringify(raw)}
|
|
75000
75241
|
`
|
|
@@ -75015,8 +75256,8 @@ RAW: ${raw}
|
|
|
75015
75256
|
);
|
|
75016
75257
|
let ttyFd = null;
|
|
75017
75258
|
try {
|
|
75018
|
-
ttyFd =
|
|
75019
|
-
const writeTty = (line) =>
|
|
75259
|
+
ttyFd = import_fs75.default.openSync("/dev/tty", "w");
|
|
75260
|
+
const writeTty = (line) => import_fs75.default.writeSync(ttyFd, line + "\n");
|
|
75020
75261
|
if (result2?.blockKind === "protected-path") {
|
|
75021
75262
|
writeTty(
|
|
75022
75263
|
import_chalk14.default.red.bold(
|
|
@@ -75043,7 +75284,7 @@ RAW: ${raw}
|
|
|
75043
75284
|
} finally {
|
|
75044
75285
|
if (ttyFd !== null)
|
|
75045
75286
|
try {
|
|
75046
|
-
|
|
75287
|
+
import_fs75.default.closeSync(ttyFd);
|
|
75047
75288
|
} catch {
|
|
75048
75289
|
}
|
|
75049
75290
|
}
|
|
@@ -75052,7 +75293,12 @@ RAW: ${raw}
|
|
|
75052
75293
|
humanDecision,
|
|
75053
75294
|
msg,
|
|
75054
75295
|
result2?.recoveryCommand,
|
|
75055
|
-
{
|
|
75296
|
+
{
|
|
75297
|
+
kind: result2?.blockKind,
|
|
75298
|
+
path: result2?.blockedPath,
|
|
75299
|
+
redirect: !!result2?.redirect,
|
|
75300
|
+
ruleDescription: result2?.ruleDescription
|
|
75301
|
+
}
|
|
75056
75302
|
);
|
|
75057
75303
|
if (agent === "Antigravity") {
|
|
75058
75304
|
process.stdout.write(
|
|
@@ -75069,11 +75315,13 @@ RAW: ${raw}
|
|
|
75069
75315
|
);
|
|
75070
75316
|
process.exit(0);
|
|
75071
75317
|
}
|
|
75318
|
+
const userLine = userLineOf(aiFeedbackMessage);
|
|
75072
75319
|
process.stdout.write(
|
|
75073
75320
|
JSON.stringify({
|
|
75074
75321
|
decision: "block",
|
|
75075
75322
|
reason: aiFeedbackMessage,
|
|
75076
75323
|
// This is the core instruction
|
|
75324
|
+
...agent === "Claude Code" && userLine ? { systemMessage: userLine } : {},
|
|
75077
75325
|
hookSpecificOutput: {
|
|
75078
75326
|
hookEventName: "PreToolUse",
|
|
75079
75327
|
permissionDecision: "deny",
|
|
@@ -75107,8 +75355,8 @@ RAW: ${raw}
|
|
|
75107
75355
|
} catch {
|
|
75108
75356
|
}
|
|
75109
75357
|
try {
|
|
75110
|
-
const ttyFd =
|
|
75111
|
-
|
|
75358
|
+
const ttyFd = import_fs75.default.openSync("/dev/tty", "w");
|
|
75359
|
+
import_fs75.default.writeSync(
|
|
75112
75360
|
ttyFd,
|
|
75113
75361
|
import_chalk14.default.yellow(
|
|
75114
75362
|
`
|
|
@@ -75116,7 +75364,7 @@ RAW: ${raw}
|
|
|
75116
75364
|
`
|
|
75117
75365
|
)
|
|
75118
75366
|
);
|
|
75119
|
-
|
|
75367
|
+
import_fs75.default.closeSync(ttyFd);
|
|
75120
75368
|
} catch {
|
|
75121
75369
|
}
|
|
75122
75370
|
if (agent === "GitHub Copilot") {
|
|
@@ -75148,17 +75396,20 @@ RAW: ${raw}
|
|
|
75148
75396
|
const safeSessionId = /^[A-Za-z0-9_\-]{1,128}$/.test(rawSessionId) ? rawSessionId : "";
|
|
75149
75397
|
if (skillPinCfg.enabled && safeSessionId) {
|
|
75150
75398
|
try {
|
|
75151
|
-
const sessionsDir =
|
|
75152
|
-
const flagPath =
|
|
75399
|
+
const sessionsDir = import_path75.default.join(import_os62.default.homedir(), ".node9", "skill-sessions");
|
|
75400
|
+
const flagPath = import_path75.default.join(sessionsDir, `${safeSessionId}${SESSION_FLAG_SUFFIX}`);
|
|
75401
|
+
const memo = ensureOwnDir(sessionsDir);
|
|
75153
75402
|
let flag = null;
|
|
75154
75403
|
try {
|
|
75155
|
-
|
|
75404
|
+
const st = memo ? import_fs75.default.lstatSync(flagPath) : null;
|
|
75405
|
+
if (st && st.isFile() && st.nlink === 1)
|
|
75406
|
+
flag = JSON.parse(import_fs75.default.readFileSync(flagPath, "utf-8"));
|
|
75156
75407
|
} catch {
|
|
75157
75408
|
}
|
|
75158
75409
|
const writeFlag = (data2) => {
|
|
75410
|
+
if (!memo || !isSameOwnDir(sessionsDir, memo)) return;
|
|
75159
75411
|
try {
|
|
75160
|
-
|
|
75161
|
-
import_fs73.default.writeFileSync(
|
|
75412
|
+
atomicWriteSync(
|
|
75162
75413
|
flagPath,
|
|
75163
75414
|
JSON.stringify({ ...data2, timestamp: (/* @__PURE__ */ new Date()).toISOString() }, null, 2),
|
|
75164
75415
|
{ mode: 384 }
|
|
@@ -75169,8 +75420,8 @@ RAW: ${raw}
|
|
|
75169
75420
|
const sendSkillWarn = (detail, recoveryCmd) => {
|
|
75170
75421
|
let ttyFd = null;
|
|
75171
75422
|
try {
|
|
75172
|
-
ttyFd =
|
|
75173
|
-
const w = (line) =>
|
|
75423
|
+
ttyFd = import_fs75.default.openSync("/dev/tty", "w");
|
|
75424
|
+
const w = (line) => import_fs75.default.writeSync(ttyFd, line + "\n");
|
|
75174
75425
|
w(import_chalk14.default.yellow(`
|
|
75175
75426
|
\u26A0\uFE0F Node9: installed skill drift detected`));
|
|
75176
75427
|
w(import_chalk14.default.gray(` ${detail}`));
|
|
@@ -75185,7 +75436,7 @@ RAW: ${raw}
|
|
|
75185
75436
|
} finally {
|
|
75186
75437
|
if (ttyFd !== null)
|
|
75187
75438
|
try {
|
|
75188
|
-
|
|
75439
|
+
import_fs75.default.closeSync(ttyFd);
|
|
75189
75440
|
} catch {
|
|
75190
75441
|
}
|
|
75191
75442
|
}
|
|
@@ -75201,7 +75452,7 @@ RAW: ${raw}
|
|
|
75201
75452
|
return;
|
|
75202
75453
|
}
|
|
75203
75454
|
if (!flag || flag.state !== "verified" && flag.state !== "warned") {
|
|
75204
|
-
const absoluteCwd = typeof payloadCwd === "string" &&
|
|
75455
|
+
const absoluteCwd = typeof payloadCwd === "string" && import_path75.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
|
|
75205
75456
|
const extraRoots = skillPinCfg.roots;
|
|
75206
75457
|
const resolvedExtra = extraRoots.map((r) => resolveUserSkillRoot(r, absoluteCwd)).filter((r) => typeof r === "string");
|
|
75207
75458
|
const roots = [...defaultSkillRoots(absoluteCwd), ...resolvedExtra];
|
|
@@ -75240,31 +75491,27 @@ RAW: ${raw}
|
|
|
75240
75491
|
} else {
|
|
75241
75492
|
writeFlag({ state: "verified" });
|
|
75242
75493
|
}
|
|
75243
|
-
|
|
75244
|
-
|
|
75245
|
-
|
|
75246
|
-
const
|
|
75247
|
-
|
|
75248
|
-
|
|
75249
|
-
} catch {
|
|
75250
|
-
}
|
|
75494
|
+
if (memo)
|
|
75495
|
+
try {
|
|
75496
|
+
const cutoff = Date.now() - 7 * 24 * 60 * 60 * 1e3;
|
|
75497
|
+
for (const name of import_fs75.default.readdirSync(sessionsDir))
|
|
75498
|
+
removeOldFlag(sessionsDir, memo, name, cutoff);
|
|
75499
|
+
} catch {
|
|
75251
75500
|
}
|
|
75252
|
-
} catch {
|
|
75253
|
-
}
|
|
75254
75501
|
}
|
|
75255
75502
|
} catch (err2) {
|
|
75256
75503
|
if (process.env.NODE9_DEBUG === "1") {
|
|
75257
75504
|
try {
|
|
75258
|
-
const dbg =
|
|
75505
|
+
const dbg = import_path75.default.join(import_os62.default.homedir(), ".node9", "hook-debug.log");
|
|
75259
75506
|
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
75260
|
-
|
|
75507
|
+
import_fs75.default.appendFileSync(dbg, `[${(/* @__PURE__ */ new Date()).toISOString()}] SKILL_PIN_ERROR: ${msg}
|
|
75261
75508
|
`);
|
|
75262
75509
|
} catch {
|
|
75263
75510
|
}
|
|
75264
75511
|
}
|
|
75265
75512
|
}
|
|
75266
75513
|
}
|
|
75267
|
-
const safeCwdForAuth = typeof payloadCwd === "string" &&
|
|
75514
|
+
const safeCwdForAuth = typeof payloadCwd === "string" && import_path75.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
|
|
75268
75515
|
const askMode = resolveAskMode(agent, opts, config);
|
|
75269
75516
|
const result = await authorizeHeadless(toolName, toolInput, meta, {
|
|
75270
75517
|
cwd: safeCwdForAuth,
|
|
@@ -75277,11 +75524,21 @@ RAW: ${raw}
|
|
|
75277
75524
|
} catch {
|
|
75278
75525
|
}
|
|
75279
75526
|
}
|
|
75527
|
+
const isSubagentCall = typeof payload.agent_id === "string" && payload.agent_id !== "";
|
|
75528
|
+
const allowExit = (checkedBy) => {
|
|
75529
|
+
if (checkedBy !== "paused" && agent === "Claude Code" && !isSubagentCall && sessionNoticeEnabled() && claimSessionNotice(safeSessionId)) {
|
|
75530
|
+
try {
|
|
75531
|
+
import_fs75.default.writeSync(1, sessionNoticeOutput(config.settings.mode) + "\n");
|
|
75532
|
+
} catch {
|
|
75533
|
+
}
|
|
75534
|
+
}
|
|
75535
|
+
process.exit(0);
|
|
75536
|
+
};
|
|
75280
75537
|
if (result.approved) {
|
|
75281
75538
|
if (result.checkedBy && process.env.NODE9_DEBUG === "1")
|
|
75282
75539
|
process.stderr.write(`\u2713 node9 [${result.checkedBy}]: "${toolName}" allowed
|
|
75283
75540
|
`);
|
|
75284
|
-
|
|
75541
|
+
allowExit(result.checkedBy);
|
|
75285
75542
|
}
|
|
75286
75543
|
if (result.review) {
|
|
75287
75544
|
sendAsk(result);
|
|
@@ -75289,12 +75546,12 @@ RAW: ${raw}
|
|
|
75289
75546
|
}
|
|
75290
75547
|
if (result.noApprovalMechanism && !isDaemonRunning() && !process.env.NODE9_NO_AUTO_DAEMON && !process.stdout.isTTY && config.settings.autoStartDaemon) {
|
|
75291
75548
|
try {
|
|
75292
|
-
const tty =
|
|
75293
|
-
|
|
75549
|
+
const tty = import_fs75.default.openSync("/dev/tty", "w");
|
|
75550
|
+
import_fs75.default.writeSync(
|
|
75294
75551
|
tty,
|
|
75295
75552
|
import_chalk14.default.cyan("\n\u{1F6E1}\uFE0F Node9: Starting approval daemon automatically...\n")
|
|
75296
75553
|
);
|
|
75297
|
-
|
|
75554
|
+
import_fs75.default.closeSync(tty);
|
|
75298
75555
|
} catch {
|
|
75299
75556
|
}
|
|
75300
75557
|
const daemonReady = await autoStartDaemonAndWait();
|
|
@@ -75306,7 +75563,7 @@ RAW: ${raw}
|
|
|
75306
75563
|
if (retry.checkedBy && process.env.NODE9_DEBUG === "1")
|
|
75307
75564
|
process.stderr.write(`\u2713 node9 [${retry.checkedBy}]: "${toolName}" allowed
|
|
75308
75565
|
`);
|
|
75309
|
-
|
|
75566
|
+
allowExit(retry.checkedBy);
|
|
75310
75567
|
}
|
|
75311
75568
|
sendBlock(retry.reason ?? `Node9 blocked "${toolName}".`, {
|
|
75312
75569
|
...retry,
|
|
@@ -75321,9 +75578,9 @@ RAW: ${raw}
|
|
|
75321
75578
|
});
|
|
75322
75579
|
} catch (err2) {
|
|
75323
75580
|
if (process.env.NODE9_DEBUG === "1") {
|
|
75324
|
-
const logPath =
|
|
75581
|
+
const logPath = import_path75.default.join(import_os62.default.homedir(), ".node9", "hook-debug.log");
|
|
75325
75582
|
const errMsg = err2 instanceof Error ? err2.message : String(err2);
|
|
75326
|
-
|
|
75583
|
+
import_fs75.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] ERROR: ${errMsg}
|
|
75327
75584
|
`);
|
|
75328
75585
|
}
|
|
75329
75586
|
process.exit(0);
|
|
@@ -75358,9 +75615,9 @@ RAW: ${raw}
|
|
|
75358
75615
|
|
|
75359
75616
|
// src/cli/commands/log.ts
|
|
75360
75617
|
init_cjs_shims();
|
|
75361
|
-
var
|
|
75362
|
-
var
|
|
75363
|
-
var
|
|
75618
|
+
var import_fs76 = __toESM(require("fs"));
|
|
75619
|
+
var import_path76 = __toESM(require("path"));
|
|
75620
|
+
var import_os63 = __toESM(require("os"));
|
|
75364
75621
|
init_audit();
|
|
75365
75622
|
init_config();
|
|
75366
75623
|
init_daemon();
|
|
@@ -75640,12 +75897,12 @@ function registerLogCommand(program2) {
|
|
|
75640
75897
|
if (rawToolName !== tool) entry.agentToolName = rawToolName;
|
|
75641
75898
|
const payloadSessionId = payload.session_id ?? payload.conversationId;
|
|
75642
75899
|
if (payloadSessionId) entry.sessionId = payloadSessionId;
|
|
75643
|
-
const logPath =
|
|
75644
|
-
if (!
|
|
75645
|
-
|
|
75646
|
-
|
|
75900
|
+
const logPath = import_path76.default.join(import_os63.default.homedir(), ".node9", "audit.log");
|
|
75901
|
+
if (!import_fs76.default.existsSync(import_path76.default.dirname(logPath)))
|
|
75902
|
+
import_fs76.default.mkdirSync(import_path76.default.dirname(logPath), { recursive: true });
|
|
75903
|
+
import_fs76.default.appendFileSync(logPath, JSON.stringify(entry) + "\n");
|
|
75647
75904
|
const payloadCwd = typeof payload.cwd === "string" ? payload.cwd : Array.isArray(payload.workspacePaths) && typeof payload.workspacePaths[0] === "string" ? payload.workspacePaths[0] : void 0;
|
|
75648
|
-
const safeCwd = typeof payloadCwd === "string" &&
|
|
75905
|
+
const safeCwd = typeof payloadCwd === "string" && import_path76.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
|
|
75649
75906
|
if ((tool === "Bash" || tool === "bash") && isDaemonRunning()) {
|
|
75650
75907
|
const command = typeof rawInput === "object" && rawInput !== null && "command" in rawInput && typeof rawInput.command === "string" ? rawInput.command : null;
|
|
75651
75908
|
if (command) {
|
|
@@ -75866,9 +76123,9 @@ function registerLogCommand(program2) {
|
|
|
75866
76123
|
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
75867
76124
|
process.stderr.write(`[Node9] audit log error: ${msg}
|
|
75868
76125
|
`);
|
|
75869
|
-
const debugPath =
|
|
76126
|
+
const debugPath = import_path76.default.join(import_os63.default.homedir(), ".node9", "hook-debug.log");
|
|
75870
76127
|
try {
|
|
75871
|
-
|
|
76128
|
+
import_fs76.default.appendFileSync(debugPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] LOG_ERROR: ${msg}
|
|
75872
76129
|
`);
|
|
75873
76130
|
} catch {
|
|
75874
76131
|
}
|
|
@@ -75891,9 +76148,9 @@ function registerLogCommand(program2) {
|
|
|
75891
76148
|
});
|
|
75892
76149
|
}
|
|
75893
76150
|
function absolutePathFor(spelled, cwd) {
|
|
75894
|
-
const expanded = spelled === "~" || spelled.startsWith("~/") ?
|
|
75895
|
-
if (
|
|
75896
|
-
return cwd ?
|
|
76151
|
+
const expanded = spelled === "~" || spelled.startsWith("~/") ? import_path76.default.join(import_os63.default.homedir(), spelled.slice(1)) : spelled;
|
|
76152
|
+
if (import_path76.default.isAbsolute(expanded)) return expanded;
|
|
76153
|
+
return cwd ? import_path76.default.resolve(cwd, expanded) : import_path76.default.resolve(expanded);
|
|
75897
76154
|
}
|
|
75898
76155
|
async function carryTaintAcrossWrites(command, cwd) {
|
|
75899
76156
|
let pairs;
|
|
@@ -75912,23 +76169,23 @@ async function carryTaintAcrossWrites(command, cwd) {
|
|
|
75912
76169
|
continue;
|
|
75913
76170
|
}
|
|
75914
76171
|
const sensitive = scanFilePath(src, cwd);
|
|
75915
|
-
if (sensitive) await notifyTaint(dst, `copy:${sensitive.patternName}:${
|
|
76172
|
+
if (sensitive) await notifyTaint(dst, `copy:${sensitive.patternName}:${import_path76.default.basename(src)}`);
|
|
75916
76173
|
}
|
|
75917
76174
|
}
|
|
75918
76175
|
|
|
75919
76176
|
// src/cli/commands/shield.ts
|
|
75920
76177
|
init_cjs_shims();
|
|
75921
76178
|
var import_chalk16 = __toESM(require("chalk"));
|
|
75922
|
-
var
|
|
75923
|
-
var
|
|
75924
|
-
var
|
|
76179
|
+
var import_fs78 = __toESM(require("fs"));
|
|
76180
|
+
var import_path78 = __toESM(require("path"));
|
|
76181
|
+
var import_os64 = __toESM(require("os"));
|
|
75925
76182
|
init_shields();
|
|
75926
76183
|
init_build();
|
|
75927
76184
|
|
|
75928
76185
|
// src/shields/create.ts
|
|
75929
76186
|
init_cjs_shims();
|
|
75930
|
-
var
|
|
75931
|
-
var
|
|
76187
|
+
var import_fs77 = __toESM(require("fs"));
|
|
76188
|
+
var import_path77 = __toESM(require("path"));
|
|
75932
76189
|
init_dist();
|
|
75933
76190
|
init_shields();
|
|
75934
76191
|
init_audit();
|
|
@@ -75948,8 +76205,8 @@ function createShield(def, opts = {}) {
|
|
|
75948
76205
|
error: `"${name}" is a built-in shield \u2014 choose a different name (a user shield with this name would shadow the built-in).`
|
|
75949
76206
|
};
|
|
75950
76207
|
}
|
|
75951
|
-
const filePath =
|
|
75952
|
-
if (!opts.overwrite &&
|
|
76208
|
+
const filePath = import_path77.default.join(USER_SHIELDS_DIR_PATH, `${name}.json`);
|
|
76209
|
+
if (!opts.overwrite && import_fs77.default.existsSync(filePath)) {
|
|
75953
76210
|
return {
|
|
75954
76211
|
ok: false,
|
|
75955
76212
|
error: `Shield "${name}" already exists at ${filePath}. Pass --overwrite to replace it.`
|
|
@@ -76047,8 +76304,8 @@ var COMMUNITY_INDEX_URL = "https://raw.githubusercontent.com/node9ai/node9-proxy
|
|
|
76047
76304
|
function readCloudShields() {
|
|
76048
76305
|
const out = /* @__PURE__ */ new Set();
|
|
76049
76306
|
try {
|
|
76050
|
-
const file2 =
|
|
76051
|
-
const raw = JSON.parse(
|
|
76307
|
+
const file2 = import_path78.default.join(import_os64.default.homedir(), ".node9", "rules-cache.json");
|
|
76308
|
+
const raw = JSON.parse(import_fs78.default.readFileSync(file2, "utf-8"));
|
|
76052
76309
|
for (const r of raw.rules ?? []) {
|
|
76053
76310
|
const rule = r;
|
|
76054
76311
|
const fromSource = rule.source?.startsWith("SHIELD:") ? rule.source.slice("SHIELD:".length).toLowerCase() : void 0;
|
|
@@ -76385,7 +76642,7 @@ function registerShieldCommand(program2) {
|
|
|
76385
76642
|
if (opts.fromFile) {
|
|
76386
76643
|
let raw;
|
|
76387
76644
|
try {
|
|
76388
|
-
raw = JSON.parse(
|
|
76645
|
+
raw = JSON.parse(import_fs78.default.readFileSync(opts.fromFile, "utf-8"));
|
|
76389
76646
|
} catch (err2) {
|
|
76390
76647
|
console.error(
|
|
76391
76648
|
import_chalk16.default.red(`
|
|
@@ -76733,9 +76990,9 @@ init_migrate();
|
|
|
76733
76990
|
// src/cli/commands/doctor.ts
|
|
76734
76991
|
init_cjs_shims();
|
|
76735
76992
|
var import_chalk19 = __toESM(require("chalk"));
|
|
76736
|
-
var
|
|
76737
|
-
var
|
|
76738
|
-
var
|
|
76993
|
+
var import_fs80 = __toESM(require("fs"));
|
|
76994
|
+
var import_path80 = __toESM(require("path"));
|
|
76995
|
+
var import_os66 = __toESM(require("os"));
|
|
76739
76996
|
var import_child_process10 = require("child_process");
|
|
76740
76997
|
init_daemon();
|
|
76741
76998
|
init_build_id();
|
|
@@ -76764,22 +77021,22 @@ init_startup_log();
|
|
|
76764
77021
|
|
|
76765
77022
|
// src/utils/undo-leftovers.ts
|
|
76766
77023
|
init_cjs_shims();
|
|
76767
|
-
var
|
|
76768
|
-
var
|
|
76769
|
-
var
|
|
77024
|
+
var import_fs79 = __toESM(require("fs"));
|
|
77025
|
+
var import_os65 = __toESM(require("os"));
|
|
77026
|
+
var import_path79 = __toESM(require("path"));
|
|
76770
77027
|
function candidates(homeDir2) {
|
|
76771
|
-
const node9Dir =
|
|
77028
|
+
const node9Dir = import_path79.default.join(homeDir2, ".node9");
|
|
76772
77029
|
return [
|
|
76773
|
-
|
|
76774
|
-
|
|
76775
|
-
|
|
77030
|
+
import_path79.default.join(node9Dir, "snapshots"),
|
|
77031
|
+
import_path79.default.join(node9Dir, "snapshots.json"),
|
|
77032
|
+
import_path79.default.join(node9Dir, "undo_latest.txt")
|
|
76776
77033
|
];
|
|
76777
77034
|
}
|
|
76778
|
-
function undoLeftoverPaths(homeDir2 =
|
|
77035
|
+
function undoLeftoverPaths(homeDir2 = import_os65.default.homedir()) {
|
|
76779
77036
|
const found = [];
|
|
76780
77037
|
for (const p of candidates(homeDir2)) {
|
|
76781
77038
|
try {
|
|
76782
|
-
|
|
77039
|
+
import_fs79.default.lstatSync(p);
|
|
76783
77040
|
found.push(p);
|
|
76784
77041
|
} catch (err2) {
|
|
76785
77042
|
if (err2.code !== "ENOENT") found.push(p);
|
|
@@ -76787,11 +77044,11 @@ function undoLeftoverPaths(homeDir2 = import_os64.default.homedir()) {
|
|
|
76787
77044
|
}
|
|
76788
77045
|
return found;
|
|
76789
77046
|
}
|
|
76790
|
-
function purgeUndoLeftovers(homeDir2 =
|
|
77047
|
+
function purgeUndoLeftovers(homeDir2 = import_os65.default.homedir()) {
|
|
76791
77048
|
const out = { deleted: [], skipped: [], failed: [] };
|
|
76792
77049
|
for (const p of undoLeftoverPaths(homeDir2)) {
|
|
76793
77050
|
try {
|
|
76794
|
-
if (
|
|
77051
|
+
if (import_fs79.default.lstatSync(p).isSymbolicLink()) {
|
|
76795
77052
|
out.skipped.push({
|
|
76796
77053
|
path: p,
|
|
76797
77054
|
reason: "is a symlink \u2014 remove it yourself so nothing else is followed"
|
|
@@ -76804,11 +77061,11 @@ function purgeUndoLeftovers(homeDir2 = import_os64.default.homedir()) {
|
|
|
76804
77061
|
}
|
|
76805
77062
|
let reason = null;
|
|
76806
77063
|
try {
|
|
76807
|
-
|
|
77064
|
+
import_fs79.default.rmSync(p, { recursive: true, force: true });
|
|
76808
77065
|
} catch (err2) {
|
|
76809
77066
|
reason = err2.message;
|
|
76810
77067
|
}
|
|
76811
|
-
if (
|
|
77068
|
+
if (import_fs79.default.existsSync(p)) {
|
|
76812
77069
|
out.failed.push({ path: p, reason: reason ?? "still present after removal" });
|
|
76813
77070
|
} else {
|
|
76814
77071
|
out.deleted.push(p);
|
|
@@ -76824,7 +77081,7 @@ function keyRejected(health) {
|
|
|
76824
77081
|
}
|
|
76825
77082
|
function registerDoctorCommand(program2, version2) {
|
|
76826
77083
|
program2.command("doctor").description("Check that Node9 is installed and configured correctly").action(async () => {
|
|
76827
|
-
const homeDir2 =
|
|
77084
|
+
const homeDir2 = import_os66.default.homedir();
|
|
76828
77085
|
let failures = 0;
|
|
76829
77086
|
let warnings = 0;
|
|
76830
77087
|
function pass(msg) {
|
|
@@ -76878,10 +77135,10 @@ function registerDoctorCommand(program2, version2) {
|
|
|
76878
77135
|
"Policy source: workspace config (app.node9.ai) \u2014 local config files govern operational settings only"
|
|
76879
77136
|
);
|
|
76880
77137
|
}
|
|
76881
|
-
const globalConfigPath2 =
|
|
76882
|
-
if (
|
|
77138
|
+
const globalConfigPath2 = import_path80.default.join(homeDir2, ".node9", "config.json");
|
|
77139
|
+
if (import_fs80.default.existsSync(globalConfigPath2)) {
|
|
76883
77140
|
try {
|
|
76884
|
-
JSON.parse(
|
|
77141
|
+
JSON.parse(import_fs80.default.readFileSync(globalConfigPath2, "utf-8"));
|
|
76885
77142
|
pass(
|
|
76886
77143
|
wsGoverned ? "~/.node9/config.json found and valid (policy fields ignored \u2014 workspace governs)" : "~/.node9/config.json found and valid"
|
|
76887
77144
|
);
|
|
@@ -76900,10 +77157,10 @@ function registerDoctorCommand(program2, version2) {
|
|
|
76900
77157
|
"Remove them when ready: node9 undo --purge"
|
|
76901
77158
|
);
|
|
76902
77159
|
}
|
|
76903
|
-
const projectConfigPath =
|
|
76904
|
-
if (
|
|
77160
|
+
const projectConfigPath = import_path80.default.join(process.cwd(), "node9.config.json");
|
|
77161
|
+
if (import_fs80.default.existsSync(projectConfigPath)) {
|
|
76905
77162
|
try {
|
|
76906
|
-
JSON.parse(
|
|
77163
|
+
JSON.parse(import_fs80.default.readFileSync(projectConfigPath, "utf-8"));
|
|
76907
77164
|
pass("node9.config.json found and valid (project)");
|
|
76908
77165
|
} catch {
|
|
76909
77166
|
fail2(
|
|
@@ -76912,8 +77169,8 @@ function registerDoctorCommand(program2, version2) {
|
|
|
76912
77169
|
);
|
|
76913
77170
|
}
|
|
76914
77171
|
}
|
|
76915
|
-
const credsPath =
|
|
76916
|
-
if (
|
|
77172
|
+
const credsPath = import_path80.default.join(homeDir2, ".node9", "credentials.json");
|
|
77173
|
+
if (import_fs80.default.existsSync(credsPath)) {
|
|
76917
77174
|
pass("Cloud credentials found (~/.node9/credentials.json)");
|
|
76918
77175
|
} else {
|
|
76919
77176
|
warn(
|
|
@@ -76967,7 +77224,7 @@ function registerDoctorCommand(program2, version2) {
|
|
|
76967
77224
|
)
|
|
76968
77225
|
);
|
|
76969
77226
|
}
|
|
76970
|
-
const cloudOn =
|
|
77227
|
+
const cloudOn = import_fs80.default.existsSync(import_path80.default.join(homeDir2, ".node9", "credentials.json")) && !!getConfig().settings.approvers?.cloud;
|
|
76971
77228
|
section(cloudOn ? "Daemon" : "Daemon (optional)");
|
|
76972
77229
|
if (isDaemonRunning()) {
|
|
76973
77230
|
pass(
|
|
@@ -77005,7 +77262,7 @@ function registerDoctorCommand(program2, version2) {
|
|
|
77005
77262
|
cloudEnabled: !!getConfig().settings.approvers?.cloud
|
|
77006
77263
|
});
|
|
77007
77264
|
if (autostart) warn(autostart.message, autostart.hint);
|
|
77008
|
-
if (
|
|
77265
|
+
if (import_fs80.default.existsSync(import_path80.default.join(import_os66.default.homedir(), ".node9", "credentials.json")) && getConfig().settings.approvers?.cloud) {
|
|
77009
77266
|
section("Policy sync");
|
|
77010
77267
|
const health = readSyncHealth();
|
|
77011
77268
|
if (keyRejected(health)) {
|
|
@@ -77031,7 +77288,7 @@ function registerDoctorCommand(program2, version2) {
|
|
|
77031
77288
|
try {
|
|
77032
77289
|
const { shipLagBytes: shipLagBytes2, readWatermark: readWatermark2, AUDIT_SHIP_WATERMARK: AUDIT_SHIP_WATERMARK2 } = await Promise.resolve().then(() => (init_audit_shipper(), audit_shipper_exports));
|
|
77033
77290
|
const cfg = getConfig();
|
|
77034
|
-
const creds =
|
|
77291
|
+
const creds = import_fs80.default.existsSync(import_path80.default.join(import_os66.default.homedir(), ".node9", "credentials.json"));
|
|
77035
77292
|
if (!creds) {
|
|
77036
77293
|
warn("Not logged in \u2014 audit rows stay local", "Run: node9 login <api-key>");
|
|
77037
77294
|
} else if (!cfg.settings.approvers.cloud) {
|
|
@@ -77097,10 +77354,10 @@ function registerDoctorCommand(program2, version2) {
|
|
|
77097
77354
|
// src/cli/commands/audit.ts
|
|
77098
77355
|
init_cjs_shims();
|
|
77099
77356
|
var import_chalk20 = __toESM(require("chalk"));
|
|
77100
|
-
var
|
|
77101
|
-
var
|
|
77357
|
+
var import_fs81 = __toESM(require("fs"));
|
|
77358
|
+
var import_path81 = __toESM(require("path"));
|
|
77102
77359
|
init_decision();
|
|
77103
|
-
var
|
|
77360
|
+
var import_os67 = __toESM(require("os"));
|
|
77104
77361
|
function formatRelativeTime(timestamp2) {
|
|
77105
77362
|
const diff = Date.now() - new Date(timestamp2).getTime();
|
|
77106
77363
|
const sec = Math.floor(diff / 1e3);
|
|
@@ -77113,14 +77370,14 @@ function formatRelativeTime(timestamp2) {
|
|
|
77113
77370
|
}
|
|
77114
77371
|
function registerAuditCommand(program2) {
|
|
77115
77372
|
program2.command("audit").description("View local execution audit log").option("--tail <n>", "Number of entries to show", "20").option("--tool <pattern>", "Filter by tool name (substring match)").option("--deny", "Show only denied actions").option("--json", "Output raw JSON").action((options) => {
|
|
77116
|
-
const logPath =
|
|
77117
|
-
if (!
|
|
77373
|
+
const logPath = import_path81.default.join(import_os67.default.homedir(), ".node9", "audit.log");
|
|
77374
|
+
if (!import_fs81.default.existsSync(logPath)) {
|
|
77118
77375
|
console.log(
|
|
77119
77376
|
import_chalk20.default.yellow("No audit logs found. Run node9 with an agent to generate entries.")
|
|
77120
77377
|
);
|
|
77121
77378
|
return;
|
|
77122
77379
|
}
|
|
77123
|
-
const raw =
|
|
77380
|
+
const raw = import_fs81.default.readFileSync(logPath, "utf-8");
|
|
77124
77381
|
const lines = raw.split("\n").filter((l) => l.trim() !== "");
|
|
77125
77382
|
let entries = lines.flatMap((line) => {
|
|
77126
77383
|
try {
|
|
@@ -77183,7 +77440,7 @@ init_cjs_shims();
|
|
|
77183
77440
|
|
|
77184
77441
|
// src/apps/report.ts
|
|
77185
77442
|
init_cjs_shims();
|
|
77186
|
-
var
|
|
77443
|
+
var import_fs82 = __toESM(require("fs"));
|
|
77187
77444
|
init_catalog();
|
|
77188
77445
|
init_dist();
|
|
77189
77446
|
function appsReportLines(file2, activeShields, opts = {}) {
|
|
@@ -77213,17 +77470,17 @@ var AUDIT_TAIL_BYTES2 = 5 * 1024 * 1024;
|
|
|
77213
77470
|
function readTail2(file2) {
|
|
77214
77471
|
let fd;
|
|
77215
77472
|
try {
|
|
77216
|
-
fd =
|
|
77217
|
-
const size =
|
|
77473
|
+
fd = import_fs82.default.openSync(file2, "r");
|
|
77474
|
+
const size = import_fs82.default.fstatSync(fd).size;
|
|
77218
77475
|
const start = Math.max(0, size - AUDIT_TAIL_BYTES2);
|
|
77219
77476
|
const buf = Buffer.alloc(size - start);
|
|
77220
|
-
|
|
77477
|
+
import_fs82.default.readSync(fd, buf, 0, buf.length, start);
|
|
77221
77478
|
const text = buf.toString("utf8");
|
|
77222
77479
|
return start > 0 ? text.slice(text.indexOf("\n") + 1) : text;
|
|
77223
77480
|
} catch {
|
|
77224
77481
|
return "";
|
|
77225
77482
|
} finally {
|
|
77226
|
-
if (fd !== void 0)
|
|
77483
|
+
if (fd !== void 0) import_fs82.default.closeSync(fd);
|
|
77227
77484
|
}
|
|
77228
77485
|
}
|
|
77229
77486
|
function approvalsFromAudit(auditFile, sinceMs) {
|
|
@@ -77278,21 +77535,21 @@ init_detect();
|
|
|
77278
77535
|
|
|
77279
77536
|
// src/apps/nudges.ts
|
|
77280
77537
|
init_cjs_shims();
|
|
77281
|
-
var
|
|
77282
|
-
var
|
|
77283
|
-
var
|
|
77538
|
+
var import_fs83 = __toESM(require("fs"));
|
|
77539
|
+
var import_os68 = __toESM(require("os"));
|
|
77540
|
+
var import_path82 = __toESM(require("path"));
|
|
77284
77541
|
var import_child_process11 = require("child_process");
|
|
77285
77542
|
var UNANSWERED_AT = 3;
|
|
77286
77543
|
var QUESTIONS_AT = 10;
|
|
77287
77544
|
var TEAM_AUTHORS_AT = 2;
|
|
77288
77545
|
var TEAM_PROJECTS = 5;
|
|
77289
77546
|
var GIT_TIMEOUT_MS = 2e3;
|
|
77290
|
-
function nudgesFilePath(home =
|
|
77291
|
-
return
|
|
77547
|
+
function nudgesFilePath(home = import_os68.default.homedir()) {
|
|
77548
|
+
return import_path82.default.join(home, ".node9", "nudges.json");
|
|
77292
77549
|
}
|
|
77293
77550
|
function readShownNudges(home) {
|
|
77294
77551
|
try {
|
|
77295
|
-
const raw = JSON.parse(
|
|
77552
|
+
const raw = JSON.parse(import_fs83.default.readFileSync(nudgesFilePath(home), "utf8"));
|
|
77296
77553
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return /* @__PURE__ */ new Set();
|
|
77297
77554
|
return new Set(
|
|
77298
77555
|
Object.keys(raw).filter(
|
|
@@ -77307,14 +77564,14 @@ function markNudgeShown(key, home, now = /* @__PURE__ */ new Date()) {
|
|
|
77307
77564
|
const file2 = nudgesFilePath(home);
|
|
77308
77565
|
let data = {};
|
|
77309
77566
|
try {
|
|
77310
|
-
const raw = JSON.parse(
|
|
77567
|
+
const raw = JSON.parse(import_fs83.default.readFileSync(file2, "utf8"));
|
|
77311
77568
|
if (raw && typeof raw === "object" && !Array.isArray(raw)) data = raw;
|
|
77312
77569
|
} catch {
|
|
77313
77570
|
}
|
|
77314
77571
|
data[key] = now.toISOString();
|
|
77315
77572
|
try {
|
|
77316
|
-
|
|
77317
|
-
|
|
77573
|
+
import_fs83.default.mkdirSync(import_path82.default.dirname(file2), { recursive: true });
|
|
77574
|
+
import_fs83.default.writeFileSync(file2, JSON.stringify(data, null, 2) + "\n", { mode: 384 });
|
|
77318
77575
|
} catch {
|
|
77319
77576
|
}
|
|
77320
77577
|
}
|
|
@@ -77335,7 +77592,7 @@ function recentAuthorCount(dir2) {
|
|
|
77335
77592
|
}
|
|
77336
77593
|
function teamProject(dirs, countAuthors = recentAuthorCount) {
|
|
77337
77594
|
for (const dir2 of dirs.slice(0, TEAM_PROJECTS)) {
|
|
77338
|
-
if (countAuthors(dir2) >= TEAM_AUTHORS_AT) return
|
|
77595
|
+
if (countAuthors(dir2) >= TEAM_AUTHORS_AT) return import_path82.default.basename(dir2);
|
|
77339
77596
|
}
|
|
77340
77597
|
return void 0;
|
|
77341
77598
|
}
|
|
@@ -77370,9 +77627,9 @@ var import_chalk22 = __toESM(require("chalk"));
|
|
|
77370
77627
|
|
|
77371
77628
|
// src/cli/aggregate/report-audit.ts
|
|
77372
77629
|
init_cjs_shims();
|
|
77373
|
-
var
|
|
77374
|
-
var
|
|
77375
|
-
var
|
|
77630
|
+
var import_fs84 = __toESM(require("fs"));
|
|
77631
|
+
var import_os69 = __toESM(require("os"));
|
|
77632
|
+
var import_path83 = __toESM(require("path"));
|
|
77376
77633
|
init_costSync();
|
|
77377
77634
|
init_litellm();
|
|
77378
77635
|
init_cost_codex();
|
|
@@ -77457,8 +77714,8 @@ function getDateRange(period, now) {
|
|
|
77457
77714
|
}
|
|
77458
77715
|
}
|
|
77459
77716
|
function parseAuditLog(logPath) {
|
|
77460
|
-
if (!
|
|
77461
|
-
const raw =
|
|
77717
|
+
if (!import_fs84.default.existsSync(logPath)) return [];
|
|
77718
|
+
const raw = import_fs84.default.readFileSync(logPath, "utf-8");
|
|
77462
77719
|
return raw.split("\n").flatMap((line) => {
|
|
77463
77720
|
if (!line.trim()) return [];
|
|
77464
77721
|
try {
|
|
@@ -77512,10 +77769,10 @@ function freezeClaudeCost(acc) {
|
|
|
77512
77769
|
};
|
|
77513
77770
|
}
|
|
77514
77771
|
function processClaudeCostProject(proj, projectsDir, start, end, acc) {
|
|
77515
|
-
const projPath =
|
|
77772
|
+
const projPath = import_path83.default.join(projectsDir, proj);
|
|
77516
77773
|
let files;
|
|
77517
77774
|
try {
|
|
77518
|
-
const stat =
|
|
77775
|
+
const stat = import_fs84.default.statSync(projPath);
|
|
77519
77776
|
if (!stat.isDirectory()) return;
|
|
77520
77777
|
files = listSessionFiles(projPath);
|
|
77521
77778
|
} catch {
|
|
@@ -77523,14 +77780,14 @@ function processClaudeCostProject(proj, projectsDir, start, end, acc) {
|
|
|
77523
77780
|
}
|
|
77524
77781
|
const startMs = start.getTime();
|
|
77525
77782
|
for (const file2 of files) {
|
|
77526
|
-
const filePath =
|
|
77783
|
+
const filePath = import_path83.default.join(projPath, file2);
|
|
77527
77784
|
try {
|
|
77528
|
-
if (
|
|
77785
|
+
if (import_fs84.default.statSync(filePath).mtimeMs < startMs) continue;
|
|
77529
77786
|
} catch {
|
|
77530
77787
|
continue;
|
|
77531
77788
|
}
|
|
77532
77789
|
try {
|
|
77533
|
-
const raw =
|
|
77790
|
+
const raw = import_fs84.default.readFileSync(filePath, "utf-8");
|
|
77534
77791
|
for (const line of raw.split("\n")) {
|
|
77535
77792
|
if (!line.trim()) continue;
|
|
77536
77793
|
let entry;
|
|
@@ -77580,10 +77837,10 @@ function processClaudeCostProject(proj, projectsDir, start, end, acc) {
|
|
|
77580
77837
|
}
|
|
77581
77838
|
function loadClaudeCost(start, end, projectsDir) {
|
|
77582
77839
|
const acc = emptyClaudeCostAccumulator();
|
|
77583
|
-
if (!
|
|
77840
|
+
if (!import_fs84.default.existsSync(projectsDir)) return freezeClaudeCost(acc);
|
|
77584
77841
|
let dirs;
|
|
77585
77842
|
try {
|
|
77586
|
-
dirs =
|
|
77843
|
+
dirs = import_fs84.default.readdirSync(projectsDir);
|
|
77587
77844
|
} catch {
|
|
77588
77845
|
return freezeClaudeCost(acc);
|
|
77589
77846
|
}
|
|
@@ -77595,7 +77852,7 @@ function loadClaudeCost(start, end, projectsDir) {
|
|
|
77595
77852
|
function processCodexCostFile(filePath, start, end, acc) {
|
|
77596
77853
|
let lines;
|
|
77597
77854
|
try {
|
|
77598
|
-
lines =
|
|
77855
|
+
lines = import_fs84.default.readFileSync(filePath, "utf-8").split("\n");
|
|
77599
77856
|
} catch {
|
|
77600
77857
|
return;
|
|
77601
77858
|
}
|
|
@@ -77670,13 +77927,13 @@ function freezeGeminiCost(acc) {
|
|
|
77670
77927
|
function processGeminiCostFile(filePath, projectKey, start, end, acc) {
|
|
77671
77928
|
const startMs = start.getTime();
|
|
77672
77929
|
try {
|
|
77673
|
-
if (
|
|
77930
|
+
if (import_fs84.default.statSync(filePath).mtimeMs < startMs) return;
|
|
77674
77931
|
} catch {
|
|
77675
77932
|
return;
|
|
77676
77933
|
}
|
|
77677
77934
|
let raw;
|
|
77678
77935
|
try {
|
|
77679
|
-
raw =
|
|
77936
|
+
raw = import_fs84.default.readFileSync(filePath, "utf-8");
|
|
77680
77937
|
} catch {
|
|
77681
77938
|
return;
|
|
77682
77939
|
}
|
|
@@ -77725,30 +77982,30 @@ function listGeminiSessionFiles2(geminiTmpDir2) {
|
|
|
77725
77982
|
const out = [];
|
|
77726
77983
|
let dirs;
|
|
77727
77984
|
try {
|
|
77728
|
-
if (!
|
|
77729
|
-
dirs =
|
|
77985
|
+
if (!import_fs84.default.statSync(geminiTmpDir2).isDirectory()) return out;
|
|
77986
|
+
dirs = import_fs84.default.readdirSync(geminiTmpDir2);
|
|
77730
77987
|
} catch {
|
|
77731
77988
|
return out;
|
|
77732
77989
|
}
|
|
77733
77990
|
for (const proj of dirs) {
|
|
77734
|
-
const chatsDir =
|
|
77991
|
+
const chatsDir = import_path83.default.join(geminiTmpDir2, proj, "chats");
|
|
77735
77992
|
let files;
|
|
77736
77993
|
try {
|
|
77737
|
-
if (!
|
|
77738
|
-
files =
|
|
77994
|
+
if (!import_fs84.default.statSync(chatsDir).isDirectory()) continue;
|
|
77995
|
+
files = import_fs84.default.readdirSync(chatsDir);
|
|
77739
77996
|
} catch {
|
|
77740
77997
|
continue;
|
|
77741
77998
|
}
|
|
77742
77999
|
for (const f of files) {
|
|
77743
78000
|
if (!f.endsWith(".jsonl")) continue;
|
|
77744
|
-
out.push({ projectKey: proj, file:
|
|
78001
|
+
out.push({ projectKey: proj, file: import_path83.default.join(chatsDir, f) });
|
|
77745
78002
|
}
|
|
77746
78003
|
}
|
|
77747
78004
|
return out;
|
|
77748
78005
|
}
|
|
77749
78006
|
function loadGeminiCost(start, end, geminiTmpDir2) {
|
|
77750
78007
|
const acc = emptyGeminiAccumulator();
|
|
77751
|
-
if (!
|
|
78008
|
+
if (!import_fs84.default.existsSync(geminiTmpDir2)) return freezeGeminiCost(acc);
|
|
77752
78009
|
for (const { projectKey, file: file2 } of listGeminiSessionFiles2(geminiTmpDir2)) {
|
|
77753
78010
|
processGeminiCostFile(file2, projectKey, start, end, acc);
|
|
77754
78011
|
}
|
|
@@ -77769,11 +78026,11 @@ function dimensionOfBlock(checkedBy, ruleName) {
|
|
|
77769
78026
|
}
|
|
77770
78027
|
function aggregateReportFromAudit(period, opts = {}) {
|
|
77771
78028
|
const now = opts.now ?? /* @__PURE__ */ new Date();
|
|
77772
|
-
const auditLogPath = opts.auditLogPath ??
|
|
77773
|
-
const claudeProjectsDir = opts.claudeProjectsDir ??
|
|
78029
|
+
const auditLogPath = opts.auditLogPath ?? import_path83.default.join(import_os69.default.homedir(), ".node9", "audit.log");
|
|
78030
|
+
const claudeProjectsDir = opts.claudeProjectsDir ?? import_path83.default.join(import_os69.default.homedir(), ".claude", "projects");
|
|
77774
78031
|
const codexSessionsDir2 = opts.codexSessionsDir ?? codexSessionsDir();
|
|
77775
|
-
const geminiTmpDir2 = opts.geminiTmpDir ??
|
|
77776
|
-
const hasAuditFile =
|
|
78032
|
+
const geminiTmpDir2 = opts.geminiTmpDir ?? import_path83.default.join(import_os69.default.homedir(), ".gemini", "tmp");
|
|
78033
|
+
const hasAuditFile = import_fs84.default.existsSync(auditLogPath);
|
|
77777
78034
|
const allEntries = opts.preloadedAuditEntries ?? parseAuditLog(auditLogPath);
|
|
77778
78035
|
const unackedDlp = allEntries.filter((e) => e.source === "response-dlp");
|
|
77779
78036
|
const { start, end } = getDateRange(period, now);
|
|
@@ -78059,10 +78316,10 @@ function buildReportJson(input) {
|
|
|
78059
78316
|
// src/cli/commands/sessions.ts
|
|
78060
78317
|
init_cjs_shims();
|
|
78061
78318
|
var import_chalk21 = __toESM(require("chalk"));
|
|
78062
|
-
var
|
|
78063
|
-
var
|
|
78319
|
+
var import_fs85 = __toESM(require("fs"));
|
|
78320
|
+
var import_path84 = __toESM(require("path"));
|
|
78064
78321
|
init_decision();
|
|
78065
|
-
var
|
|
78322
|
+
var import_os70 = __toESM(require("os"));
|
|
78066
78323
|
init_scan_summary();
|
|
78067
78324
|
init_litellm();
|
|
78068
78325
|
init_cost_gemini();
|
|
@@ -78083,10 +78340,10 @@ function encodeProjectPath(projectPath) {
|
|
|
78083
78340
|
}
|
|
78084
78341
|
function sessionJsonlPath(projectPath, sessionId) {
|
|
78085
78342
|
const encoded = encodeProjectPath(projectPath);
|
|
78086
|
-
return
|
|
78343
|
+
return import_path84.default.join(import_os70.default.homedir(), ".claude", "projects", encoded, `${sessionId}.jsonl`);
|
|
78087
78344
|
}
|
|
78088
78345
|
function projectLabel(projectPath) {
|
|
78089
|
-
return projectPath.replace(
|
|
78346
|
+
return projectPath.replace(import_os70.default.homedir(), "~");
|
|
78090
78347
|
}
|
|
78091
78348
|
function parseHistoryLines(lines) {
|
|
78092
78349
|
const entries = [];
|
|
@@ -78155,10 +78412,10 @@ function parseSessionLines(lines) {
|
|
|
78155
78412
|
return { toolCalls, costUSD, hasSnapshot, modifiedFiles };
|
|
78156
78413
|
}
|
|
78157
78414
|
function loadAuditEntries(auditPath) {
|
|
78158
|
-
const aPath = auditPath ??
|
|
78415
|
+
const aPath = auditPath ?? import_path84.default.join(import_os70.default.homedir(), ".node9", "audit.log");
|
|
78159
78416
|
let raw;
|
|
78160
78417
|
try {
|
|
78161
|
-
raw =
|
|
78418
|
+
raw = import_fs85.default.readFileSync(aPath, "utf-8");
|
|
78162
78419
|
} catch {
|
|
78163
78420
|
return [];
|
|
78164
78421
|
}
|
|
@@ -78194,8 +78451,8 @@ function auditEntriesInWindow(entries, windowStart, windowEnd) {
|
|
|
78194
78451
|
return result;
|
|
78195
78452
|
}
|
|
78196
78453
|
function buildGeminiSessions(days, allAuditEntries) {
|
|
78197
|
-
const tmpDir =
|
|
78198
|
-
if (!
|
|
78454
|
+
const tmpDir = import_path84.default.join(import_os70.default.homedir(), ".gemini", "tmp");
|
|
78455
|
+
if (!import_fs85.default.existsSync(tmpDir)) return [];
|
|
78199
78456
|
const cutoff = days !== null ? (() => {
|
|
78200
78457
|
const d = /* @__PURE__ */ new Date();
|
|
78201
78458
|
d.setDate(d.getDate() - days);
|
|
@@ -78204,35 +78461,35 @@ function buildGeminiSessions(days, allAuditEntries) {
|
|
|
78204
78461
|
})() : null;
|
|
78205
78462
|
let slugDirs;
|
|
78206
78463
|
try {
|
|
78207
|
-
slugDirs =
|
|
78464
|
+
slugDirs = import_fs85.default.readdirSync(tmpDir);
|
|
78208
78465
|
} catch {
|
|
78209
78466
|
return [];
|
|
78210
78467
|
}
|
|
78211
78468
|
const summaries = [];
|
|
78212
78469
|
for (const slug2 of slugDirs) {
|
|
78213
|
-
const slugPath =
|
|
78470
|
+
const slugPath = import_path84.default.join(tmpDir, slug2);
|
|
78214
78471
|
try {
|
|
78215
|
-
if (!
|
|
78472
|
+
if (!import_fs85.default.statSync(slugPath).isDirectory()) continue;
|
|
78216
78473
|
} catch {
|
|
78217
78474
|
continue;
|
|
78218
78475
|
}
|
|
78219
|
-
let projectRoot =
|
|
78476
|
+
let projectRoot = import_path84.default.join(import_os70.default.homedir(), slug2);
|
|
78220
78477
|
try {
|
|
78221
|
-
projectRoot =
|
|
78478
|
+
projectRoot = import_fs85.default.readFileSync(import_path84.default.join(slugPath, ".project_root"), "utf-8").trim();
|
|
78222
78479
|
} catch {
|
|
78223
78480
|
}
|
|
78224
|
-
const chatsDir =
|
|
78225
|
-
if (!
|
|
78481
|
+
const chatsDir = import_path84.default.join(slugPath, "chats");
|
|
78482
|
+
if (!import_fs85.default.existsSync(chatsDir)) continue;
|
|
78226
78483
|
let chatFiles;
|
|
78227
78484
|
try {
|
|
78228
|
-
chatFiles =
|
|
78485
|
+
chatFiles = import_fs85.default.readdirSync(chatsDir).filter((f) => f.endsWith(".json"));
|
|
78229
78486
|
} catch {
|
|
78230
78487
|
continue;
|
|
78231
78488
|
}
|
|
78232
78489
|
for (const chatFile of chatFiles) {
|
|
78233
78490
|
let raw;
|
|
78234
78491
|
try {
|
|
78235
|
-
raw =
|
|
78492
|
+
raw = import_fs85.default.readFileSync(import_path84.default.join(chatsDir, chatFile), "utf-8");
|
|
78236
78493
|
} catch {
|
|
78237
78494
|
continue;
|
|
78238
78495
|
}
|
|
@@ -78323,7 +78580,7 @@ function buildCodexSessions(days, allAuditEntries) {
|
|
|
78323
78580
|
for (const filePath of jsonlFiles) {
|
|
78324
78581
|
let lines;
|
|
78325
78582
|
try {
|
|
78326
|
-
lines =
|
|
78583
|
+
lines = import_fs85.default.readFileSync(filePath, "utf-8").split("\n");
|
|
78327
78584
|
} catch {
|
|
78328
78585
|
continue;
|
|
78329
78586
|
}
|
|
@@ -78394,10 +78651,10 @@ function buildCodexSessions(days, allAuditEntries) {
|
|
|
78394
78651
|
return summaries;
|
|
78395
78652
|
}
|
|
78396
78653
|
function buildSessions(days, historyPath) {
|
|
78397
|
-
const hPath = historyPath ??
|
|
78654
|
+
const hPath = historyPath ?? import_path84.default.join(import_os70.default.homedir(), ".claude", "history.jsonl");
|
|
78398
78655
|
let historyRaw = "";
|
|
78399
78656
|
try {
|
|
78400
|
-
historyRaw =
|
|
78657
|
+
historyRaw = import_fs85.default.readFileSync(hPath, "utf-8");
|
|
78401
78658
|
} catch {
|
|
78402
78659
|
}
|
|
78403
78660
|
const cutoff = days !== null ? (() => {
|
|
@@ -78421,7 +78678,7 @@ function buildSessions(days, historyPath) {
|
|
|
78421
78678
|
const jsonlFile = sessionJsonlPath(entry.project, entry.sessionId);
|
|
78422
78679
|
let sessionLines = [];
|
|
78423
78680
|
try {
|
|
78424
|
-
sessionLines =
|
|
78681
|
+
sessionLines = import_fs85.default.readFileSync(jsonlFile, "utf-8").split("\n");
|
|
78425
78682
|
} catch {
|
|
78426
78683
|
}
|
|
78427
78684
|
const { toolCalls, costUSD, hasSnapshot, modifiedFiles } = parseSessionLines(sessionLines);
|
|
@@ -79212,7 +79469,7 @@ init_cjs_shims();
|
|
|
79212
79469
|
var import_chalk23 = __toESM(require("chalk"));
|
|
79213
79470
|
var import_child_process12 = require("child_process");
|
|
79214
79471
|
init_daemon();
|
|
79215
|
-
var
|
|
79472
|
+
var import_fs86 = __toESM(require("fs"));
|
|
79216
79473
|
init_startup_log();
|
|
79217
79474
|
init_daemon3();
|
|
79218
79475
|
init_service();
|
|
@@ -79289,7 +79546,7 @@ function registerDaemonCommand(program2) {
|
|
|
79289
79546
|
child.unref();
|
|
79290
79547
|
if (restartFd !== void 0) {
|
|
79291
79548
|
try {
|
|
79292
|
-
|
|
79549
|
+
import_fs86.default.closeSync(restartFd);
|
|
79293
79550
|
} catch {
|
|
79294
79551
|
}
|
|
79295
79552
|
}
|
|
@@ -79340,7 +79597,7 @@ function registerDaemonCommand(program2) {
|
|
|
79340
79597
|
} finally {
|
|
79341
79598
|
if (startupFd !== void 0) {
|
|
79342
79599
|
try {
|
|
79343
|
-
|
|
79600
|
+
import_fs86.default.closeSync(startupFd);
|
|
79344
79601
|
} catch {
|
|
79345
79602
|
}
|
|
79346
79603
|
}
|
|
@@ -79355,9 +79612,9 @@ function registerDaemonCommand(program2) {
|
|
|
79355
79612
|
// src/cli/commands/status.ts
|
|
79356
79613
|
init_cjs_shims();
|
|
79357
79614
|
var import_chalk24 = __toESM(require("chalk"));
|
|
79358
|
-
var
|
|
79359
|
-
var
|
|
79360
|
-
var
|
|
79615
|
+
var import_fs87 = __toESM(require("fs"));
|
|
79616
|
+
var import_path85 = __toESM(require("path"));
|
|
79617
|
+
var import_os71 = __toESM(require("os"));
|
|
79361
79618
|
init_core();
|
|
79362
79619
|
init_daemon();
|
|
79363
79620
|
init_build_id();
|
|
@@ -79458,20 +79715,20 @@ function registerStatusCommand(program2) {
|
|
|
79458
79715
|
console.log(` Policy: ${import_chalk24.default.cyan("Workspace config (app.node9.ai)")}`);
|
|
79459
79716
|
}
|
|
79460
79717
|
const ignoredLabel = import_chalk24.default.gray("Present \u2014 ignored (workspace config governs)");
|
|
79461
|
-
const projectConfig =
|
|
79462
|
-
const globalConfig =
|
|
79718
|
+
const projectConfig = import_path85.default.join(process.cwd(), "node9.config.json");
|
|
79719
|
+
const globalConfig = import_path85.default.join(import_os71.default.homedir(), ".node9", "config.json");
|
|
79463
79720
|
console.log(
|
|
79464
|
-
` Local: ${
|
|
79721
|
+
` Local: ${import_fs87.default.existsSync(projectConfig) ? wsGoverned ? ignoredLabel : import_chalk24.default.green("Active (node9.config.json)") : import_chalk24.default.gray("Not present")}`
|
|
79465
79722
|
);
|
|
79466
79723
|
console.log(
|
|
79467
|
-
` Global: ${
|
|
79724
|
+
` Global: ${import_fs87.default.existsSync(globalConfig) ? wsGoverned ? ignoredLabel : import_chalk24.default.green("Active (~/.node9/config.json)") : import_chalk24.default.gray("Not present")}`
|
|
79468
79725
|
);
|
|
79469
79726
|
if (mergedConfig.policy.sandboxPaths.length > 0) {
|
|
79470
79727
|
console.log(
|
|
79471
79728
|
` Sandbox: ${import_chalk24.default.green(`${mergedConfig.policy.sandboxPaths.length} safe zones active`)}`
|
|
79472
79729
|
);
|
|
79473
79730
|
}
|
|
79474
|
-
const wiring = getAgentWiring(
|
|
79731
|
+
const wiring = getAgentWiring(import_os71.default.homedir()).filter((a) => a.present);
|
|
79475
79732
|
if (wiring.length > 0) {
|
|
79476
79733
|
console.log("");
|
|
79477
79734
|
console.log(import_chalk24.default.bold(" Agent Wiring:"));
|
|
@@ -79490,7 +79747,7 @@ function registerStatusCommand(program2) {
|
|
|
79490
79747
|
a.mcpServers
|
|
79491
79748
|
);
|
|
79492
79749
|
if (a.id === "codex" && a.hooks.some((h) => h.wired)) {
|
|
79493
|
-
const t = assessCodexTrust(
|
|
79750
|
+
const t = assessCodexTrust(import_os71.default.homedir());
|
|
79494
79751
|
if (t.state === "observed") {
|
|
79495
79752
|
console.log(
|
|
79496
79753
|
import_chalk24.default.green(
|
|
@@ -79534,7 +79791,7 @@ init_init();
|
|
|
79534
79791
|
// src/cli/commands/heal.ts
|
|
79535
79792
|
init_cjs_shims();
|
|
79536
79793
|
var import_chalk25 = __toESM(require("chalk"));
|
|
79537
|
-
var
|
|
79794
|
+
var import_fs90 = __toESM(require("fs"));
|
|
79538
79795
|
init_agent_wiring();
|
|
79539
79796
|
init_mcp_wrap();
|
|
79540
79797
|
init_setup();
|
|
@@ -79542,7 +79799,7 @@ init_hook_baseline();
|
|
|
79542
79799
|
var hasHookSurface = (a) => a.hooks.length > 0;
|
|
79543
79800
|
function backupForHeal(file2) {
|
|
79544
79801
|
try {
|
|
79545
|
-
if (file2 &&
|
|
79802
|
+
if (file2 && import_fs90.default.existsSync(file2)) import_fs90.default.copyFileSync(file2, `${file2}.node9-heal-bak`);
|
|
79546
79803
|
} catch {
|
|
79547
79804
|
}
|
|
79548
79805
|
}
|
|
@@ -80163,7 +80420,12 @@ async function runMcpGateway(upstreamCommand, configName) {
|
|
|
80163
80420
|
humanDecision,
|
|
80164
80421
|
result.reason,
|
|
80165
80422
|
void 0,
|
|
80166
|
-
{
|
|
80423
|
+
{
|
|
80424
|
+
kind: result.blockKind,
|
|
80425
|
+
path: result.blockedPath,
|
|
80426
|
+
redirect: !!result.redirect,
|
|
80427
|
+
ruleDescription: result.ruleDescription
|
|
80428
|
+
}
|
|
80167
80429
|
);
|
|
80168
80430
|
const errorResponse = {
|
|
80169
80431
|
jsonrpc: "2.0",
|
|
@@ -80507,9 +80769,9 @@ init_cjs_shims();
|
|
|
80507
80769
|
init_cjs_shims();
|
|
80508
80770
|
var import_readline4 = __toESM(require("readline"));
|
|
80509
80771
|
init_write();
|
|
80510
|
-
var
|
|
80511
|
-
var
|
|
80512
|
-
var
|
|
80772
|
+
var import_fs91 = __toESM(require("fs"));
|
|
80773
|
+
var import_os76 = __toESM(require("os"));
|
|
80774
|
+
var import_path90 = __toESM(require("path"));
|
|
80513
80775
|
var import_child_process14 = require("child_process");
|
|
80514
80776
|
init_decision();
|
|
80515
80777
|
init_core();
|
|
@@ -81060,14 +81322,14 @@ function handleStatus() {
|
|
|
81060
81322
|
const state = !a.installed ? "not installed" : hooked ? "wired" : a.isProtected ? "protected through MCP" : "not wired";
|
|
81061
81323
|
lines.push(` ${a.label}: ${state}`);
|
|
81062
81324
|
}
|
|
81063
|
-
const projectConfig =
|
|
81064
|
-
const globalConfig =
|
|
81325
|
+
const projectConfig = import_path90.default.join(process.cwd(), "node9.config.json");
|
|
81326
|
+
const globalConfig = import_path90.default.join(import_os76.default.homedir(), ".node9", "config.json");
|
|
81065
81327
|
const presentLabel = wsGoverned ? "present \u2014 ignored (workspace config governs)" : "present";
|
|
81066
81328
|
lines.push(
|
|
81067
|
-
`Project config (node9.config.json): ${
|
|
81329
|
+
`Project config (node9.config.json): ${import_fs91.default.existsSync(projectConfig) ? presentLabel : "not found"}`
|
|
81068
81330
|
);
|
|
81069
81331
|
lines.push(
|
|
81070
|
-
`Global config (~/.node9/config.json): ${
|
|
81332
|
+
`Global config (~/.node9/config.json): ${import_fs91.default.existsSync(globalConfig) ? presentLabel : "not found"}`
|
|
81071
81333
|
);
|
|
81072
81334
|
return lines.join("\n");
|
|
81073
81335
|
}
|
|
@@ -81204,7 +81466,7 @@ function handleEgressDeny(args) {
|
|
|
81204
81466
|
addEgressHost("deny", host2);
|
|
81205
81467
|
return `Denied egress to ${host2} (deny always wins over allow).`;
|
|
81206
81468
|
}
|
|
81207
|
-
var GLOBAL_CONFIG_PATH2 =
|
|
81469
|
+
var GLOBAL_CONFIG_PATH2 = import_path90.default.join(import_os76.default.homedir(), ".node9", "config.json");
|
|
81208
81470
|
var APPROVER_CHANNELS2 = ["native", "browser", "cloud", "terminal"];
|
|
81209
81471
|
function handleApproverList() {
|
|
81210
81472
|
const config = getConfig();
|
|
@@ -81245,9 +81507,9 @@ function handleApproverSet(args) {
|
|
|
81245
81507
|
function handleAuditGet(args) {
|
|
81246
81508
|
const limit = Math.min(typeof args.limit === "number" ? args.limit : 20, 100);
|
|
81247
81509
|
const filter = typeof args.filter === "string" && args.filter !== "all" ? args.filter : null;
|
|
81248
|
-
const auditPath =
|
|
81249
|
-
if (!
|
|
81250
|
-
const rawLines =
|
|
81510
|
+
const auditPath = import_path90.default.join(import_os76.default.homedir(), ".node9", "audit.log");
|
|
81511
|
+
if (!import_fs91.default.existsSync(auditPath)) return "No audit log found.";
|
|
81512
|
+
const rawLines = import_fs91.default.readFileSync(auditPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
81251
81513
|
const wanted = filter === "block" ? "deny" : filter;
|
|
81252
81514
|
const parsed = [];
|
|
81253
81515
|
for (const line of rawLines) {
|
|
@@ -81607,7 +81869,7 @@ function registerTrustCommand(program2) {
|
|
|
81607
81869
|
init_cjs_shims();
|
|
81608
81870
|
var import_chalk32 = __toESM(require("chalk"));
|
|
81609
81871
|
init_mcp_pin();
|
|
81610
|
-
var
|
|
81872
|
+
var import_fs92 = __toESM(require("fs"));
|
|
81611
81873
|
|
|
81612
81874
|
// src/cli/commands/mcp-gateway-cmd.ts
|
|
81613
81875
|
init_cjs_shims();
|
|
@@ -81816,7 +82078,7 @@ function registerMcpPinCommand(program2) {
|
|
|
81816
82078
|
let repoCorrupt = false;
|
|
81817
82079
|
if (found.source === "repo") {
|
|
81818
82080
|
try {
|
|
81819
|
-
const raw =
|
|
82081
|
+
const raw = import_fs92.default.readFileSync(found.path, "utf-8");
|
|
81820
82082
|
const parsed = JSON.parse(raw);
|
|
81821
82083
|
repoEntries = parsed.servers ?? {};
|
|
81822
82084
|
} catch {
|
|
@@ -82268,8 +82530,8 @@ init_cjs_shims();
|
|
|
82268
82530
|
|
|
82269
82531
|
// src/ci-check/fetch.ts
|
|
82270
82532
|
init_cjs_shims();
|
|
82271
|
-
var
|
|
82272
|
-
var
|
|
82533
|
+
var import_fs93 = __toESM(require("fs"));
|
|
82534
|
+
var import_path91 = __toESM(require("path"));
|
|
82273
82535
|
var import_node_child_process = require("child_process");
|
|
82274
82536
|
var import_undici = __toESM(require_undici());
|
|
82275
82537
|
|
|
@@ -82469,8 +82731,8 @@ function isOfficialInstaller(u) {
|
|
|
82469
82731
|
if (u.username || u.password) return false;
|
|
82470
82732
|
const host2 = u.hostname.toLowerCase().replace(/^www\./, "");
|
|
82471
82733
|
if (OFFICIAL_HOSTS.has(host2)) return true;
|
|
82472
|
-
const
|
|
82473
|
-
return !!
|
|
82734
|
+
const path110 = OFFICIAL_PATHS[host2];
|
|
82735
|
+
return !!path110 && path110.test(u.pathname);
|
|
82474
82736
|
}
|
|
82475
82737
|
function onlyOfficialInstaller(s) {
|
|
82476
82738
|
const urls = s.match(URL_RE3);
|
|
@@ -82661,21 +82923,21 @@ function appSkillDirsOf(paths, skillDirs) {
|
|
|
82661
82923
|
}
|
|
82662
82924
|
return apps;
|
|
82663
82925
|
}
|
|
82664
|
-
function isSkillSupportFile(
|
|
82665
|
-
if (!
|
|
82666
|
-
for (let d =
|
|
82667
|
-
const dir2 =
|
|
82926
|
+
function isSkillSupportFile(path110, skillDirs, appDirs) {
|
|
82927
|
+
if (!path110.endsWith(".md") || /(^|\/)[Ss][Kk][Ii][Ll][Ll]\.md$/.test(path110)) return false;
|
|
82928
|
+
for (let d = path110.lastIndexOf("/"); d > 0; d = path110.lastIndexOf("/", d - 1)) {
|
|
82929
|
+
const dir2 = path110.slice(0, d);
|
|
82668
82930
|
if (!skillDirs.has(dir2)) continue;
|
|
82669
|
-
return !appDirs?.has(dir2) || SKILL_LAYOUT_RE.test(
|
|
82931
|
+
return !appDirs?.has(dir2) || SKILL_LAYOUT_RE.test(path110.slice(d + 1));
|
|
82670
82932
|
}
|
|
82671
82933
|
return false;
|
|
82672
82934
|
}
|
|
82673
|
-
function isAppDoc(
|
|
82674
|
-
if (!
|
|
82675
|
-
for (let d =
|
|
82676
|
-
const dir2 =
|
|
82935
|
+
function isAppDoc(path110, skillDirs, appDirs) {
|
|
82936
|
+
if (!path110.endsWith(".md") || INSTRUCTION_FILE_RE.test(path110)) return false;
|
|
82937
|
+
for (let d = path110.lastIndexOf("/"); d > 0; d = path110.lastIndexOf("/", d - 1)) {
|
|
82938
|
+
const dir2 = path110.slice(0, d);
|
|
82677
82939
|
if (!skillDirs.has(dir2)) continue;
|
|
82678
|
-
return appDirs.has(dir2) && !SKILL_LAYOUT_RE.test(
|
|
82940
|
+
return appDirs.has(dir2) && !SKILL_LAYOUT_RE.test(path110.slice(d + 1));
|
|
82679
82941
|
}
|
|
82680
82942
|
return false;
|
|
82681
82943
|
}
|
|
@@ -82698,20 +82960,20 @@ function namedDocs(dir2, skillMd) {
|
|
|
82698
82960
|
return out;
|
|
82699
82961
|
}
|
|
82700
82962
|
var SCRIPT_EXT_RE = /\.(sh|bash|zsh|py|js|mjs|cjs|ts|rb|pl|ps1)$/i;
|
|
82701
|
-
function isHookScript(
|
|
82702
|
-
return /(^|\/)\.claude\/hooks\/.+/.test(
|
|
82703
|
-
}
|
|
82704
|
-
function isSkillScript(
|
|
82705
|
-
if (!SCRIPT_EXT_RE.test(
|
|
82706
|
-
for (let d =
|
|
82707
|
-
if (!skillDirs.has(
|
|
82708
|
-
const rel =
|
|
82963
|
+
function isHookScript(path110) {
|
|
82964
|
+
return /(^|\/)\.claude\/hooks\/.+/.test(path110) && SCRIPT_EXT_RE.test(path110);
|
|
82965
|
+
}
|
|
82966
|
+
function isSkillScript(path110, skillDirs) {
|
|
82967
|
+
if (!SCRIPT_EXT_RE.test(path110)) return false;
|
|
82968
|
+
for (let d = path110.lastIndexOf("/"); d > 0; d = path110.lastIndexOf("/", d - 1)) {
|
|
82969
|
+
if (!skillDirs.has(path110.slice(0, d))) continue;
|
|
82970
|
+
const rel = path110.slice(d + 1);
|
|
82709
82971
|
return !rel.includes("/") || /^(scripts|bin)\//.test(rel);
|
|
82710
82972
|
}
|
|
82711
82973
|
return false;
|
|
82712
82974
|
}
|
|
82713
|
-
function isInstructionFile(
|
|
82714
|
-
return INSTRUCTION_FILE_RE.test(
|
|
82975
|
+
function isInstructionFile(path110, skillDirs, appDirs) {
|
|
82976
|
+
return INSTRUCTION_FILE_RE.test(path110) || isSkillSupportFile(path110, skillDirs, appDirs);
|
|
82715
82977
|
}
|
|
82716
82978
|
var OVERRIDE_RE = /ignore\s+(all\s+)?(previous|prior|the\s+above)\s+(instructions|prompts?|rules)|disregard\s+(the\s+|your\s+)?(system\s+)?(prompt|instructions|rules)|forget\s+(everything|all\s+(previous|prior))|you\s+are\s+now\s+(a|an|the)\b|<\/?system>/i;
|
|
82717
82979
|
var FETCH_WORD_RE = /\b(curl|wget|iwr|invoke-webrequest)\b/gi;
|
|
@@ -82848,21 +83110,21 @@ function decodeSuspiciousBase64(text) {
|
|
|
82848
83110
|
}
|
|
82849
83111
|
return out;
|
|
82850
83112
|
}
|
|
82851
|
-
function mk2(rule, severity, title, signals, fix,
|
|
83113
|
+
function mk2(rule, severity, title, signals, fix, path110, line) {
|
|
82852
83114
|
return {
|
|
82853
83115
|
check: "CI-6",
|
|
82854
83116
|
rule,
|
|
82855
83117
|
dimension: "instructions",
|
|
82856
83118
|
severity,
|
|
82857
83119
|
title,
|
|
82858
|
-
file:
|
|
83120
|
+
file: path110,
|
|
82859
83121
|
...line ? { line } : {},
|
|
82860
83122
|
signals,
|
|
82861
83123
|
fix
|
|
82862
83124
|
};
|
|
82863
83125
|
}
|
|
82864
83126
|
var lineAt = (text, i) => i >= 0 ? lineAtIndex(text, i) : void 0;
|
|
82865
|
-
function analyzeInstructionFile(
|
|
83127
|
+
function analyzeInstructionFile(path110, content) {
|
|
82866
83128
|
const findings = [];
|
|
82867
83129
|
const decoded = decodeSuspiciousBase64(content);
|
|
82868
83130
|
const glyph = homoglyphWord(content);
|
|
@@ -82876,7 +83138,7 @@ function analyzeInstructionFile(path108, content) {
|
|
|
82876
83138
|
`\`${glyph.folded}\` is written with ${glyph.count} non-Latin look-alike letter(s): it reads the same to a reviewer, but a search, a replace or a policy check on the real word misses it`
|
|
82877
83139
|
],
|
|
82878
83140
|
"Spell the word with plain Latin letters, or explain on the same line why the look-alikes are there.",
|
|
82879
|
-
|
|
83141
|
+
path110,
|
|
82880
83142
|
glyph.line
|
|
82881
83143
|
)
|
|
82882
83144
|
);
|
|
@@ -82890,7 +83152,7 @@ function analyzeInstructionFile(path108, content) {
|
|
|
82890
83152
|
"contains Unicode tag characters (U+E0000\u2013E007F): an invisible instruction-smuggling channel with no legitimate use in text"
|
|
82891
83153
|
],
|
|
82892
83154
|
"Remove the tag characters. Instruction files must be plain, reviewable text.",
|
|
82893
|
-
|
|
83155
|
+
path110,
|
|
82894
83156
|
lineAt(content, content.search(TAG_CHARS))
|
|
82895
83157
|
)
|
|
82896
83158
|
);
|
|
@@ -82904,7 +83166,7 @@ function analyzeInstructionFile(path108, content) {
|
|
|
82904
83166
|
"contains a bidi override (U+202D/U+202E): a Trojan-Source technique that visually reorders text so a human reads something different from what the agent parses"
|
|
82905
83167
|
],
|
|
82906
83168
|
"Remove the bidi override characters.",
|
|
82907
|
-
|
|
83169
|
+
path110,
|
|
82908
83170
|
lineAt(content, content.search(BIDI_OVERRIDE))
|
|
82909
83171
|
)
|
|
82910
83172
|
);
|
|
@@ -82918,7 +83180,7 @@ function analyzeInstructionFile(path108, content) {
|
|
|
82918
83180
|
"contains bidi embed/isolate characters (U+202A\u2013202C / U+2066\u20132069): legitimate in right-to-left text, but confirm they are not being used to hide or reorder instructions"
|
|
82919
83181
|
],
|
|
82920
83182
|
"Confirm the bidi marks are legitimate RTL formatting; remove otherwise.",
|
|
82921
|
-
|
|
83183
|
+
path110,
|
|
82922
83184
|
lineAt(content, content.search(BIDI_EMBED_ISOLATE))
|
|
82923
83185
|
)
|
|
82924
83186
|
);
|
|
@@ -82934,7 +83196,7 @@ function analyzeInstructionFile(path108, content) {
|
|
|
82934
83196
|
revealed ? "a zero-width character conceals a prompt-override directive that only appears once the hidden characters are stripped" : "a zero-width character splits a visible Latin word: a concealment technique (hides text from human review while the agent reads it as contiguous)"
|
|
82935
83197
|
],
|
|
82936
83198
|
"Remove the zero-width characters. Instruction files must be plain, reviewable text.",
|
|
82937
|
-
|
|
83199
|
+
path110,
|
|
82938
83200
|
lineAt(content, zw.first)
|
|
82939
83201
|
)
|
|
82940
83202
|
);
|
|
@@ -82953,7 +83215,7 @@ function analyzeInstructionFile(path108, content) {
|
|
|
82953
83215
|
`contains a prompt-override / role-impersonation directive (\`${safeText(m[0].slice(0, 60).trim(), 60)}\`)${ovEnc ? ", concealed in a base64 blob" : ""}`
|
|
82954
83216
|
],
|
|
82955
83217
|
"Remove the override text. An instruction file should not tell the agent to ignore its own rules.",
|
|
82956
|
-
|
|
83218
|
+
path110,
|
|
82957
83219
|
ov ? lineAt(content, ov.index) : void 0
|
|
82958
83220
|
// concealed in base64: no line, never a wrong one
|
|
82959
83221
|
)
|
|
@@ -82970,7 +83232,7 @@ function analyzeInstructionFile(path108, content) {
|
|
|
82970
83232
|
`\`${safeText(fo[0].slice(0, 70).trim(), 70)}\`: fetch-and-obey, outside an install/setup section`
|
|
82971
83233
|
],
|
|
82972
83234
|
"Do not instruct the agent to pipe remote content into a shell; pin and vendor scripts instead.",
|
|
82973
|
-
|
|
83235
|
+
path110,
|
|
82974
83236
|
lineAt(content, fo.index)
|
|
82975
83237
|
)
|
|
82976
83238
|
);
|
|
@@ -82986,7 +83248,7 @@ function analyzeInstructionFile(path108, content) {
|
|
|
82986
83248
|
`references \`${safeText(sp[0].slice(0, 50).trim(), 50)}\`: directs the agent toward secrets`
|
|
82987
83249
|
],
|
|
82988
83250
|
"Do not reference credential files or paths in agent instructions.",
|
|
82989
|
-
|
|
83251
|
+
path110,
|
|
82990
83252
|
lineAt(content, sp.index)
|
|
82991
83253
|
)
|
|
82992
83254
|
);
|
|
@@ -83009,7 +83271,7 @@ function analyzeInstructionFile(path108, content) {
|
|
|
83009
83271
|
"Instruction directs the agent to send data to an external endpoint",
|
|
83010
83272
|
[`\`${safeText(ex[0].slice(0, 70).trim(), 70)}\`: possible exfiltration directive`],
|
|
83011
83273
|
"Remove external post/upload directives from agent instructions.",
|
|
83012
|
-
|
|
83274
|
+
path110,
|
|
83013
83275
|
lineAt(content, ex.index)
|
|
83014
83276
|
)
|
|
83015
83277
|
);
|
|
@@ -83020,18 +83282,18 @@ function analyzeInstructionFile(path108, content) {
|
|
|
83020
83282
|
// src/ci-check/route.ts
|
|
83021
83283
|
var MCP_CONFIG_RE = /\.mcp\.json$|\.cursor\/mcp\.json$|(^|\/)\.vscode\/mcp\.json$|(^|\/)\.kiro\/settings\/mcp\.json$|(^|\/)\.gemini\/settings\.json$|(^|\/)opencode\.json$|(^|\/)\.opencode\/config\.json$/;
|
|
83022
83284
|
var ISSUE_FORM_RE = /^\.github\/ISSUE_TEMPLATE\/[^/]+\.(ya?ml|md)$/i;
|
|
83023
|
-
function routeOf(
|
|
83024
|
-
if (
|
|
83025
|
-
if (/\.github\/workflows\/.+\.ya?ml$/.test(
|
|
83026
|
-
if (ISSUE_FORM_RE.test(
|
|
83027
|
-
if (
|
|
83028
|
-
if (/\.claude\/settings(\.local)?\.json$/.test(
|
|
83029
|
-
if (isHookScript(
|
|
83030
|
-
if (isSkillScript(
|
|
83031
|
-
if (MCP_CONFIG_RE.test(
|
|
83032
|
-
if (/(^|\/)\.codex\/config\.toml$/.test(
|
|
83033
|
-
if (isInstructionFile(
|
|
83034
|
-
if (isAppDoc(
|
|
83285
|
+
function routeOf(path110, skillDirs, appDirs = /* @__PURE__ */ new Set()) {
|
|
83286
|
+
if (path110 === SUPPRESSIONS_FILE) return "suppressions";
|
|
83287
|
+
if (/\.github\/workflows\/.+\.ya?ml$/.test(path110)) return "workflow";
|
|
83288
|
+
if (ISSUE_FORM_RE.test(path110)) return "issue-form";
|
|
83289
|
+
if (path110 === "package.json" || path110 === "pyproject.toml") return "manifest";
|
|
83290
|
+
if (/\.claude\/settings(\.local)?\.json$/.test(path110)) return "agent-config";
|
|
83291
|
+
if (isHookScript(path110)) return "hook-script";
|
|
83292
|
+
if (isSkillScript(path110, skillDirs)) return "skill-script";
|
|
83293
|
+
if (MCP_CONFIG_RE.test(path110)) return "mcp";
|
|
83294
|
+
if (/(^|\/)\.codex\/config\.toml$/.test(path110)) return "codex";
|
|
83295
|
+
if (isInstructionFile(path110, skillDirs, appDirs)) return "instruction";
|
|
83296
|
+
if (isAppDoc(path110, skillDirs, appDirs)) return "app-doc";
|
|
83035
83297
|
return null;
|
|
83036
83298
|
}
|
|
83037
83299
|
|
|
@@ -83160,7 +83422,7 @@ function parseRepoUrl(input) {
|
|
|
83160
83422
|
function isLocalPath(input) {
|
|
83161
83423
|
if (input.startsWith(".") || input.startsWith("/") || input.startsWith("~")) return true;
|
|
83162
83424
|
try {
|
|
83163
|
-
return
|
|
83425
|
+
return import_fs93.default.existsSync(input) && import_fs93.default.statSync(input).isDirectory();
|
|
83164
83426
|
} catch {
|
|
83165
83427
|
return false;
|
|
83166
83428
|
}
|
|
@@ -83521,7 +83783,7 @@ function capNested(reads, cap, notes) {
|
|
|
83521
83783
|
}
|
|
83522
83784
|
var overLimit = (text) => Buffer.byteLength(text, "utf8") > MAX_FILE_BYTES3;
|
|
83523
83785
|
var RAW_LIMIT = 2 * MAX_FILE_BYTES3;
|
|
83524
|
-
var OPEN_READ =
|
|
83786
|
+
var OPEN_READ = import_fs93.default.constants.O_RDONLY | (import_fs93.default.constants.O_NOFOLLOW ?? 0) | (import_fs93.default.constants.O_NONBLOCK ?? 0);
|
|
83525
83787
|
var MAX_WALK_ENTRIES = 1e6;
|
|
83526
83788
|
var direntKind = (e) => e.isSymbolicLink() ? "link" : e.isDirectory() ? "dir" : e.isFile() ? "file" : "other";
|
|
83527
83789
|
function walkDisk(root, notes) {
|
|
@@ -83536,7 +83798,7 @@ function walkDisk(root, notes) {
|
|
|
83536
83798
|
const relDir = stack.pop();
|
|
83537
83799
|
let dirents;
|
|
83538
83800
|
try {
|
|
83539
|
-
dirents =
|
|
83801
|
+
dirents = import_fs93.default.readdirSync(import_path91.default.join(root, relDir), { withFileTypes: true });
|
|
83540
83802
|
} catch (e) {
|
|
83541
83803
|
unlistable.push(`${relDir || "."} (${e?.code ?? "error"})`);
|
|
83542
83804
|
continue;
|
|
@@ -83550,7 +83812,7 @@ function walkDisk(root, notes) {
|
|
|
83550
83812
|
const k = direntKind(e);
|
|
83551
83813
|
kinds2.set(rel, k);
|
|
83552
83814
|
if (k !== "dir" || isUnwalked(`${rel}/`)) continue;
|
|
83553
|
-
if (
|
|
83815
|
+
if (import_fs93.default.existsSync(import_path91.default.join(root, rel, ".git"))) {
|
|
83554
83816
|
sealed.add(rel);
|
|
83555
83817
|
nestedRepos.push(rel);
|
|
83556
83818
|
} else stack.push(rel);
|
|
@@ -83573,7 +83835,7 @@ function walkDisk(root, notes) {
|
|
|
83573
83835
|
}
|
|
83574
83836
|
function gitmodulePaths(root) {
|
|
83575
83837
|
try {
|
|
83576
|
-
const text = readLocalFile(
|
|
83838
|
+
const text = readLocalFile(import_path91.default.join(root, ".gitmodules"), ".gitmodules");
|
|
83577
83839
|
return [...text.matchAll(/^\s*path\s*=\s*(.+?)\s*$/gm)].map((m) => m[1].replace(/\/+$/, ""));
|
|
83578
83840
|
} catch {
|
|
83579
83841
|
return [];
|
|
@@ -83581,9 +83843,9 @@ function gitmodulePaths(root) {
|
|
|
83581
83843
|
}
|
|
83582
83844
|
function localLinkText(root, rel) {
|
|
83583
83845
|
try {
|
|
83584
|
-
const t =
|
|
83846
|
+
const t = import_fs93.default.readlinkSync(import_path91.default.join(root, rel));
|
|
83585
83847
|
if (process.platform !== "win32") return t;
|
|
83586
|
-
return
|
|
83848
|
+
return import_path91.default.win32.isAbsolute(t) ? `/${t.replace(/\\/g, "/")}` : t.replace(/\\/g, "/");
|
|
83587
83849
|
} catch {
|
|
83588
83850
|
return null;
|
|
83589
83851
|
}
|
|
@@ -83591,11 +83853,11 @@ function localLinkText(root, rel) {
|
|
|
83591
83853
|
function readLocalFile(abs, rel) {
|
|
83592
83854
|
let fd;
|
|
83593
83855
|
try {
|
|
83594
|
-
fd =
|
|
83595
|
-
const st =
|
|
83856
|
+
fd = import_fs93.default.openSync(abs, OPEN_READ);
|
|
83857
|
+
const st = import_fs93.default.fstatSync(fd);
|
|
83596
83858
|
if (!st.isFile()) throw new Error(unreadNote(rel, "no longer a regular file"));
|
|
83597
83859
|
if (st.size > RAW_LIMIT) throw new Error(tooLargeNote(rel));
|
|
83598
|
-
const text = lf(
|
|
83860
|
+
const text = lf(import_fs93.default.readFileSync(fd, "utf8"));
|
|
83599
83861
|
if (overLimit(text)) throw new Error(tooLargeNote(rel));
|
|
83600
83862
|
return text;
|
|
83601
83863
|
} catch (e) {
|
|
@@ -83603,7 +83865,7 @@ function readLocalFile(abs, rel) {
|
|
|
83603
83865
|
if (msg.includes(INCOMPLETE)) throw e;
|
|
83604
83866
|
throw new Error(unreadNote(rel, e?.code ?? "error"));
|
|
83605
83867
|
} finally {
|
|
83606
|
-
if (fd !== void 0)
|
|
83868
|
+
if (fd !== void 0) import_fs93.default.closeSync(fd);
|
|
83607
83869
|
}
|
|
83608
83870
|
}
|
|
83609
83871
|
function localGitHubRepo(root) {
|
|
@@ -83624,10 +83886,10 @@ function readLocalTree(dir2) {
|
|
|
83624
83886
|
notes.push(...plan.notes);
|
|
83625
83887
|
const files = [];
|
|
83626
83888
|
for (const { rel, real, route } of plan.reads) {
|
|
83627
|
-
const abs =
|
|
83889
|
+
const abs = import_path91.default.join(root, real);
|
|
83628
83890
|
let size = 0;
|
|
83629
83891
|
try {
|
|
83630
|
-
size =
|
|
83892
|
+
size = import_fs93.default.lstatSync(abs).size;
|
|
83631
83893
|
} catch {
|
|
83632
83894
|
}
|
|
83633
83895
|
if (size > RAW_LIMIT) {
|
|
@@ -85135,17 +85397,17 @@ function localTarget(uses, self) {
|
|
|
85135
85397
|
if (!f) return null;
|
|
85136
85398
|
return f[1].toLowerCase() === self.owner.toLowerCase() && f[2].toLowerCase() === self.repo.toLowerCase() ? `.github/workflows/${f[3]}` : null;
|
|
85137
85399
|
}
|
|
85138
|
-
function localCallsOf(
|
|
85400
|
+
function localCallsOf(path110, content, autoLabels, trustedRunSources, self) {
|
|
85139
85401
|
AUTO_LABELS = autoLabels ?? /* @__PURE__ */ new Set();
|
|
85140
85402
|
TRUSTED_RUN_SOURCES = trustedRunSources ?? /* @__PURE__ */ new Set();
|
|
85141
85403
|
try {
|
|
85142
|
-
return localCallsOfInner(
|
|
85404
|
+
return localCallsOfInner(path110, content, self);
|
|
85143
85405
|
} finally {
|
|
85144
85406
|
AUTO_LABELS = /* @__PURE__ */ new Set();
|
|
85145
85407
|
TRUSTED_RUN_SOURCES = /* @__PURE__ */ new Set();
|
|
85146
85408
|
}
|
|
85147
85409
|
}
|
|
85148
|
-
function localCallsOfInner(
|
|
85410
|
+
function localCallsOfInner(path110, content, self) {
|
|
85149
85411
|
let raw;
|
|
85150
85412
|
try {
|
|
85151
85413
|
raw = loadWorkflow(content).raw;
|
|
@@ -85163,7 +85425,7 @@ function localCallsOfInner(path108, content, self) {
|
|
|
85163
85425
|
out.push({
|
|
85164
85426
|
target,
|
|
85165
85427
|
caller: {
|
|
85166
|
-
file:
|
|
85428
|
+
file: path110,
|
|
85167
85429
|
keys: reach.keys,
|
|
85168
85430
|
untrusted: reach.untrusted,
|
|
85169
85431
|
secretExposed: reach.secretExposed,
|
|
@@ -85399,7 +85661,7 @@ function upstreamRunTrusted(wf, raw) {
|
|
|
85399
85661
|
const names = Array.isArray(run?.workflows) ? run.workflows.map(String) : [];
|
|
85400
85662
|
return names.length > 0 && names.every((n) => TRUSTED_RUN_SOURCES.has(n));
|
|
85401
85663
|
}
|
|
85402
|
-
function runSourceOf(
|
|
85664
|
+
function runSourceOf(path110, content, autoLabels) {
|
|
85403
85665
|
AUTO_LABELS = autoLabels ?? /* @__PURE__ */ new Set();
|
|
85404
85666
|
try {
|
|
85405
85667
|
let raw;
|
|
@@ -85412,7 +85674,7 @@ function runSourceOf(path108, content, autoLabels) {
|
|
|
85412
85674
|
const wf = raw;
|
|
85413
85675
|
CALLERS.delete(wf);
|
|
85414
85676
|
const reach = triggerReach(wf, raw);
|
|
85415
|
-
const name = typeof raw["name"] === "string" && raw["name"] ? raw["name"] :
|
|
85677
|
+
const name = typeof raw["name"] === "string" && raw["name"] ? raw["name"] : path110;
|
|
85416
85678
|
return { name, trusted: !reach.untrusted && !reach.reusable };
|
|
85417
85679
|
} finally {
|
|
85418
85680
|
AUTO_LABELS = /* @__PURE__ */ new Set();
|
|
@@ -85882,18 +86144,18 @@ function severityFromScore(score) {
|
|
|
85882
86144
|
if (score >= 1) return "advisory";
|
|
85883
86145
|
return null;
|
|
85884
86146
|
}
|
|
85885
|
-
function analyzeWorkflow(
|
|
86147
|
+
function analyzeWorkflow(path110, content, callers, autoLabels, trustedRunSources) {
|
|
85886
86148
|
AUTO_LABELS = autoLabels ?? /* @__PURE__ */ new Set();
|
|
85887
86149
|
TRUSTED_RUN_SOURCES = trustedRunSources ?? /* @__PURE__ */ new Set();
|
|
85888
86150
|
try {
|
|
85889
|
-
return analyzeWorkflowInner(
|
|
86151
|
+
return analyzeWorkflowInner(path110, content, callers);
|
|
85890
86152
|
} finally {
|
|
85891
86153
|
AUTO_LABELS = /* @__PURE__ */ new Set();
|
|
85892
86154
|
TRUSTED_RUN_SOURCES = /* @__PURE__ */ new Set();
|
|
85893
86155
|
UPSTREAM_TRUSTED = false;
|
|
85894
86156
|
}
|
|
85895
86157
|
}
|
|
85896
|
-
function analyzeWorkflowInner(
|
|
86158
|
+
function analyzeWorkflowInner(path110, content, callers) {
|
|
85897
86159
|
let raw;
|
|
85898
86160
|
try {
|
|
85899
86161
|
raw = loadWorkflow(content).raw;
|
|
@@ -86102,7 +86364,7 @@ function analyzeWorkflowInner(path108, content, callers) {
|
|
|
86102
86364
|
dimension: "workflows",
|
|
86103
86365
|
severity,
|
|
86104
86366
|
title,
|
|
86105
|
-
file:
|
|
86367
|
+
file: path110,
|
|
86106
86368
|
signals,
|
|
86107
86369
|
mitigations: mitigations.length ? mitigations : void 0,
|
|
86108
86370
|
fix: head === "root" && privileged ? "Do not check out the untrusted PR head into the workspace root under a privileged trigger (pull_request_target/workflow_run): check out the base ref, or isolate the head in a subdir (--add-dir). Add an actor gate and scope the agent tools." : head === "root" ? "This runs under `pull_request` (fork PRs get a read-only token), so the head checkout is low-risk today: keep it on `pull_request` (not `pull_request_target`) and keep the actor gate + scoped tools." : "Add/verify an actor gate, scope the agent tools to read-only, and env-deny secrets. See Anthropic\u2019s claude-code-action security doc."
|
|
@@ -86206,18 +86468,18 @@ function evalAgentJob(job, wf, raw, untrustedTrigger, reusable) {
|
|
|
86206
86468
|
if (reusable && !loadedGun && SEVERITY_RANK2[severity] > SEVERITY_RANK2.medium) severity = "medium";
|
|
86207
86469
|
return { severity, secrets, injectable, canReadEnv };
|
|
86208
86470
|
}
|
|
86209
|
-
function analyzeWorkflowSecrets(
|
|
86471
|
+
function analyzeWorkflowSecrets(path110, content, callers, autoLabels, trustedRunSources) {
|
|
86210
86472
|
AUTO_LABELS = autoLabels ?? /* @__PURE__ */ new Set();
|
|
86211
86473
|
TRUSTED_RUN_SOURCES = trustedRunSources ?? /* @__PURE__ */ new Set();
|
|
86212
86474
|
try {
|
|
86213
|
-
return analyzeWorkflowSecretsInner(
|
|
86475
|
+
return analyzeWorkflowSecretsInner(path110, content, callers);
|
|
86214
86476
|
} finally {
|
|
86215
86477
|
AUTO_LABELS = /* @__PURE__ */ new Set();
|
|
86216
86478
|
TRUSTED_RUN_SOURCES = /* @__PURE__ */ new Set();
|
|
86217
86479
|
UPSTREAM_TRUSTED = false;
|
|
86218
86480
|
}
|
|
86219
86481
|
}
|
|
86220
|
-
function analyzeWorkflowSecretsInner(
|
|
86482
|
+
function analyzeWorkflowSecretsInner(path110, content, callers) {
|
|
86221
86483
|
let raw;
|
|
86222
86484
|
try {
|
|
86223
86485
|
raw = loadWorkflow(content).raw;
|
|
@@ -86244,7 +86506,7 @@ function analyzeWorkflowSecretsInner(path108, content, callers) {
|
|
|
86244
86506
|
dimension: "data",
|
|
86245
86507
|
severity: worst.severity,
|
|
86246
86508
|
title: worst.severity === "advisory" ? "Secrets reachable by the agent: hardening" : "Exfiltratable secrets reachable by an injectable agent",
|
|
86247
|
-
file:
|
|
86509
|
+
file: path110,
|
|
86248
86510
|
signals: [
|
|
86249
86511
|
`agent can reach: ${worst.secrets.map((s) => s.name).join(", ")}`,
|
|
86250
86512
|
worst.injectable ? "the agent is externally triggerable (untrusted trigger, no gate)" : "gated / not externally triggerable: latent risk only",
|
|
@@ -86266,7 +86528,7 @@ function marketplaceOwner(market) {
|
|
|
86266
86528
|
market
|
|
86267
86529
|
)?.[1] ?? /^([\w.-]{1,100})\/[\w.-]{1,100}(?:[#@].*)?$/.exec(market)?.[1];
|
|
86268
86530
|
}
|
|
86269
|
-
function analyzeWorkflowPlugins(
|
|
86531
|
+
function analyzeWorkflowPlugins(path110, content, owner) {
|
|
86270
86532
|
let raw;
|
|
86271
86533
|
try {
|
|
86272
86534
|
raw = loadWorkflow(content).raw;
|
|
@@ -86296,7 +86558,7 @@ function analyzeWorkflowPlugins(path108, content, owner) {
|
|
|
86296
86558
|
dimension: "mcp",
|
|
86297
86559
|
severity: "medium",
|
|
86298
86560
|
title: "Agent installs plugins from a third-party marketplace on every run",
|
|
86299
|
-
file:
|
|
86561
|
+
file: path110,
|
|
86300
86562
|
signals: [
|
|
86301
86563
|
`\`plugin_marketplaces: ${safeText(market, 120)}\` is not pinned to a commit: whoever controls it changes the code and prompts the agent runs`
|
|
86302
86564
|
],
|
|
@@ -86312,11 +86574,11 @@ function readsItemList(text) {
|
|
|
86312
86574
|
if (text.length > 2e5) return ITEM_LIST_RE.test(text);
|
|
86313
86575
|
return text.replace(/\\\r?\n/g, " ").split("\n").some((l) => ITEM_LIST_RE.test(l) && !sanitizedListing(l));
|
|
86314
86576
|
}
|
|
86315
|
-
function analyzeTrustedReaders(
|
|
86577
|
+
function analyzeTrustedReaders(path110, content, autoLabels, callers, trustedRunSources) {
|
|
86316
86578
|
AUTO_LABELS = autoLabels ?? /* @__PURE__ */ new Set();
|
|
86317
86579
|
TRUSTED_RUN_SOURCES = trustedRunSources ?? /* @__PURE__ */ new Set();
|
|
86318
86580
|
try {
|
|
86319
|
-
return analyzeTrustedReadersInner(
|
|
86581
|
+
return analyzeTrustedReadersInner(path110, content, callers);
|
|
86320
86582
|
} finally {
|
|
86321
86583
|
AUTO_LABELS = /* @__PURE__ */ new Set();
|
|
86322
86584
|
TRUSTED_RUN_SOURCES = /* @__PURE__ */ new Set();
|
|
@@ -86325,7 +86587,7 @@ function analyzeTrustedReaders(path108, content, autoLabels, callers, trustedRun
|
|
|
86325
86587
|
function keysWithCallers(keys, callers) {
|
|
86326
86588
|
return [.../* @__PURE__ */ new Set([...keys, ...(callers ?? []).flatMap((c) => c.keys)])];
|
|
86327
86589
|
}
|
|
86328
|
-
function analyzeTrustedReadersInner(
|
|
86590
|
+
function analyzeTrustedReadersInner(path110, content, callers) {
|
|
86329
86591
|
let raw;
|
|
86330
86592
|
try {
|
|
86331
86593
|
raw = loadWorkflow(content).raw;
|
|
@@ -86386,7 +86648,7 @@ function analyzeTrustedReadersInner(path108, content, callers) {
|
|
|
86386
86648
|
dimension: "workflows",
|
|
86387
86649
|
severity: "advisory",
|
|
86388
86650
|
title: "Agent on a trusted trigger reads content strangers write, with a write token",
|
|
86389
|
-
file:
|
|
86651
|
+
file: path110,
|
|
86390
86652
|
signals: [
|
|
86391
86653
|
`runs on ${keys.map((k) => safeText(k, 40)).join(", ")}: no stranger starts it`,
|
|
86392
86654
|
...reads.map((r) => `the agent ${r}`),
|
|
@@ -86474,17 +86736,17 @@ function requiresTrustedAuthor(src) {
|
|
|
86474
86736
|
};
|
|
86475
86737
|
return req(x);
|
|
86476
86738
|
}
|
|
86477
|
-
function analyzeForkCodeOnTrust(
|
|
86739
|
+
function analyzeForkCodeOnTrust(path110, content, callers, autoLabels, trustedRunSources) {
|
|
86478
86740
|
AUTO_LABELS = autoLabels ?? /* @__PURE__ */ new Set();
|
|
86479
86741
|
TRUSTED_RUN_SOURCES = trustedRunSources ?? /* @__PURE__ */ new Set();
|
|
86480
86742
|
try {
|
|
86481
|
-
return analyzeForkCodeOnTrustInner(
|
|
86743
|
+
return analyzeForkCodeOnTrustInner(path110, content, callers);
|
|
86482
86744
|
} finally {
|
|
86483
86745
|
AUTO_LABELS = /* @__PURE__ */ new Set();
|
|
86484
86746
|
TRUSTED_RUN_SOURCES = /* @__PURE__ */ new Set();
|
|
86485
86747
|
}
|
|
86486
86748
|
}
|
|
86487
|
-
function analyzeForkCodeOnTrustInner(
|
|
86749
|
+
function analyzeForkCodeOnTrustInner(path110, content, callers) {
|
|
86488
86750
|
let raw;
|
|
86489
86751
|
try {
|
|
86490
86752
|
raw = loadWorkflow(content).raw;
|
|
@@ -86523,7 +86785,7 @@ function analyzeForkCodeOnTrustInner(path108, content, callers) {
|
|
|
86523
86785
|
dimension: "workflows",
|
|
86524
86786
|
severity: "advisory",
|
|
86525
86787
|
title: "A maintainer's action runs the agent inside the fork's code",
|
|
86526
|
-
file:
|
|
86788
|
+
file: path110,
|
|
86527
86789
|
signals: [
|
|
86528
86790
|
`triggered by ${forkKeys.map((k) => safeText(k, 40)).join(", ")}, behind a gate a maintainer passes (a comment, a label, a push to the PR branch, a reopen)`,
|
|
86529
86791
|
"checks out the untrusted PR head into the workspace root",
|
|
@@ -86555,18 +86817,18 @@ function laterSecrets(wf, job, from) {
|
|
|
86555
86817
|
if (!/^GITHUB_TOKEN$/i.test(m[1])) out.add(m[1]);
|
|
86556
86818
|
return [...out];
|
|
86557
86819
|
}
|
|
86558
|
-
function analyzeAgentOutputToEnv(
|
|
86820
|
+
function analyzeAgentOutputToEnv(path110, content, callers, autoLabels, trustedRunSources) {
|
|
86559
86821
|
AUTO_LABELS = autoLabels ?? /* @__PURE__ */ new Set();
|
|
86560
86822
|
TRUSTED_RUN_SOURCES = trustedRunSources ?? /* @__PURE__ */ new Set();
|
|
86561
86823
|
try {
|
|
86562
|
-
return analyzeAgentOutputToEnvInner(
|
|
86824
|
+
return analyzeAgentOutputToEnvInner(path110, content, callers);
|
|
86563
86825
|
} finally {
|
|
86564
86826
|
AUTO_LABELS = /* @__PURE__ */ new Set();
|
|
86565
86827
|
TRUSTED_RUN_SOURCES = /* @__PURE__ */ new Set();
|
|
86566
86828
|
UPSTREAM_TRUSTED = false;
|
|
86567
86829
|
}
|
|
86568
86830
|
}
|
|
86569
|
-
function analyzeAgentOutputToEnvInner(
|
|
86831
|
+
function analyzeAgentOutputToEnvInner(path110, content, callers) {
|
|
86570
86832
|
let raw;
|
|
86571
86833
|
try {
|
|
86572
86834
|
raw = loadWorkflow(content).raw;
|
|
@@ -86662,7 +86924,7 @@ function analyzeAgentOutputToEnvInner(path108, content, callers) {
|
|
|
86662
86924
|
dimension: "workflows",
|
|
86663
86925
|
severity,
|
|
86664
86926
|
title: sink.target === "GITHUB_PATH" ? "The agent's output is added to the job's PATH" : "The agent's output is written into the job's environment",
|
|
86665
|
-
file:
|
|
86927
|
+
file: path110,
|
|
86666
86928
|
signals,
|
|
86667
86929
|
fix: `Write the agent's result to a file and read it with a strict parser in the next step (a fixed set of values, or a number); never append free text from the agent to \`${target}\`. If a value must go there, strip newlines (\`tr -d '\\n'\`) and write it under a fixed name, or use a delimiter generated at run time.`,
|
|
86668
86930
|
explain: explainAgentOutputEnv({
|
|
@@ -86690,7 +86952,7 @@ function analyzeAgentOutputToEnvInner(path108, content, callers) {
|
|
|
86690
86952
|
|
|
86691
86953
|
// src/ci-check/agent-config.ts
|
|
86692
86954
|
init_cjs_shims();
|
|
86693
|
-
var
|
|
86955
|
+
var import_path92 = __toESM(require("path"));
|
|
86694
86956
|
function asStrings(v) {
|
|
86695
86957
|
return Array.isArray(v) ? v.filter((x) => typeof x === "string") : [];
|
|
86696
86958
|
}
|
|
@@ -86798,7 +87060,7 @@ function hookScriptPath(cmd) {
|
|
|
86798
87060
|
if (/^(https?:|\$|-)/.test(t)) continue;
|
|
86799
87061
|
t = t.replace(/^\.\//, "");
|
|
86800
87062
|
if (!SCRIPT_EXT_RE.test(t) && !/(^|\/)\.claude\/hooks\//.test(t)) continue;
|
|
86801
|
-
const norm =
|
|
87063
|
+
const norm = import_path92.default.posix.normalize(t);
|
|
86802
87064
|
if (norm.startsWith("..") || norm.startsWith("/") || norm.includes("/../")) return null;
|
|
86803
87065
|
return norm;
|
|
86804
87066
|
}
|
|
@@ -86808,7 +87070,7 @@ function cmdLine(content, cmd) {
|
|
|
86808
87070
|
const i = jsonValueIndex(content, cmd);
|
|
86809
87071
|
return i >= 0 ? lineAtIndex(content, i) : void 0;
|
|
86810
87072
|
}
|
|
86811
|
-
function analyzeAgentConfig(
|
|
87073
|
+
function analyzeAgentConfig(path110, content, tree) {
|
|
86812
87074
|
let cfg;
|
|
86813
87075
|
try {
|
|
86814
87076
|
cfg = JSON.parse(content);
|
|
@@ -86831,7 +87093,7 @@ function analyzeAgentConfig(path108, content, tree) {
|
|
|
86831
87093
|
dimension: "toolRules",
|
|
86832
87094
|
severity: high ? "high" : "medium",
|
|
86833
87095
|
title: high ? "Agent hook runs UNPINNED/remote third-party code on every action" : "Agent hook runs third-party code in the agent hot path",
|
|
86834
|
-
file:
|
|
87096
|
+
file: path110,
|
|
86835
87097
|
...cmdLine(content, cmd) ? { line: cmdLine(content, cmd) } : {},
|
|
86836
87098
|
signals: [
|
|
86837
87099
|
`hook command: \`${safeText(cmd, 120)}\``,
|
|
@@ -86852,7 +87114,7 @@ function analyzeAgentConfig(path108, content, tree) {
|
|
|
86852
87114
|
dimension: "toolRules",
|
|
86853
87115
|
severity: "medium",
|
|
86854
87116
|
title: "Agent hook runs a script that is not committed",
|
|
86855
|
-
file:
|
|
87117
|
+
file: path110,
|
|
86856
87118
|
...cmdLine(content, cmd) ? { line: cmdLine(content, cmd) } : {},
|
|
86857
87119
|
signals: [
|
|
86858
87120
|
`hook command: \`${safeText(cmd, 120)}\``,
|
|
@@ -86868,7 +87130,7 @@ function analyzeAgentConfig(path108, content, tree) {
|
|
|
86868
87130
|
dimension: "toolRules",
|
|
86869
87131
|
severity: "advisory",
|
|
86870
87132
|
title: "Agent hook runs a committed script this scan did not read",
|
|
86871
|
-
file:
|
|
87133
|
+
file: path110,
|
|
86872
87134
|
...cmdLine(content, cmd) ? { line: cmdLine(content, cmd) } : {},
|
|
86873
87135
|
signals: [
|
|
86874
87136
|
`hook command: \`${safeText(cmd, 120)}\``,
|
|
@@ -86897,12 +87159,12 @@ function analyzeAgentConfig(path108, content, tree) {
|
|
|
86897
87159
|
dimension: "toolRules",
|
|
86898
87160
|
severity: high ? "high" : "medium",
|
|
86899
87161
|
title: high ? "Committed agent config pre-authorizes broad tools with no deny backstop" : "Committed agent config pre-authorizes broad tools",
|
|
86900
|
-
file:
|
|
87162
|
+
file: path110,
|
|
86901
87163
|
signals,
|
|
86902
87164
|
fix: "Scope the allow-list to specific read-only subcommands (e.g. `Bash(gh pr view:*)`); avoid bare `Bash`/`git:`/`Write`, or add a `deny` backstop.",
|
|
86903
87165
|
explain: explainGrant({
|
|
86904
87166
|
high,
|
|
86905
|
-
file:
|
|
87167
|
+
file: path110,
|
|
86906
87168
|
broad: grade.broad,
|
|
86907
87169
|
bareShell: grade.bareShell,
|
|
86908
87170
|
hasBackstop: grade.bareShell ? deny.some((d) => /^Bash\b/.test(d)) : deny.some((d) => /Bash|Write|Edit/.test(d))
|
|
@@ -86919,7 +87181,7 @@ function analyzeAgentConfig(path108, content, tree) {
|
|
|
86919
87181
|
dimension: "toolRules",
|
|
86920
87182
|
severity: "medium",
|
|
86921
87183
|
title: "Committed agent config pre-approves a command that can run other programs",
|
|
86922
|
-
file:
|
|
87184
|
+
file: path110,
|
|
86923
87185
|
signals: [
|
|
86924
87186
|
`pre-approved: ${escapes.slice(0, 5).map((e) => `\`${safeText(e, 80)}\``).join(", ")}`,
|
|
86925
87187
|
"`find -exec` and `make -n --eval` run other programs without a prompt"
|
|
@@ -86934,8 +87196,8 @@ var ROOT_SURFACE_RE = /^\.(claude|agents|github|codex|cursor|gemini)\//;
|
|
|
86934
87196
|
var ITEM_TEXT_RE = /gh\s+(?:pr|issue)\s+(?:view|diff|list)\b|gh\s+pr\s+checkout\b|git\s+fetch\s+[^\n]{0,80}\bpull\/|gh\s+api\s+graphql\b|gh\s+api\s+[^\n]{0,120}\/(?:pulls|issues)\b|mcp__github__(?:get_issue|get_pull_request|list_issues|search_issues)|--json\s+[^\n]{0,120}\b(?:body|title)\b/;
|
|
86935
87197
|
var PR_TEXT_RE = /gh\s+pr\s+(?:view|diff)\b|gh\s+api\s+[^\n]{0,120}\/pulls\b/;
|
|
86936
87198
|
var WEB_TEXT_RE = /\bsearch the web\b|\bfetch (?:the )?(?:url|page)\b/i;
|
|
86937
|
-
function skillReadsUntrusted(
|
|
86938
|
-
if (!ROOT_SURFACE_RE.test(
|
|
87199
|
+
function skillReadsUntrusted(path110, content, allow, broad) {
|
|
87200
|
+
if (!ROOT_SURFACE_RE.test(path110)) return null;
|
|
86939
87201
|
const body = content.replace(/^---[\s\S]*?\n---/, "");
|
|
86940
87202
|
const runsCode = broad.map((a) => a.replace(/^PowerShell(?=$|\()/, "Bash")).some((a) => /^Bash$|^Bash\(\s*\*/.test(a) || openRunner(a) && !/^Bash\(\s*gh\b/.test(a));
|
|
86941
87203
|
const webGrant = allow.some((a) => /^(WebFetch|WebSearch)\b/.test(a));
|
|
@@ -86950,8 +87212,8 @@ function skillReadsUntrusted(path108, content, allow, broad) {
|
|
|
86950
87212
|
return "it reads pull request text that strangers write, and may edit files and run git/gh on it";
|
|
86951
87213
|
return null;
|
|
86952
87214
|
}
|
|
86953
|
-
function analyzeSkillGrants(
|
|
86954
|
-
if (!GRANT_CARRIER_RE.test(
|
|
87215
|
+
function analyzeSkillGrants(path110, content) {
|
|
87216
|
+
if (!GRANT_CARRIER_RE.test(path110)) return [];
|
|
86955
87217
|
const allow = allowedToolsOf(parseFrontmatter(content));
|
|
86956
87218
|
if (allow.length === 0) return [];
|
|
86957
87219
|
const grade = gradeBroadGrant(allow, [], {
|
|
@@ -86959,9 +87221,9 @@ function analyzeSkillGrants(path108, content) {
|
|
|
86959
87221
|
scope: "whenever this skill or command is active, for everyone who opens this repo with the agent"
|
|
86960
87222
|
});
|
|
86961
87223
|
if (!grade) return [];
|
|
86962
|
-
const kind = /commands\//.test(
|
|
87224
|
+
const kind = /commands\//.test(path110) ? "slash command" : "skill";
|
|
86963
87225
|
const at = content.search(/^allowed-tools\s*:/m);
|
|
86964
|
-
const untrusted = skillReadsUntrusted(
|
|
87226
|
+
const untrusted = skillReadsUntrusted(path110, content, allow, grade.broad);
|
|
86965
87227
|
if (untrusted)
|
|
86966
87228
|
return [
|
|
86967
87229
|
{
|
|
@@ -86971,7 +87233,7 @@ function analyzeSkillGrants(path108, content) {
|
|
|
86971
87233
|
dimension: "toolRules",
|
|
86972
87234
|
severity: "advisory",
|
|
86973
87235
|
title: `Committed ${kind} runs code or writes with text strangers control`,
|
|
86974
|
-
file:
|
|
87236
|
+
file: path110,
|
|
86975
87237
|
signals: [...grade.signals, untrusted],
|
|
86976
87238
|
fix: "Drop the shell or interpreter grant from a skill that reads PRs, issues or the web, or have it treat that text as data in a read-only step first."
|
|
86977
87239
|
}
|
|
@@ -86988,7 +87250,7 @@ function analyzeSkillGrants(path108, content) {
|
|
|
86988
87250
|
// shell — the cap is on reach, not on honesty.
|
|
86989
87251
|
severity: "medium",
|
|
86990
87252
|
title: grade.high ? `Committed ${kind} pre-authorizes an unrestricted shell while active` : `Committed ${kind} pre-authorizes broad tools while active`,
|
|
86991
|
-
file:
|
|
87253
|
+
file: path110,
|
|
86992
87254
|
signals: grade.signals,
|
|
86993
87255
|
fix: "Scope `allowed-tools` to the specific commands the skill needs (e.g. `Bash(git status:*)`); avoid a bare `Bash`, `Write` or `Edit`."
|
|
86994
87256
|
}
|
|
@@ -87120,7 +87382,7 @@ function ownPackageNames(manifests) {
|
|
|
87120
87382
|
}
|
|
87121
87383
|
return out;
|
|
87122
87384
|
}
|
|
87123
|
-
function analyzeMcp(
|
|
87385
|
+
function analyzeMcp(path110, content, own = /* @__PURE__ */ new Set()) {
|
|
87124
87386
|
let cfg;
|
|
87125
87387
|
try {
|
|
87126
87388
|
cfg = JSON.parse(content);
|
|
@@ -87156,9 +87418,9 @@ function analyzeMcp(path108, content, own = /* @__PURE__ */ new Set()) {
|
|
|
87156
87418
|
const key = (count.get(name) ?? 0) > 1 ? `${section}.${name}` : name;
|
|
87157
87419
|
servers[key] = { ...spec, anchor: name };
|
|
87158
87420
|
}
|
|
87159
|
-
return analyzeMcpServers(servers,
|
|
87421
|
+
return analyzeMcpServers(servers, path110, content, own);
|
|
87160
87422
|
}
|
|
87161
|
-
function analyzeMcpServers(servers,
|
|
87423
|
+
function analyzeMcpServers(servers, path110, content = "", own = /* @__PURE__ */ new Set()) {
|
|
87162
87424
|
const findings = [];
|
|
87163
87425
|
for (const [name, srv] of Object.entries(servers ?? {})) {
|
|
87164
87426
|
if (!srv || srv.disabled) continue;
|
|
@@ -87177,7 +87439,7 @@ function analyzeMcpServers(servers, path108, content = "", own = /* @__PURE__ */
|
|
|
87177
87439
|
dimension: "mcp",
|
|
87178
87440
|
severity: "medium",
|
|
87179
87441
|
title: `MCP server "${name}" runs an unpinned executable`,
|
|
87180
|
-
file:
|
|
87442
|
+
file: path110,
|
|
87181
87443
|
...line ? { line } : {},
|
|
87182
87444
|
signals: [
|
|
87183
87445
|
why.launcher === "npx" ? `\`${safeText(argv, 120)}\`: unversioned/@latest npx` : `\`${safeText(argv, 120)}\`: unversioned/latest ${why.launcher}`
|
|
@@ -87202,7 +87464,7 @@ function analyzeMcpServers(servers, path108, content = "", own = /* @__PURE__ */
|
|
|
87202
87464
|
dimension: "mcp",
|
|
87203
87465
|
severity: "high",
|
|
87204
87466
|
title: `MCP server "${name}" has an inline credential`,
|
|
87205
|
-
file:
|
|
87467
|
+
file: path110,
|
|
87206
87468
|
...line ? { line } : {},
|
|
87207
87469
|
signals: [
|
|
87208
87470
|
`env.${k} matches ${hit.patternName}: agent-reachable secret committed to the repo`
|
|
@@ -87218,7 +87480,7 @@ function analyzeMcpServers(servers, path108, content = "", own = /* @__PURE__ */
|
|
|
87218
87480
|
// src/ci-check/codex.ts
|
|
87219
87481
|
init_cjs_shims();
|
|
87220
87482
|
var import_smol_toml7 = require("smol-toml");
|
|
87221
|
-
function analyzeCodexConfig(
|
|
87483
|
+
function analyzeCodexConfig(path110, content, own = /* @__PURE__ */ new Set()) {
|
|
87222
87484
|
let cfg;
|
|
87223
87485
|
try {
|
|
87224
87486
|
cfg = (0, import_smol_toml7.parse)(content);
|
|
@@ -87226,7 +87488,7 @@ function analyzeCodexConfig(path108, content, own = /* @__PURE__ */ new Set()) {
|
|
|
87226
87488
|
return [];
|
|
87227
87489
|
}
|
|
87228
87490
|
const findings = [];
|
|
87229
|
-
findings.push(...analyzeMcpServers(cfg.mcp_servers ?? {},
|
|
87491
|
+
findings.push(...analyzeMcpServers(cfg.mcp_servers ?? {}, path110, content, own));
|
|
87230
87492
|
const sandbox = typeof cfg.sandbox_mode === "string" ? cfg.sandbox_mode : "";
|
|
87231
87493
|
const approval = typeof cfg.approval_policy === "string" ? cfg.approval_policy : "";
|
|
87232
87494
|
const fullAccess = /danger-full-access/i.test(sandbox);
|
|
@@ -87249,7 +87511,7 @@ function analyzeCodexConfig(path108, content, own = /* @__PURE__ */ new Set()) {
|
|
|
87249
87511
|
dimension: "toolRules",
|
|
87250
87512
|
severity: fullAccess ? "high" : "medium",
|
|
87251
87513
|
title: fullAccess ? "Codex config grants a full-access sandbox" : "Codex config never requires approval",
|
|
87252
|
-
file:
|
|
87514
|
+
file: path110,
|
|
87253
87515
|
signals,
|
|
87254
87516
|
fix: 'Commit a least-privilege Codex config: prefer `sandbox_mode = "read-only"` (or `"workspace-write"`) and `approval_policy = "on-request"`/`"on-failure"`. A repo-committed config applies to every contributor who runs Codex here.'
|
|
87255
87517
|
});
|
|
@@ -87303,7 +87565,7 @@ function reviewQuestion(rule) {
|
|
|
87303
87565
|
return "Is this an instruction the agent follows, or text for a person?";
|
|
87304
87566
|
}
|
|
87305
87567
|
var RANK2 = { critical: 4, high: 3, medium: 2, advisory: 1 };
|
|
87306
|
-
var worstRank = (
|
|
87568
|
+
var worstRank = (fs111) => Math.max(...fs111.map((f) => RANK2[f.severity] ?? 0));
|
|
87307
87569
|
var fileOrder = (a, b) => worstRank(b[1]) - worstRank(a[1]) || b[1].length - a[1].length;
|
|
87308
87570
|
function groupReview(findings) {
|
|
87309
87571
|
const byFile = /* @__PURE__ */ new Map();
|
|
@@ -87368,7 +87630,7 @@ function logicalLines2(content) {
|
|
|
87368
87630
|
}
|
|
87369
87631
|
return out;
|
|
87370
87632
|
}
|
|
87371
|
-
function analyzeScript(
|
|
87633
|
+
function analyzeScript(path110, content, rulePrefix) {
|
|
87372
87634
|
const check = rulePrefix.startsWith("CI-1") ? "CI-1" : "CI-6";
|
|
87373
87635
|
const dimension = check === "CI-1" ? "toolRules" : "instructions";
|
|
87374
87636
|
const mk3 = (suffix, severity, title, signal, fix, line) => ({
|
|
@@ -87377,7 +87639,7 @@ function analyzeScript(path108, content, rulePrefix) {
|
|
|
87377
87639
|
dimension,
|
|
87378
87640
|
severity,
|
|
87379
87641
|
title,
|
|
87380
|
-
file:
|
|
87642
|
+
file: path110,
|
|
87381
87643
|
...line ? { line } : {},
|
|
87382
87644
|
signals: [signal],
|
|
87383
87645
|
fix
|
|
@@ -87803,7 +88065,7 @@ async function scanRepo(input, onProgress) {
|
|
|
87803
88065
|
// src/ci-check/render.ts
|
|
87804
88066
|
init_cjs_shims();
|
|
87805
88067
|
var import_chalk36 = __toESM(require("chalk"));
|
|
87806
|
-
var listed = (
|
|
88068
|
+
var listed = (fs111) => fs111.filter((f) => f.tier !== "review");
|
|
87807
88069
|
function excerpt(f) {
|
|
87808
88070
|
const m = /`([^`]+)`/.exec(f.signals[0] ?? "");
|
|
87809
88071
|
return safeText(m ? m[1] : f.title, 120).replace(/`/g, "'");
|
|
@@ -87819,14 +88081,14 @@ function reviewMd(findings) {
|
|
|
87819
88081
|
L.push("");
|
|
87820
88082
|
const files = [...byFile.keys()];
|
|
87821
88083
|
for (const file2 of files.slice(0, REVIEW_FILES)) {
|
|
87822
|
-
const
|
|
88084
|
+
const fs111 = byFile.get(file2);
|
|
87823
88085
|
L.push(`- \`${safeText(file2, 300)}\``);
|
|
87824
|
-
for (const f of
|
|
88086
|
+
for (const f of fs111.slice(0, REVIEW_LINES_PER_FILE))
|
|
87825
88087
|
L.push(
|
|
87826
88088
|
` - ${f.line ? `line ${Number(f.line)}: ` : ""}\`${excerpt(f)}\`. Check: ${reviewQuestion(f.rule)}`
|
|
87827
88089
|
);
|
|
87828
|
-
if (
|
|
87829
|
-
L.push(` - and ${
|
|
88090
|
+
if (fs111.length > REVIEW_LINES_PER_FILE)
|
|
88091
|
+
L.push(` - and ${fs111.length - REVIEW_LINES_PER_FILE} similar lines in this file`);
|
|
87830
88092
|
}
|
|
87831
88093
|
const more = files.length - REVIEW_FILES;
|
|
87832
88094
|
if (more > 0) L.push(`- and ${more} more file${more === 1 ? "" : "s"}`);
|
|
@@ -87842,7 +88104,7 @@ function reviewMd(findings) {
|
|
|
87842
88104
|
}
|
|
87843
88105
|
function reviewTerminal(findings) {
|
|
87844
88106
|
const { byFile, grants } = groupReview(findings);
|
|
87845
|
-
const items = [...byFile.values()].reduce((a,
|
|
88107
|
+
const items = [...byFile.values()].reduce((a, fs111) => a + fs111.length, 0);
|
|
87846
88108
|
if (!items && !grants) return [];
|
|
87847
88109
|
const L = [];
|
|
87848
88110
|
if (items) {
|
|
@@ -87851,12 +88113,12 @@ function reviewTerminal(findings) {
|
|
|
87851
88113
|
);
|
|
87852
88114
|
const files = [...byFile.keys()];
|
|
87853
88115
|
for (const file2 of files.slice(0, REVIEW_FILES)) {
|
|
87854
|
-
const
|
|
88116
|
+
const fs111 = byFile.get(file2);
|
|
87855
88117
|
L.push(import_chalk36.default.gray(` ${file2}`));
|
|
87856
|
-
for (const f of
|
|
88118
|
+
for (const f of fs111.slice(0, REVIEW_LINES_PER_FILE))
|
|
87857
88119
|
L.push(` \u2022 ${f.line ? `line ${f.line}: ` : ""}${excerpt(f)}`);
|
|
87858
|
-
if (
|
|
87859
|
-
L.push(import_chalk36.default.gray(` and ${
|
|
88120
|
+
if (fs111.length > REVIEW_LINES_PER_FILE)
|
|
88121
|
+
L.push(import_chalk36.default.gray(` and ${fs111.length - REVIEW_LINES_PER_FILE} similar lines`));
|
|
87860
88122
|
}
|
|
87861
88123
|
const more = files.length - REVIEW_FILES;
|
|
87862
88124
|
if (more > 0) L.push(import_chalk36.default.gray(` and ${more} more file${more === 1 ? "" : "s"}`));
|
|
@@ -87870,7 +88132,7 @@ function reviewTerminal(findings) {
|
|
|
87870
88132
|
L.push("");
|
|
87871
88133
|
return L;
|
|
87872
88134
|
}
|
|
87873
|
-
var
|
|
88135
|
+
var ICON3 = {
|
|
87874
88136
|
critical: "\u{1F534}",
|
|
87875
88137
|
high: "\u{1F534}",
|
|
87876
88138
|
medium: "\u{1F7E1}",
|
|
@@ -87930,7 +88192,7 @@ function mdLine(v) {
|
|
|
87930
88192
|
function findingMd(f, L) {
|
|
87931
88193
|
const ex = f.explain;
|
|
87932
88194
|
L.push(
|
|
87933
|
-
`**${
|
|
88195
|
+
`**${ICON3[f.severity]} ${f.severity.toUpperCase()}: ${mdLine(ex ? ex.headline : f.title)}**` + (f.suppressed ? ` _(suppressed: \`${safeText(f.suppressed.reason, 200)}\`)_` : "")
|
|
87934
88196
|
);
|
|
87935
88197
|
L.push(`\`${safeText(f.file, 300)}${f.line ? ":" + Number(f.line) : ""}\` \xB7 ${f.rule}`);
|
|
87936
88198
|
L.push("");
|
|
@@ -87986,7 +88248,7 @@ function renderScan(res, diff) {
|
|
|
87986
88248
|
for (const f of shown) {
|
|
87987
88249
|
const ex = f.explain;
|
|
87988
88250
|
L.push(
|
|
87989
|
-
`${
|
|
88251
|
+
`${ICON3[f.severity]} ${COLOR[f.severity](f.severity.toUpperCase())} ${import_chalk36.default.bold(ex ? ex.headline : f.title)}`
|
|
87990
88252
|
);
|
|
87991
88253
|
L.push(import_chalk36.default.gray(` ${f.file}${f.line ? ":" + f.line : ""} \xB7 ${f.check}`));
|
|
87992
88254
|
if (ex) {
|
|
@@ -88508,16 +88770,16 @@ var import_chalk40 = __toESM(require("chalk"));
|
|
|
88508
88770
|
|
|
88509
88771
|
// src/canary/plant.ts
|
|
88510
88772
|
init_cjs_shims();
|
|
88511
|
-
var
|
|
88512
|
-
var
|
|
88513
|
-
var
|
|
88773
|
+
var import_fs95 = __toESM(require("fs"));
|
|
88774
|
+
var import_os77 = __toESM(require("os"));
|
|
88775
|
+
var import_path94 = __toESM(require("path"));
|
|
88514
88776
|
init_jail();
|
|
88515
88777
|
init_registry2();
|
|
88516
88778
|
|
|
88517
88779
|
// src/canary/sites.ts
|
|
88518
88780
|
init_cjs_shims();
|
|
88519
|
-
var
|
|
88520
|
-
var
|
|
88781
|
+
var import_fs94 = __toESM(require("fs"));
|
|
88782
|
+
var import_path93 = __toESM(require("path"));
|
|
88521
88783
|
|
|
88522
88784
|
// src/canary/generate.ts
|
|
88523
88785
|
init_cjs_shims();
|
|
@@ -88612,26 +88874,26 @@ function generateSshKey() {
|
|
|
88612
88874
|
var SITES = {
|
|
88613
88875
|
"aws-profile": {
|
|
88614
88876
|
kind: "aws-profile",
|
|
88615
|
-
primary: (h) =>
|
|
88616
|
-
fallback: (h) =>
|
|
88877
|
+
primary: (h) => import_path93.default.join(h, ".aws", "credentials"),
|
|
88878
|
+
fallback: (h) => import_path93.default.join(h, ".aws", "credentials.bak"),
|
|
88617
88879
|
// SSO / profile-only / credential_process setups have ~/.aws/config and no
|
|
88618
88880
|
// credentials file; the SDK and CLI then parse ~/.aws/credentials on every
|
|
88619
88881
|
// profile lookup. A planted primary would be a file real tools read.
|
|
88620
|
-
preferFallback: (h) =>
|
|
88882
|
+
preferFallback: (h) => import_fs94.default.existsSync(import_path93.default.join(h, ".aws", "config")),
|
|
88621
88883
|
dirMode: 448,
|
|
88622
88884
|
generate: generateAwsProfile
|
|
88623
88885
|
},
|
|
88624
88886
|
"env-file": {
|
|
88625
88887
|
kind: "env-file",
|
|
88626
|
-
primary: (h) =>
|
|
88627
|
-
fallback: (h) =>
|
|
88888
|
+
primary: (h) => import_path93.default.join(h, ".env.bak"),
|
|
88889
|
+
fallback: (h) => import_path93.default.join(h, ".env.local.bak"),
|
|
88628
88890
|
dirMode: 493,
|
|
88629
88891
|
generate: generateEnvFile
|
|
88630
88892
|
},
|
|
88631
88893
|
"ssh-key": {
|
|
88632
88894
|
kind: "ssh-key",
|
|
88633
|
-
primary: (h) =>
|
|
88634
|
-
fallback: (h) =>
|
|
88895
|
+
primary: (h) => import_path93.default.join(h, ".ssh", "id_rsa_backup"),
|
|
88896
|
+
fallback: (h) => import_path93.default.join(h, ".ssh", "id_rsa.old"),
|
|
88635
88897
|
// ssh refuses a group-writable ~/.ssh for config / known_hosts reads.
|
|
88636
88898
|
dirMode: 448,
|
|
88637
88899
|
generate: generateSshKey
|
|
@@ -88644,12 +88906,12 @@ var isKind = (s) => ALL_KINDS.includes(s);
|
|
|
88644
88906
|
var liveRecords = (kind) => loadCanaries().filter((r) => r.kind === kind && !r.retiredAt);
|
|
88645
88907
|
var fileHashOf = (p) => {
|
|
88646
88908
|
try {
|
|
88647
|
-
return sha256Hex(
|
|
88909
|
+
return sha256Hex(import_fs95.default.readFileSync(p));
|
|
88648
88910
|
} catch {
|
|
88649
88911
|
return null;
|
|
88650
88912
|
}
|
|
88651
88913
|
};
|
|
88652
|
-
function plantKind(kind, home =
|
|
88914
|
+
function plantKind(kind, home = import_os77.default.homedir()) {
|
|
88653
88915
|
const site = SITES[kind];
|
|
88654
88916
|
const live = liveRecords(kind);
|
|
88655
88917
|
if (live.length > 0) {
|
|
@@ -88668,8 +88930,8 @@ function plantKind(kind, home = import_os76.default.homedir()) {
|
|
|
88668
88930
|
const primary = site.primary(home);
|
|
88669
88931
|
const fallback = site.fallback(home);
|
|
88670
88932
|
let target;
|
|
88671
|
-
if (!
|
|
88672
|
-
else if (!
|
|
88933
|
+
if (!import_fs95.default.existsSync(primary) && !site.preferFallback?.(home)) target = primary;
|
|
88934
|
+
else if (!import_fs95.default.existsSync(fallback)) target = fallback;
|
|
88673
88935
|
else {
|
|
88674
88936
|
return {
|
|
88675
88937
|
kind,
|
|
@@ -88680,11 +88942,11 @@ function plantKind(kind, home = import_os76.default.homedir()) {
|
|
|
88680
88942
|
recordIds: []
|
|
88681
88943
|
};
|
|
88682
88944
|
}
|
|
88683
|
-
const dir2 =
|
|
88945
|
+
const dir2 = import_path94.default.dirname(target);
|
|
88684
88946
|
const gen = site.generate();
|
|
88685
|
-
const createdDir =
|
|
88686
|
-
|
|
88687
|
-
|
|
88947
|
+
const createdDir = import_fs95.default.mkdirSync(dir2, { recursive: true, mode: site.dirMode }) !== void 0;
|
|
88948
|
+
import_fs95.default.writeFileSync(target, gen.text, { mode: 384, flag: "wx" });
|
|
88949
|
+
import_fs95.default.chmodSync(target, 384);
|
|
88688
88950
|
const fileHash = sha256Hex(gen.text);
|
|
88689
88951
|
regenerateUserJail(addJailPath(target, "block"));
|
|
88690
88952
|
const recordIds = gen.values.map(
|
|
@@ -88702,14 +88964,14 @@ function plantKind(kind, home = import_os76.default.homedir()) {
|
|
|
88702
88964
|
}
|
|
88703
88965
|
function allowedPathsFor(kind, home) {
|
|
88704
88966
|
const site = SITES[kind];
|
|
88705
|
-
return [site.primary(home), site.fallback(home)].map((x) =>
|
|
88967
|
+
return [site.primary(home), site.fallback(home)].map((x) => import_path94.default.resolve(x));
|
|
88706
88968
|
}
|
|
88707
|
-
function removeKind(kind, home =
|
|
88969
|
+
function removeKind(kind, home = import_os77.default.homedir()) {
|
|
88708
88970
|
const live = liveRecords(kind);
|
|
88709
88971
|
if (live.length === 0) return { kind, action: "absent" };
|
|
88710
88972
|
const p = live[0].path;
|
|
88711
88973
|
const { fileHash, createdDir } = live[0];
|
|
88712
|
-
if (!allowedPathsFor(kind, home).includes(
|
|
88974
|
+
if (!allowedPathsFor(kind, home).includes(import_path94.default.resolve(p))) {
|
|
88713
88975
|
return {
|
|
88714
88976
|
kind,
|
|
88715
88977
|
action: "refused",
|
|
@@ -88717,7 +88979,7 @@ function removeKind(kind, home = import_os76.default.homedir()) {
|
|
|
88717
88979
|
reason: `${p} is not a path node9 plants a ${kind} decoy at; refusing to delete it. If you believe this is a decoy, remove it by hand.`
|
|
88718
88980
|
};
|
|
88719
88981
|
}
|
|
88720
|
-
if (!
|
|
88982
|
+
if (!import_fs95.default.existsSync(p)) {
|
|
88721
88983
|
for (const r of live) retireCanary(r.id);
|
|
88722
88984
|
unjail(p);
|
|
88723
88985
|
return { kind, action: "already-gone", path: p };
|
|
@@ -88730,13 +88992,13 @@ function removeKind(kind, home = import_os76.default.homedir()) {
|
|
|
88730
88992
|
reason: `${p} changed since node9 wrote it; inspect and remove it by hand`
|
|
88731
88993
|
};
|
|
88732
88994
|
}
|
|
88733
|
-
|
|
88995
|
+
import_fs95.default.unlinkSync(p);
|
|
88734
88996
|
let dirRemoved = false;
|
|
88735
88997
|
if (createdDir) {
|
|
88736
|
-
const dir2 =
|
|
88998
|
+
const dir2 = import_path94.default.dirname(p);
|
|
88737
88999
|
try {
|
|
88738
|
-
if (
|
|
88739
|
-
|
|
89000
|
+
if (import_fs95.default.readdirSync(dir2).length === 0) {
|
|
89001
|
+
import_fs95.default.rmdirSync(dir2);
|
|
88740
89002
|
dirRemoved = true;
|
|
88741
89003
|
}
|
|
88742
89004
|
} catch {
|
|
@@ -88760,14 +89022,14 @@ function statusAll() {
|
|
|
88760
89022
|
const p = live[0].path;
|
|
88761
89023
|
return {
|
|
88762
89024
|
kind,
|
|
88763
|
-
state:
|
|
89025
|
+
state: import_fs95.default.existsSync(p) ? "planted" : "missing",
|
|
88764
89026
|
path: p,
|
|
88765
89027
|
records: live.length,
|
|
88766
89028
|
plantedAt: live[0].plantedAt
|
|
88767
89029
|
};
|
|
88768
89030
|
});
|
|
88769
89031
|
}
|
|
88770
|
-
function rotateKind(kind, home =
|
|
89032
|
+
function rotateKind(kind, home = import_os77.default.homedir()) {
|
|
88771
89033
|
const removed = removeKind(kind);
|
|
88772
89034
|
if (removed.action === "refused") return { removed };
|
|
88773
89035
|
return { removed, planted: plantKind(kind, home) };
|
|
@@ -88856,15 +89118,15 @@ init_daemon3();
|
|
|
88856
89118
|
// src/cli/commands/sandbox.ts
|
|
88857
89119
|
init_cjs_shims();
|
|
88858
89120
|
var import_chalk41 = __toESM(require("chalk"));
|
|
88859
|
-
var
|
|
88860
|
-
var
|
|
89121
|
+
var import_fs98 = __toESM(require("fs"));
|
|
89122
|
+
var import_path97 = __toESM(require("path"));
|
|
88861
89123
|
var import_child_process16 = require("child_process");
|
|
88862
89124
|
init_config();
|
|
88863
89125
|
|
|
88864
89126
|
// src/sandbox/config.ts
|
|
88865
89127
|
init_cjs_shims();
|
|
88866
|
-
var
|
|
88867
|
-
var
|
|
89128
|
+
var import_fs96 = __toESM(require("fs"));
|
|
89129
|
+
var import_path95 = __toESM(require("path"));
|
|
88868
89130
|
var import_yaml2 = require("yaml");
|
|
88869
89131
|
var SANDBOX_CONFIG_FILE = "node9.sandbox.yaml";
|
|
88870
89132
|
var FORBIDDEN_ENV = /* @__PURE__ */ new Set(["NODE9_API_KEY", "NODE9_API_URL"]);
|
|
@@ -88937,16 +89199,16 @@ function scaffoldSandboxYaml(agent) {
|
|
|
88937
89199
|
return header + (0, import_yaml2.stringify)(defaultSandboxConfig(agent));
|
|
88938
89200
|
}
|
|
88939
89201
|
function sandboxConfigPath(cwd = process.cwd()) {
|
|
88940
|
-
return
|
|
89202
|
+
return import_path95.default.join(cwd, SANDBOX_CONFIG_FILE);
|
|
88941
89203
|
}
|
|
88942
89204
|
function loadSandboxConfig(cwd = process.cwd(), fallbackAgent = "claude") {
|
|
88943
89205
|
const p = sandboxConfigPath(cwd);
|
|
88944
|
-
if (!
|
|
89206
|
+
if (!import_fs96.default.existsSync(p)) {
|
|
88945
89207
|
throw new Error(`sandbox: ${SANDBOX_CONFIG_FILE} not found \u2014 run \`node9 sandbox new\` first.`);
|
|
88946
89208
|
}
|
|
88947
89209
|
let raw;
|
|
88948
89210
|
try {
|
|
88949
|
-
raw = (0, import_yaml2.parse)(
|
|
89211
|
+
raw = (0, import_yaml2.parse)(import_fs96.default.readFileSync(p, "utf-8"));
|
|
88950
89212
|
} catch (err2) {
|
|
88951
89213
|
throw new Error(
|
|
88952
89214
|
`sandbox: ${SANDBOX_CONFIG_FILE} is not valid YAML \u2014 ${err2.message}`
|
|
@@ -89007,14 +89269,14 @@ init_atomic_write();
|
|
|
89007
89269
|
|
|
89008
89270
|
// src/sandbox/runtime.ts
|
|
89009
89271
|
init_cjs_shims();
|
|
89010
|
-
var
|
|
89011
|
-
var
|
|
89012
|
-
var
|
|
89272
|
+
var import_fs97 = __toESM(require("fs"));
|
|
89273
|
+
var import_os78 = __toESM(require("os"));
|
|
89274
|
+
var import_path96 = __toESM(require("path"));
|
|
89013
89275
|
var import_crypto26 = __toESM(require("crypto"));
|
|
89014
89276
|
var import_child_process15 = require("child_process");
|
|
89015
89277
|
init_templates();
|
|
89016
89278
|
function sandboxDataDir(cwd = process.cwd()) {
|
|
89017
|
-
return
|
|
89279
|
+
return import_path96.default.join(cwd, ".node9", "sandbox", "data");
|
|
89018
89280
|
}
|
|
89019
89281
|
function detectEngine(engine) {
|
|
89020
89282
|
const r = (0, import_child_process15.spawnSync)(engine, ["--version"], { encoding: "utf-8" });
|
|
@@ -89025,7 +89287,7 @@ function detectEngine(engine) {
|
|
|
89025
89287
|
}
|
|
89026
89288
|
function agentCredentialsMount(agent) {
|
|
89027
89289
|
const rel = agent === "codex" ? ".codex/auth.json" : ".claude/.credentials.json";
|
|
89028
|
-
return { hostPath:
|
|
89290
|
+
return { hostPath: import_path96.default.join(import_os78.default.homedir(), rel), target: `/home/${RUN_AS_USER}/${rel}` };
|
|
89029
89291
|
}
|
|
89030
89292
|
function buildRunArgs(opts) {
|
|
89031
89293
|
const { config, workspaceHostPath, dataHostPath, allowlistHostPath, agentArgs } = opts;
|
|
@@ -89035,7 +89297,7 @@ function buildRunArgs(opts) {
|
|
|
89035
89297
|
args.push("-v", `${allowlistHostPath}:${ALLOWED_DOMAINS_PATH}:ro`);
|
|
89036
89298
|
if (config.node9.mountAgentCredentials) {
|
|
89037
89299
|
const creds = agentCredentialsMount(config.agent);
|
|
89038
|
-
if (
|
|
89300
|
+
if (import_fs97.default.existsSync(creds.hostPath)) {
|
|
89039
89301
|
args.push("-v", `${creds.hostPath}:${creds.target}`);
|
|
89040
89302
|
}
|
|
89041
89303
|
}
|
|
@@ -89053,30 +89315,30 @@ function imageContentHash(dockerfile, entrypoint) {
|
|
|
89053
89315
|
return import_crypto26.default.createHash("sha256").update(dockerfile).update("\0").update(entrypoint).digest("hex").slice(0, 16);
|
|
89054
89316
|
}
|
|
89055
89317
|
function sandboxBuildDir(cwd = process.cwd()) {
|
|
89056
|
-
return
|
|
89318
|
+
return import_path96.default.join(cwd, ".node9", "sandbox", "build");
|
|
89057
89319
|
}
|
|
89058
89320
|
function writeBuildContext(cwd, dockerfile, entrypoint) {
|
|
89059
89321
|
const dir2 = sandboxBuildDir(cwd);
|
|
89060
|
-
|
|
89061
|
-
|
|
89062
|
-
|
|
89322
|
+
import_fs97.default.mkdirSync(dir2, { recursive: true });
|
|
89323
|
+
import_fs97.default.writeFileSync(import_path96.default.join(dir2, "Dockerfile"), dockerfile);
|
|
89324
|
+
import_fs97.default.writeFileSync(import_path96.default.join(dir2, "entrypoint.sh"), entrypoint);
|
|
89063
89325
|
return dir2;
|
|
89064
89326
|
}
|
|
89065
89327
|
function writeAllowlist(cwd, hosts) {
|
|
89066
|
-
const dir2 =
|
|
89067
|
-
|
|
89068
|
-
const p =
|
|
89069
|
-
|
|
89328
|
+
const dir2 = import_path96.default.join(cwd, ".node9", "sandbox");
|
|
89329
|
+
import_fs97.default.mkdirSync(dir2, { recursive: true });
|
|
89330
|
+
const p = import_path96.default.join(dir2, "allowed-domains.txt");
|
|
89331
|
+
import_fs97.default.writeFileSync(p, hosts.join("\n") + "\n");
|
|
89070
89332
|
return p;
|
|
89071
89333
|
}
|
|
89072
89334
|
function resolveHomePath(p) {
|
|
89073
|
-
return p.startsWith("~") ?
|
|
89335
|
+
return p.startsWith("~") ? import_path96.default.join(import_os78.default.homedir(), p.slice(1)) : import_path96.default.resolve(p);
|
|
89074
89336
|
}
|
|
89075
89337
|
|
|
89076
89338
|
// src/cli/commands/sandbox.ts
|
|
89077
89339
|
function seedDataDirConfig(dataDir, sandbox) {
|
|
89078
|
-
|
|
89079
|
-
const configPath2 =
|
|
89340
|
+
import_fs98.default.mkdirSync(dataDir, { recursive: true });
|
|
89341
|
+
const configPath2 = import_path97.default.join(dataDir, "config.json");
|
|
89080
89342
|
const seed = {
|
|
89081
89343
|
settings: {
|
|
89082
89344
|
approvers: {
|
|
@@ -89087,7 +89349,7 @@ function seedDataDirConfig(dataDir, sandbox) {
|
|
|
89087
89349
|
}
|
|
89088
89350
|
}
|
|
89089
89351
|
};
|
|
89090
|
-
|
|
89352
|
+
import_fs98.default.writeFileSync(configPath2, JSON.stringify(seed, null, 2), { mode: 384 });
|
|
89091
89353
|
}
|
|
89092
89354
|
function registerSandboxCommand(program2, version2) {
|
|
89093
89355
|
const node9Version2 = pinnedNode9Version(version2);
|
|
@@ -89096,7 +89358,7 @@ function registerSandboxCommand(program2, version2) {
|
|
|
89096
89358
|
const agent = opts.agent === "codex" ? "codex" : "claude";
|
|
89097
89359
|
const p = sandboxConfigPath();
|
|
89098
89360
|
try {
|
|
89099
|
-
|
|
89361
|
+
import_fs98.default.writeFileSync(p, scaffoldSandboxYaml(agent), { flag: "wx" });
|
|
89100
89362
|
} catch (e) {
|
|
89101
89363
|
if (e.code !== "EEXIST") throw e;
|
|
89102
89364
|
console.log(
|
|
@@ -89143,8 +89405,8 @@ function registerSandboxCommand(program2, version2) {
|
|
|
89143
89405
|
const buildDir = writeBuildContext(cwd, dockerfile, entrypoint);
|
|
89144
89406
|
const hash2 = imageContentHash(dockerfile, entrypoint);
|
|
89145
89407
|
const image = sandbox.runtime.image;
|
|
89146
|
-
const hashFile =
|
|
89147
|
-
const lastHash =
|
|
89408
|
+
const hashFile = import_path97.default.join(sandboxBuildDir(cwd), ".image-hash");
|
|
89409
|
+
const lastHash = import_fs98.default.existsSync(hashFile) ? import_fs98.default.readFileSync(hashFile, "utf-8").trim() : "";
|
|
89148
89410
|
const imageExists = (0, import_child_process16.spawnSync)(sandbox.runtime.engine, ["image", "inspect", image], { stdio: "ignore" }).status === 0;
|
|
89149
89411
|
const needBuild = sandbox.runtime.rebuild === "always" || !imageExists || sandbox.runtime.rebuild !== "never" && lastHash !== hash2;
|
|
89150
89412
|
if (needBuild) {
|
|
@@ -89170,7 +89432,7 @@ function registerSandboxCommand(program2, version2) {
|
|
|
89170
89432
|
});
|
|
89171
89433
|
if (sandbox.node9.mountAgentCredentials) {
|
|
89172
89434
|
const creds = agentCredentialsMount(sandbox.agent);
|
|
89173
|
-
if (
|
|
89435
|
+
if (import_fs98.default.existsSync(creds.hostPath)) {
|
|
89174
89436
|
console.log(import_chalk41.default.dim(` mounting ${creds.hostPath} (agent credentials, rw)`));
|
|
89175
89437
|
} else {
|
|
89176
89438
|
console.log(
|
|
@@ -89186,20 +89448,20 @@ function registerSandboxCommand(program2, version2) {
|
|
|
89186
89448
|
process.exit(r.status ?? 0);
|
|
89187
89449
|
});
|
|
89188
89450
|
cmd.command("tail").description("Stream the sandbox's audit log (host-side)").action(() => {
|
|
89189
|
-
const auditPath =
|
|
89190
|
-
if (!
|
|
89451
|
+
const auditPath = import_path97.default.join(sandboxDataDir(), "audit.log");
|
|
89452
|
+
if (!import_fs98.default.existsSync(auditPath)) {
|
|
89191
89453
|
console.log(import_chalk41.default.dim(" no sandbox audit yet."));
|
|
89192
89454
|
return;
|
|
89193
89455
|
}
|
|
89194
89456
|
(0, import_child_process16.spawnSync)("tail", ["-f", auditPath], { stdio: "inherit" });
|
|
89195
89457
|
});
|
|
89196
89458
|
cmd.command("logs").description("Dump the sandbox's audit log").action(() => {
|
|
89197
|
-
const auditPath =
|
|
89198
|
-
if (!
|
|
89459
|
+
const auditPath = import_path97.default.join(sandboxDataDir(), "audit.log");
|
|
89460
|
+
if (!import_fs98.default.existsSync(auditPath)) {
|
|
89199
89461
|
console.log(import_chalk41.default.dim(" no sandbox audit yet."));
|
|
89200
89462
|
return;
|
|
89201
89463
|
}
|
|
89202
|
-
process.stdout.write(
|
|
89464
|
+
process.stdout.write(import_fs98.default.readFileSync(auditPath, "utf-8"));
|
|
89203
89465
|
});
|
|
89204
89466
|
cmd.command("clean").description("Remove the sandbox image, build context, and data").action(() => {
|
|
89205
89467
|
const cwd = process.cwd();
|
|
@@ -89213,7 +89475,7 @@ function registerSandboxCommand(program2, version2) {
|
|
|
89213
89475
|
stdio: "ignore"
|
|
89214
89476
|
});
|
|
89215
89477
|
}
|
|
89216
|
-
|
|
89478
|
+
import_fs98.default.rmSync(import_path97.default.join(cwd, ".node9", "sandbox"), { recursive: true, force: true });
|
|
89217
89479
|
console.log(import_chalk41.default.green(" \u2713 sandbox image + build + data removed."));
|
|
89218
89480
|
});
|
|
89219
89481
|
}
|
|
@@ -89442,12 +89704,12 @@ function registerPackageIndexCommand(program2) {
|
|
|
89442
89704
|
// src/cli/commands/skill-pin.ts
|
|
89443
89705
|
init_cjs_shims();
|
|
89444
89706
|
var import_chalk45 = __toESM(require("chalk"));
|
|
89445
|
-
var
|
|
89446
|
-
var
|
|
89447
|
-
var
|
|
89707
|
+
var import_fs99 = __toESM(require("fs"));
|
|
89708
|
+
var import_os79 = __toESM(require("os"));
|
|
89709
|
+
var import_path98 = __toESM(require("path"));
|
|
89448
89710
|
function wipeSkillSessions() {
|
|
89449
89711
|
try {
|
|
89450
|
-
|
|
89712
|
+
import_fs99.default.rmSync(import_path98.default.join(import_os79.default.homedir(), ".node9", "skill-sessions"), {
|
|
89451
89713
|
recursive: true,
|
|
89452
89714
|
force: true
|
|
89453
89715
|
});
|
|
@@ -89530,15 +89792,15 @@ function registerSkillPinCommand(program2) {
|
|
|
89530
89792
|
|
|
89531
89793
|
// src/cli/commands/decisions.ts
|
|
89532
89794
|
init_cjs_shims();
|
|
89533
|
-
var
|
|
89534
|
-
var
|
|
89535
|
-
var
|
|
89795
|
+
var import_fs100 = __toESM(require("fs"));
|
|
89796
|
+
var import_os80 = __toESM(require("os"));
|
|
89797
|
+
var import_path99 = __toESM(require("path"));
|
|
89536
89798
|
var import_chalk46 = __toESM(require("chalk"));
|
|
89537
|
-
var DECISIONS_FILE2 =
|
|
89799
|
+
var DECISIONS_FILE2 = import_path99.default.join(import_os80.default.homedir(), ".node9", "decisions.json");
|
|
89538
89800
|
function readDecisions() {
|
|
89539
89801
|
try {
|
|
89540
|
-
if (!
|
|
89541
|
-
const raw =
|
|
89802
|
+
if (!import_fs100.default.existsSync(DECISIONS_FILE2)) return {};
|
|
89803
|
+
const raw = import_fs100.default.readFileSync(DECISIONS_FILE2, "utf-8");
|
|
89542
89804
|
const parsed = JSON.parse(raw);
|
|
89543
89805
|
const out = {};
|
|
89544
89806
|
for (const [k, v] of Object.entries(parsed)) {
|
|
@@ -89550,11 +89812,11 @@ function readDecisions() {
|
|
|
89550
89812
|
}
|
|
89551
89813
|
}
|
|
89552
89814
|
function writeDecisions(d) {
|
|
89553
|
-
const dir2 =
|
|
89554
|
-
if (!
|
|
89815
|
+
const dir2 = import_path99.default.dirname(DECISIONS_FILE2);
|
|
89816
|
+
if (!import_fs100.default.existsSync(dir2)) import_fs100.default.mkdirSync(dir2, { recursive: true });
|
|
89555
89817
|
const tmp = `${DECISIONS_FILE2}.${process.pid}.tmp`;
|
|
89556
|
-
|
|
89557
|
-
|
|
89818
|
+
import_fs100.default.writeFileSync(tmp, JSON.stringify(d, null, 2));
|
|
89819
|
+
import_fs100.default.renameSync(tmp, DECISIONS_FILE2);
|
|
89558
89820
|
}
|
|
89559
89821
|
function registerDecisionsCommand(program2) {
|
|
89560
89822
|
const cmd = program2.command("decisions").description('Manage persistent "Always Allow" / "Always Deny" tool decisions');
|
|
@@ -89612,15 +89874,15 @@ Persistent decisions (${entries.length})
|
|
|
89612
89874
|
// src/cli/commands/dlp.ts
|
|
89613
89875
|
init_cjs_shims();
|
|
89614
89876
|
var import_chalk47 = __toESM(require("chalk"));
|
|
89615
|
-
var
|
|
89616
|
-
var
|
|
89617
|
-
var
|
|
89877
|
+
var import_fs101 = __toESM(require("fs"));
|
|
89878
|
+
var import_path100 = __toESM(require("path"));
|
|
89879
|
+
var import_os81 = __toESM(require("os"));
|
|
89618
89880
|
init_safe_text();
|
|
89619
|
-
var AUDIT_LOG =
|
|
89620
|
-
var RESOLVED_FILE =
|
|
89881
|
+
var AUDIT_LOG = import_path100.default.join(import_os81.default.homedir(), ".node9", "audit.log");
|
|
89882
|
+
var RESOLVED_FILE = import_path100.default.join(import_os81.default.homedir(), ".node9", "dlp-resolved.json");
|
|
89621
89883
|
function loadResolved() {
|
|
89622
89884
|
try {
|
|
89623
|
-
const raw = JSON.parse(
|
|
89885
|
+
const raw = JSON.parse(import_fs101.default.readFileSync(RESOLVED_FILE, "utf-8"));
|
|
89624
89886
|
return new Set(raw);
|
|
89625
89887
|
} catch {
|
|
89626
89888
|
return /* @__PURE__ */ new Set();
|
|
@@ -89628,13 +89890,13 @@ function loadResolved() {
|
|
|
89628
89890
|
}
|
|
89629
89891
|
function saveResolved(resolved) {
|
|
89630
89892
|
try {
|
|
89631
|
-
|
|
89893
|
+
import_fs101.default.writeFileSync(RESOLVED_FILE, JSON.stringify([...resolved], null, 2), { mode: 384 });
|
|
89632
89894
|
} catch {
|
|
89633
89895
|
}
|
|
89634
89896
|
}
|
|
89635
89897
|
function loadDlpFindings() {
|
|
89636
|
-
if (!
|
|
89637
|
-
return
|
|
89898
|
+
if (!import_fs101.default.existsSync(AUDIT_LOG)) return [];
|
|
89899
|
+
return import_fs101.default.readFileSync(AUDIT_LOG, "utf-8").split("\n").flatMap((line) => {
|
|
89638
89900
|
if (!line.trim()) return [];
|
|
89639
89901
|
try {
|
|
89640
89902
|
const e = JSON.parse(line);
|
|
@@ -89733,15 +89995,15 @@ function registerDlpCommand(program2) {
|
|
|
89733
89995
|
// src/cli/commands/mask.ts
|
|
89734
89996
|
init_cjs_shims();
|
|
89735
89997
|
var import_chalk48 = __toESM(require("chalk"));
|
|
89736
|
-
var
|
|
89737
|
-
var
|
|
89738
|
-
var
|
|
89998
|
+
var import_fs102 = __toESM(require("fs"));
|
|
89999
|
+
var import_path101 = __toESM(require("path"));
|
|
90000
|
+
var import_os82 = __toESM(require("os"));
|
|
89739
90001
|
init_dlp();
|
|
89740
90002
|
function findJsonlFiles(dir2) {
|
|
89741
90003
|
const results = [];
|
|
89742
|
-
if (!
|
|
89743
|
-
for (const entry of
|
|
89744
|
-
const full =
|
|
90004
|
+
if (!import_fs102.default.existsSync(dir2)) return results;
|
|
90005
|
+
for (const entry of import_fs102.default.readdirSync(dir2, { withFileTypes: true })) {
|
|
90006
|
+
const full = import_path101.default.join(dir2, entry.name);
|
|
89745
90007
|
if (entry.isDirectory()) results.push(...findJsonlFiles(full));
|
|
89746
90008
|
else if (entry.isFile() && entry.name.endsWith(".jsonl")) results.push(full);
|
|
89747
90009
|
}
|
|
@@ -89784,7 +90046,7 @@ function redactJson(obj) {
|
|
|
89784
90046
|
function processFile(filePath, dryRun) {
|
|
89785
90047
|
let raw;
|
|
89786
90048
|
try {
|
|
89787
|
-
raw =
|
|
90049
|
+
raw = import_fs102.default.readFileSync(filePath, "utf-8");
|
|
89788
90050
|
} catch {
|
|
89789
90051
|
return { redactedLines: 0, patterns: [] };
|
|
89790
90052
|
}
|
|
@@ -89816,14 +90078,14 @@ function processFile(filePath, dryRun) {
|
|
|
89816
90078
|
}
|
|
89817
90079
|
}
|
|
89818
90080
|
if (!dryRun && redactedLines > 0) {
|
|
89819
|
-
|
|
90081
|
+
import_fs102.default.writeFileSync(filePath, newLines.join("\n"), "utf-8");
|
|
89820
90082
|
}
|
|
89821
90083
|
return { redactedLines, patterns };
|
|
89822
90084
|
}
|
|
89823
90085
|
function processJsonFile(filePath, dryRun) {
|
|
89824
90086
|
let raw;
|
|
89825
90087
|
try {
|
|
89826
|
-
raw =
|
|
90088
|
+
raw = import_fs102.default.readFileSync(filePath, "utf-8");
|
|
89827
90089
|
} catch {
|
|
89828
90090
|
return { redactedLines: 0, patterns: [] };
|
|
89829
90091
|
}
|
|
@@ -89836,15 +90098,15 @@ function processJsonFile(filePath, dryRun) {
|
|
|
89836
90098
|
const { value, modified, found } = redactJson(parsed);
|
|
89837
90099
|
if (!modified) return { redactedLines: 0, patterns: [] };
|
|
89838
90100
|
if (!dryRun) {
|
|
89839
|
-
|
|
90101
|
+
import_fs102.default.writeFileSync(filePath, JSON.stringify(value, null, 2), "utf-8");
|
|
89840
90102
|
}
|
|
89841
90103
|
return { redactedLines: 1, patterns: found };
|
|
89842
90104
|
}
|
|
89843
90105
|
function findJsonFiles(dir2) {
|
|
89844
90106
|
const results = [];
|
|
89845
|
-
if (!
|
|
89846
|
-
for (const entry of
|
|
89847
|
-
const full =
|
|
90107
|
+
if (!import_fs102.default.existsSync(dir2)) return results;
|
|
90108
|
+
for (const entry of import_fs102.default.readdirSync(dir2, { withFileTypes: true })) {
|
|
90109
|
+
const full = import_path101.default.join(dir2, entry.name);
|
|
89848
90110
|
if (entry.isDirectory()) results.push(...findJsonFiles(full));
|
|
89849
90111
|
else if (entry.isFile() && entry.name.endsWith(".json")) results.push(full);
|
|
89850
90112
|
}
|
|
@@ -89853,9 +90115,9 @@ function findJsonFiles(dir2) {
|
|
|
89853
90115
|
function registerMaskCommand(program2) {
|
|
89854
90116
|
program2.command("mask").description("Redact plaintext secrets from local AI session history files").option("--dry-run", "show what would be redacted without making changes").option("--all", "scan all history (default: last 30 days)").action(async (options) => {
|
|
89855
90117
|
const dryRun = !!options.dryRun;
|
|
89856
|
-
const home =
|
|
89857
|
-
const claudeDir =
|
|
89858
|
-
const geminiDir =
|
|
90118
|
+
const home = import_os82.default.homedir();
|
|
90119
|
+
const claudeDir = import_path101.default.join(home, ".claude", "projects");
|
|
90120
|
+
const geminiDir = import_path101.default.join(home, ".gemini", "tmp");
|
|
89859
90121
|
const allFiles = [
|
|
89860
90122
|
...findJsonlFiles(claudeDir).map((p) => ({ path: p, type: "jsonl" })),
|
|
89861
90123
|
...findJsonFiles(geminiDir).map((p) => ({ path: p, type: "json" }))
|
|
@@ -89863,7 +90125,7 @@ function registerMaskCommand(program2) {
|
|
|
89863
90125
|
const cutoff = options.all ? null : new Date(Date.now() - 30 * 24 * 60 * 60 * 1e3);
|
|
89864
90126
|
const filtered = cutoff ? allFiles.filter((f) => {
|
|
89865
90127
|
try {
|
|
89866
|
-
return
|
|
90128
|
+
return import_fs102.default.statSync(f.path).mtime >= cutoff;
|
|
89867
90129
|
} catch {
|
|
89868
90130
|
return false;
|
|
89869
90131
|
}
|
|
@@ -89920,7 +90182,7 @@ function registerMaskCommand(program2) {
|
|
|
89920
90182
|
init_blast();
|
|
89921
90183
|
init_safe_text();
|
|
89922
90184
|
var { version } = JSON.parse(
|
|
89923
|
-
|
|
90185
|
+
import_fs106.default.readFileSync(import_path105.default.join(__dirname, "../package.json"), "utf-8")
|
|
89924
90186
|
);
|
|
89925
90187
|
var program = new import_commander.Command();
|
|
89926
90188
|
program.name("node9").description("The Sudo Command for AI Agents").version(version);
|
|
@@ -90078,8 +90340,8 @@ function undoLeftoverNote() {
|
|
|
90078
90340
|
program.command("uninstall").description("Remove all Node9 hooks and optionally delete config files").option("--purge", "Also delete ~/.node9/ directory (config, audit log, credentials)").action(async (options) => {
|
|
90079
90341
|
console.log(import_chalk50.default.cyan("\n\u{1F6E1}\uFE0F Node9 Uninstall\n"));
|
|
90080
90342
|
try {
|
|
90081
|
-
const credRaw =
|
|
90082
|
-
|
|
90343
|
+
const credRaw = import_fs106.default.readFileSync(
|
|
90344
|
+
import_path105.default.join(import_os86.default.homedir(), ".node9", "credentials.json"),
|
|
90083
90345
|
"utf-8"
|
|
90084
90346
|
);
|
|
90085
90347
|
const prof = JSON.parse(credRaw)[process.env.NODE9_PROFILE || "default"];
|
|
@@ -90154,7 +90416,7 @@ program.command("uninstall").description("Remove all Node9 hooks and optionally
|
|
|
90154
90416
|
if (removed.length > 0 || refused.length > 0) {
|
|
90155
90417
|
console.log(import_chalk50.default.bold("\nRemoving decoy credentials..."));
|
|
90156
90418
|
for (const r of removed) {
|
|
90157
|
-
if (r.path) console.log(import_chalk50.default.green(` \u2705 ${r.path.replace(
|
|
90419
|
+
if (r.path) console.log(import_chalk50.default.green(` \u2705 ${r.path.replace(import_os86.default.homedir(), "~")}`));
|
|
90158
90420
|
}
|
|
90159
90421
|
for (const r of refused) {
|
|
90160
90422
|
decoysLeft.push(r.path ?? "(unknown path)");
|
|
@@ -90171,8 +90433,8 @@ program.command("uninstall").description("Remove all Node9 hooks and optionally
|
|
|
90171
90433
|
decoysLeft = ["(the decoy registry could not be read)"];
|
|
90172
90434
|
}
|
|
90173
90435
|
if (options.purge) {
|
|
90174
|
-
const node9Dir =
|
|
90175
|
-
if (
|
|
90436
|
+
const node9Dir = import_path105.default.join(import_os86.default.homedir(), ".node9");
|
|
90437
|
+
if (import_fs106.default.existsSync(node9Dir)) {
|
|
90176
90438
|
const alsoSnapshots = undoLeftoverPaths().length > 0 ? ", old undo snapshots" : "";
|
|
90177
90439
|
if (decoysLeft.length > 0) {
|
|
90178
90440
|
console.error(import_chalk50.default.red("\n \u26A0\uFE0F Decoy credential files are still on disk:"));
|
|
@@ -90188,8 +90450,8 @@ program.command("uninstall").description("Remove all Node9 hooks and optionally
|
|
|
90188
90450
|
default: false
|
|
90189
90451
|
});
|
|
90190
90452
|
if (confirmed) {
|
|
90191
|
-
|
|
90192
|
-
if (
|
|
90453
|
+
import_fs106.default.rmSync(node9Dir, { recursive: true });
|
|
90454
|
+
if (import_fs106.default.existsSync(node9Dir)) {
|
|
90193
90455
|
console.error(
|
|
90194
90456
|
import_chalk50.default.red("\n \u26A0\uFE0F ~/.node9/ could not be fully deleted \u2014 remove it manually.")
|
|
90195
90457
|
);
|
|
@@ -90345,7 +90607,7 @@ program.command("tail").description("Stream live agent activity to the terminal"
|
|
|
90345
90607
|
});
|
|
90346
90608
|
program.command("monitor").description("Live interactive dashboard \u2014 activity feed, approvals, security signals").action(async () => {
|
|
90347
90609
|
try {
|
|
90348
|
-
const dashboardPath =
|
|
90610
|
+
const dashboardPath = import_path105.default.join(__dirname, "dashboard.mjs");
|
|
90349
90611
|
const dynamicImport = new Function("id", "return import(id)");
|
|
90350
90612
|
const mod = await dynamicImport(`file://${dashboardPath}`);
|
|
90351
90613
|
await mod.startMonitor();
|
|
@@ -90383,14 +90645,14 @@ Claude Code spawns this command every ~300ms and writes a JSON payload to stdin.
|
|
|
90383
90645
|
Run "node9 addto claude" to register it as the statusLine.`
|
|
90384
90646
|
).argument("[subcommand]", 'Optional: "debug on" / "debug off" to toggle stdin logging').argument("[state]", 'on|off \u2014 used with "debug" subcommand').action(async (subcommand, state) => {
|
|
90385
90647
|
if (subcommand === "debug") {
|
|
90386
|
-
const flagFile =
|
|
90648
|
+
const flagFile = import_path105.default.join(import_os86.default.homedir(), ".node9", "hud-debug");
|
|
90387
90649
|
if (state === "on") {
|
|
90388
|
-
|
|
90389
|
-
|
|
90650
|
+
import_fs106.default.mkdirSync(import_path105.default.dirname(flagFile), { recursive: true });
|
|
90651
|
+
import_fs106.default.writeFileSync(flagFile, "");
|
|
90390
90652
|
console.log("HUD debug logging enabled \u2192 ~/.node9/hud-debug.log");
|
|
90391
90653
|
console.log("Tail it with: tail -f ~/.node9/hud-debug.log");
|
|
90392
90654
|
} else if (state === "off") {
|
|
90393
|
-
if (
|
|
90655
|
+
if (import_fs106.default.existsSync(flagFile)) import_fs106.default.unlinkSync(flagFile);
|
|
90394
90656
|
console.log("HUD debug logging disabled.");
|
|
90395
90657
|
} else {
|
|
90396
90658
|
console.error("Usage: node9 hud debug on|off");
|
|
@@ -90524,9 +90786,9 @@ if (process.argv[2] !== "daemon") {
|
|
|
90524
90786
|
const isCheckHook = process.argv[2] === "check";
|
|
90525
90787
|
if (isCheckHook) {
|
|
90526
90788
|
if (process.env.NODE9_DEBUG === "1" || getConfig().settings.enableHookLogDebug) {
|
|
90527
|
-
const logPath =
|
|
90789
|
+
const logPath = import_path105.default.join(import_os86.default.homedir(), ".node9", "hook-debug.log");
|
|
90528
90790
|
const msg = reason instanceof Error ? reason.message : String(reason);
|
|
90529
|
-
|
|
90791
|
+
import_fs106.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] UNHANDLED: ${msg}
|
|
90530
90792
|
`);
|
|
90531
90793
|
}
|
|
90532
90794
|
process.exit(0);
|