@node9/proxy 2.47.2 → 2.48.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli-main.js +959 -660
- package/dist/dashboard.mjs +1 -0
- package/dist/hook.js +407 -118
- package/dist/index.js +1 -0
- package/dist/index.mjs +1 -0
- 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 -90554
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)) {
|
|
@@ -26723,6 +26723,70 @@ var init_loop_detector = __esm({
|
|
|
26723
26723
|
});
|
|
26724
26724
|
|
|
26725
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
|
+
}
|
|
26726
26790
|
function buildNegotiationMessage(blockedByLabel, isHumanDecision2, humanReason, recoveryCommand, context) {
|
|
26727
26791
|
if (isHumanDecision2 && context?.redirect && humanReason) {
|
|
26728
26792
|
return `NODE9: The user stopped this action and gave you an instruction.
|
|
@@ -26732,88 +26796,138 @@ INSTRUCTIONS:
|
|
|
26732
26796
|
- Retry the original action only if the instruction says you may.`;
|
|
26733
26797
|
}
|
|
26734
26798
|
if (isHumanDecision2) {
|
|
26735
|
-
return
|
|
26799
|
+
return withUserLine(
|
|
26800
|
+
"Node9: you blocked this action",
|
|
26801
|
+
`NODE9: The human user rejected this action.
|
|
26736
26802
|
REASON: ${humanReason || "No specific reason provided."}
|
|
26737
26803
|
INSTRUCTIONS:
|
|
26738
26804
|
- Do NOT retry this exact command.
|
|
26739
26805
|
- Acknowledge the block to the user and ask if there is an alternative approach.
|
|
26740
|
-
- 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
|
+
);
|
|
26741
26808
|
}
|
|
26742
26809
|
if (context?.kind === "protected-path") {
|
|
26743
26810
|
const subject = context.path ? `${context.path} is a protected file` : "This file is protected";
|
|
26744
|
-
|
|
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.
|
|
26745
26816
|
INSTRUCTIONS:
|
|
26746
26817
|
- Do NOT retry, and do NOT reach the file another way (cat, grep, a copy, a script, a redirect).
|
|
26747
26818
|
- If this step needs that file, ask the user to provide what you need or to do the step themselves.
|
|
26748
|
-
- 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
|
+
);
|
|
26749
26821
|
}
|
|
26750
26822
|
const label3 = blockedByLabel.toLowerCase();
|
|
26751
26823
|
if (label3.includes("dlp") || label3.includes("secret detected") || label3.includes("credential review")) {
|
|
26752
|
-
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.
|
|
26753
26827
|
CRITICAL INSTRUCTION: Do NOT retry this action.
|
|
26754
26828
|
REQUIRED ACTIONS:
|
|
26755
26829
|
1. Remove the hardcoded credential from your command or code.
|
|
26756
26830
|
2. Use an environment variable or a dedicated secrets manager instead.
|
|
26757
26831
|
3. Treat the leaked credential as compromised and rotate it immediately.
|
|
26758
26832
|
Do NOT attempt to bypass this check or pass the credential through another tool.
|
|
26759
|
-
- 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
|
+
);
|
|
26760
26835
|
}
|
|
26761
26836
|
if (label3.includes("package check")) {
|
|
26762
|
-
|
|
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."}
|
|
26763
26841
|
INSTRUCTIONS:
|
|
26764
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).
|
|
26765
26843
|
- If a dependency is needed, suggest a well-known alternative and let the user choose.
|
|
26766
|
-
- 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
|
+
);
|
|
26767
26846
|
}
|
|
26768
26847
|
if (label3.includes("sql safety") && label3.includes("delete without where")) {
|
|
26769
|
-
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.
|
|
26770
26851
|
INSTRUCTION: Add a WHERE clause to scope the deletion (e.g. WHERE id = <value>).
|
|
26771
26852
|
Do NOT retry without a WHERE clause.
|
|
26772
|
-
- 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
|
+
);
|
|
26773
26855
|
}
|
|
26774
26856
|
if (label3.includes("sql safety") && label3.includes("update without where")) {
|
|
26775
|
-
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.
|
|
26776
26860
|
INSTRUCTION: Add a WHERE clause to scope the update (e.g. WHERE id = <value>).
|
|
26777
26861
|
Do NOT retry without a WHERE clause.
|
|
26778
|
-
- 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
|
+
);
|
|
26779
26864
|
}
|
|
26780
26865
|
if (label3.includes("dangerous word")) {
|
|
26781
26866
|
const match = blockedByLabel.match(/dangerous word: "([^"]+)"/i);
|
|
26782
26867
|
const word = match?.[1] ?? "a dangerous keyword";
|
|
26783
|
-
return
|
|
26868
|
+
return withUserLine(
|
|
26869
|
+
blockedLine(context, `the command contains ${userLineValue(word)}`),
|
|
26870
|
+
`NODE9: Blocked \u2014 command contains forbidden keyword "${word}".
|
|
26784
26871
|
INSTRUCTION: Do NOT use "${word}". Use a non-destructive alternative.
|
|
26785
26872
|
Do NOT attempt to bypass this with shell tricks or aliases \u2014 it will be blocked again.
|
|
26786
|
-
- 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
|
+
);
|
|
26787
26875
|
}
|
|
26788
26876
|
if (label3.includes("path blocked") || label3.includes("sandbox")) {
|
|
26789
|
-
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.
|
|
26790
26880
|
INSTRUCTION: Move your output to an allowed directory such as /tmp/ or the project directory.
|
|
26791
26881
|
Do NOT retry on the same path.
|
|
26792
|
-
- 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
|
+
);
|
|
26793
26884
|
}
|
|
26794
26885
|
if (label3.includes("inline execution")) {
|
|
26795
|
-
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.
|
|
26796
26889
|
INSTRUCTION: Use individual tool calls instead of embedding code in a shell string.
|
|
26797
|
-
- 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
|
+
);
|
|
26798
26892
|
}
|
|
26799
26893
|
if (label3.includes("strict mode")) {
|
|
26800
|
-
return
|
|
26801
|
-
|
|
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
|
+
);
|
|
26802
26899
|
}
|
|
26803
26900
|
if (label3.includes("rule") && label3.includes("default block")) {
|
|
26804
26901
|
const match = blockedByLabel.match(/rule "([^"]+)"/i);
|
|
26805
|
-
const
|
|
26806
|
-
return
|
|
26807
|
-
|
|
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.
|
|
26808
26907
|
Do NOT attempt to bypass this rule.
|
|
26809
|
-
- 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))})`;
|
|
26810
26921
|
}
|
|
26811
26922
|
const recovery = recoveryCommand ? `
|
|
26812
26923
|
REQUIRED ACTION: Run \`${recoveryCommand}\` first, then retry your original command.` : "\n- Pivot to a non-destructive or read-only alternative.";
|
|
26813
|
-
return
|
|
26924
|
+
return withUserLine(
|
|
26925
|
+
line,
|
|
26926
|
+
`NODE9: Action blocked by security policy [${agentFacingLabel(blockedByLabel)}].
|
|
26814
26927
|
INSTRUCTIONS:
|
|
26815
26928
|
- Do NOT retry this exact command or attempt to bypass the rule.${recovery}
|
|
26816
|
-
- 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
|
+
);
|
|
26817
26931
|
}
|
|
26818
26932
|
function buildReviewMessage(blockedByLabel, ruleDescription, reason) {
|
|
26819
26933
|
const why = ruleDescription || (reason && reason !== blockedByLabel ? reason : void 0) || blockedByLabel || "this action needs your review";
|
|
@@ -26828,7 +26942,7 @@ function isHumanDecision(label3, blockedBy, decidedBy) {
|
|
|
26828
26942
|
return l.includes("user") || l.includes("daemon") || l.includes("decision");
|
|
26829
26943
|
}
|
|
26830
26944
|
function agentFacingLabel(label3) {
|
|
26831
|
-
const plain = label3.replace(
|
|
26945
|
+
const plain = label3.replace(PICTOGRAPHS, "").replace(/\bNode9\b/g, "node9").replace(/\s+/g, " ").trim();
|
|
26832
26946
|
return plain || "Security Policy";
|
|
26833
26947
|
}
|
|
26834
26948
|
function asApprovalRequest(description) {
|
|
@@ -26844,11 +26958,20 @@ function asApprovalRequest(description) {
|
|
|
26844
26958
|
}
|
|
26845
26959
|
return description;
|
|
26846
26960
|
}
|
|
26847
|
-
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;
|
|
26848
26962
|
var init_negotiation = __esm({
|
|
26849
26963
|
"src/policy/negotiation.ts"() {
|
|
26850
26964
|
"use strict";
|
|
26851
26965
|
init_cjs_shims();
|
|
26966
|
+
init_dist();
|
|
26967
|
+
USER_LINE_ICON = "\u{1F6E1}\uFE0F";
|
|
26968
|
+
QUOTE_INSTRUCTION = "Start your reply about this blocked action with the line above, exactly as written, on its own line. Leave it out of later replies.";
|
|
26969
|
+
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;
|
|
26852
26975
|
BLOCKED_BY = " is blocked by ";
|
|
26853
26976
|
DASH_BLOCKED_BY = " \u2014 blocked by ";
|
|
26854
26977
|
SHIELD = " shield";
|
|
@@ -45916,21 +46039,21 @@ function patchConfig(configPath2, patch) {
|
|
|
45916
46039
|
throw err2;
|
|
45917
46040
|
}
|
|
45918
46041
|
}
|
|
45919
|
-
var
|
|
46042
|
+
var import_path86, import_os72, GLOBAL_CONFIG_PATH;
|
|
45920
46043
|
var init_patch = __esm({
|
|
45921
46044
|
"src/config/patch.ts"() {
|
|
45922
46045
|
"use strict";
|
|
45923
46046
|
init_cjs_shims();
|
|
45924
|
-
|
|
45925
|
-
|
|
46047
|
+
import_path86 = __toESM(require("path"));
|
|
46048
|
+
import_os72 = __toESM(require("os"));
|
|
45926
46049
|
init_write();
|
|
45927
|
-
GLOBAL_CONFIG_PATH =
|
|
46050
|
+
GLOBAL_CONFIG_PATH = import_path86.default.join(import_os72.default.homedir(), ".node9", "config.json");
|
|
45928
46051
|
}
|
|
45929
46052
|
});
|
|
45930
46053
|
|
|
45931
46054
|
// src/auth/egress-config.ts
|
|
45932
46055
|
function egressConfigPath() {
|
|
45933
|
-
return
|
|
46056
|
+
return import_path87.default.join(import_os73.default.homedir(), ".node9", "config.json");
|
|
45934
46057
|
}
|
|
45935
46058
|
function readEgressRawConfig() {
|
|
45936
46059
|
return readConfigFileLegacy(egressConfigPath());
|
|
@@ -45990,14 +46113,14 @@ function normalizeEgressHost(host2) {
|
|
|
45990
46113
|
function isValidEgressHost(host2) {
|
|
45991
46114
|
return EGRESS_HOST_RE.test(host2);
|
|
45992
46115
|
}
|
|
45993
|
-
var
|
|
46116
|
+
var import_os73, import_path87, DEFAULT_EGRESS, EGRESS_HOST_RE;
|
|
45994
46117
|
var init_egress_config = __esm({
|
|
45995
46118
|
"src/auth/egress-config.ts"() {
|
|
45996
46119
|
"use strict";
|
|
45997
46120
|
init_cjs_shims();
|
|
45998
46121
|
init_write();
|
|
45999
|
-
|
|
46000
|
-
|
|
46122
|
+
import_os73 = __toESM(require("os"));
|
|
46123
|
+
import_path87 = __toESM(require("path"));
|
|
46001
46124
|
init_dist();
|
|
46002
46125
|
DEFAULT_EGRESS = {
|
|
46003
46126
|
enabled: false,
|
|
@@ -46025,27 +46148,27 @@ __export(local_setup_exports, {
|
|
|
46025
46148
|
runLocalSetup: () => runLocalSetup
|
|
46026
46149
|
});
|
|
46027
46150
|
function configPath() {
|
|
46028
|
-
return
|
|
46151
|
+
return import_path88.default.join(import_os74.default.homedir(), ".node9", "config.json");
|
|
46029
46152
|
}
|
|
46030
46153
|
function combined(values) {
|
|
46031
46154
|
return values.every(Boolean) ? "on" : values.some(Boolean) ? "partial" : "off";
|
|
46032
46155
|
}
|
|
46033
46156
|
function readLocalState(opts = {}) {
|
|
46034
46157
|
const file2 = configPath();
|
|
46035
|
-
if (
|
|
46158
|
+
if (import_fs88.default.existsSync(file2) && !opts.replaceConfig) {
|
|
46036
46159
|
let raw;
|
|
46037
46160
|
try {
|
|
46038
|
-
raw = JSON.parse(
|
|
46161
|
+
raw = JSON.parse(import_fs88.default.readFileSync(file2, "utf8"));
|
|
46039
46162
|
} catch {
|
|
46040
46163
|
raw = void 0;
|
|
46041
46164
|
}
|
|
46042
46165
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) throw invalidConfig();
|
|
46043
46166
|
}
|
|
46044
|
-
const config = getConfig(
|
|
46167
|
+
const config = getConfig(import_path88.default.join(import_os74.default.homedir(), ".node9"));
|
|
46045
46168
|
const active = readActiveShields();
|
|
46046
46169
|
const installed = isDaemonServiceInstalled();
|
|
46047
46170
|
return {
|
|
46048
|
-
fresh: !
|
|
46171
|
+
fresh: !import_fs88.default.existsSync(file2),
|
|
46049
46172
|
managed: config.policySource === "workspace",
|
|
46050
46173
|
shields: combined(DEFAULT_SHIELDS.map((s) => active.includes(s))),
|
|
46051
46174
|
dlp: combined([config.policy.dlp.enabled, config.policy.dlp.pii !== "off"]),
|
|
@@ -46093,7 +46216,7 @@ function diffChoices(state, selected, partial = {}) {
|
|
|
46093
46216
|
}
|
|
46094
46217
|
function setAutostart(enabled) {
|
|
46095
46218
|
const file2 = configPath();
|
|
46096
|
-
const raw = JSON.parse(
|
|
46219
|
+
const raw = JSON.parse(import_fs88.default.readFileSync(file2, "utf8"));
|
|
46097
46220
|
if (raw.settings?.autoStartDaemon === enabled) return;
|
|
46098
46221
|
raw.settings = { ...raw.settings, autoStartDaemon: enabled };
|
|
46099
46222
|
atomicWriteSync(file2, JSON.stringify(raw, null, 2) + "\n", { mode: 384 });
|
|
@@ -46260,14 +46383,14 @@ async function runLocalSetup(opts) {
|
|
|
46260
46383
|
if (interactive && !state.managed && !opts.skipSetup) await askTelemetry(agents, firstInstall);
|
|
46261
46384
|
return collectSummary(applied);
|
|
46262
46385
|
}
|
|
46263
|
-
var
|
|
46386
|
+
var import_fs88, import_os74, import_path88, DEFAULT_SHIELDS;
|
|
46264
46387
|
var init_local_setup = __esm({
|
|
46265
46388
|
"src/cli/local-setup.ts"() {
|
|
46266
46389
|
"use strict";
|
|
46267
46390
|
init_cjs_shims();
|
|
46268
|
-
|
|
46269
|
-
|
|
46270
|
-
|
|
46391
|
+
import_fs88 = __toESM(require("fs"));
|
|
46392
|
+
import_os74 = __toESM(require("os"));
|
|
46393
|
+
import_path88 = __toESM(require("path"));
|
|
46271
46394
|
init_config();
|
|
46272
46395
|
init_patch();
|
|
46273
46396
|
init_keyed_guard();
|
|
@@ -46330,8 +46453,8 @@ async function askTelemetry(agents, firstInstall) {
|
|
|
46330
46453
|
}
|
|
46331
46454
|
}
|
|
46332
46455
|
function ensureConfig(mode, force = false) {
|
|
46333
|
-
const file2 =
|
|
46334
|
-
const firstInstall = !
|
|
46456
|
+
const file2 = import_path89.default.join(import_os75.default.homedir(), ".node9", "config.json");
|
|
46457
|
+
const firstInstall = !import_fs89.default.existsSync(file2);
|
|
46335
46458
|
if (firstInstall || force) {
|
|
46336
46459
|
const body = legacyToV2(
|
|
46337
46460
|
mode !== void 0 && mode !== DEFAULT_CONFIG.settings.mode ? { settings: { mode } } : {}
|
|
@@ -46383,16 +46506,16 @@ function registerInitCommand(program2) {
|
|
|
46383
46506
|
}
|
|
46384
46507
|
);
|
|
46385
46508
|
}
|
|
46386
|
-
var
|
|
46509
|
+
var import_fs89, import_path89, import_os75, import_https6, TELEMETRY_PROMPT;
|
|
46387
46510
|
var init_init = __esm({
|
|
46388
46511
|
"src/cli/commands/init.ts"() {
|
|
46389
46512
|
"use strict";
|
|
46390
46513
|
init_cjs_shims();
|
|
46391
46514
|
init_v2();
|
|
46392
46515
|
init_write();
|
|
46393
|
-
|
|
46394
|
-
|
|
46395
|
-
|
|
46516
|
+
import_fs89 = __toESM(require("fs"));
|
|
46517
|
+
import_path89 = __toESM(require("path"));
|
|
46518
|
+
import_os75 = __toESM(require("os"));
|
|
46396
46519
|
import_https6 = __toESM(require("https"));
|
|
46397
46520
|
init_config();
|
|
46398
46521
|
init_setup();
|
|
@@ -47519,14 +47642,14 @@ var require_util = __commonJS({
|
|
|
47519
47642
|
}
|
|
47520
47643
|
const port = url.port != null ? url.port : url.protocol === "https:" ? 443 : 80;
|
|
47521
47644
|
let origin = url.origin != null ? url.origin : `${url.protocol || ""}//${url.hostname || ""}:${port}`;
|
|
47522
|
-
let
|
|
47645
|
+
let path110 = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`;
|
|
47523
47646
|
if (origin[origin.length - 1] === "/") {
|
|
47524
47647
|
origin = origin.slice(0, origin.length - 1);
|
|
47525
47648
|
}
|
|
47526
|
-
if (
|
|
47527
|
-
|
|
47649
|
+
if (path110 && path110[0] !== "/") {
|
|
47650
|
+
path110 = `/${path110}`;
|
|
47528
47651
|
}
|
|
47529
|
-
return new URL(`${origin}${
|
|
47652
|
+
return new URL(`${origin}${path110}`);
|
|
47530
47653
|
}
|
|
47531
47654
|
if (!isHttpOrHttpsPrefixed(url.origin || url.protocol)) {
|
|
47532
47655
|
throw new InvalidArgumentError("Invalid URL protocol: the URL must start with `http:` or `https:`.");
|
|
@@ -48349,9 +48472,9 @@ var require_diagnostics = __commonJS({
|
|
|
48349
48472
|
"undici:client:sendHeaders",
|
|
48350
48473
|
(evt) => {
|
|
48351
48474
|
const {
|
|
48352
|
-
request: { method, path:
|
|
48475
|
+
request: { method, path: path110, origin }
|
|
48353
48476
|
} = evt;
|
|
48354
|
-
debugLog2("sending request to %s %s%s", method, origin,
|
|
48477
|
+
debugLog2("sending request to %s %s%s", method, origin, path110);
|
|
48355
48478
|
}
|
|
48356
48479
|
);
|
|
48357
48480
|
}
|
|
@@ -48369,14 +48492,14 @@ var require_diagnostics = __commonJS({
|
|
|
48369
48492
|
"undici:request:headers",
|
|
48370
48493
|
(evt) => {
|
|
48371
48494
|
const {
|
|
48372
|
-
request: { method, path:
|
|
48495
|
+
request: { method, path: path110, origin },
|
|
48373
48496
|
response: { statusCode }
|
|
48374
48497
|
} = evt;
|
|
48375
48498
|
debugLog2(
|
|
48376
48499
|
"received response to %s %s%s - HTTP %d",
|
|
48377
48500
|
method,
|
|
48378
48501
|
origin,
|
|
48379
|
-
|
|
48502
|
+
path110,
|
|
48380
48503
|
statusCode
|
|
48381
48504
|
);
|
|
48382
48505
|
}
|
|
@@ -48385,23 +48508,23 @@ var require_diagnostics = __commonJS({
|
|
|
48385
48508
|
"undici:request:trailers",
|
|
48386
48509
|
(evt) => {
|
|
48387
48510
|
const {
|
|
48388
|
-
request: { method, path:
|
|
48511
|
+
request: { method, path: path110, origin }
|
|
48389
48512
|
} = evt;
|
|
48390
|
-
debugLog2("trailers received from %s %s%s", method, origin,
|
|
48513
|
+
debugLog2("trailers received from %s %s%s", method, origin, path110);
|
|
48391
48514
|
}
|
|
48392
48515
|
);
|
|
48393
48516
|
diagnosticsChannel.subscribe(
|
|
48394
48517
|
"undici:request:error",
|
|
48395
48518
|
(evt) => {
|
|
48396
48519
|
const {
|
|
48397
|
-
request: { method, path:
|
|
48520
|
+
request: { method, path: path110, origin },
|
|
48398
48521
|
error
|
|
48399
48522
|
} = evt;
|
|
48400
48523
|
debugLog2(
|
|
48401
48524
|
"request to %s %s%s errored - %s",
|
|
48402
48525
|
method,
|
|
48403
48526
|
origin,
|
|
48404
|
-
|
|
48527
|
+
path110,
|
|
48405
48528
|
error.message
|
|
48406
48529
|
);
|
|
48407
48530
|
}
|
|
@@ -48517,7 +48640,7 @@ var require_request = __commonJS({
|
|
|
48517
48640
|
var kHandler = /* @__PURE__ */ Symbol("handler");
|
|
48518
48641
|
var Request = class {
|
|
48519
48642
|
constructor(origin, {
|
|
48520
|
-
path:
|
|
48643
|
+
path: path110,
|
|
48521
48644
|
method,
|
|
48522
48645
|
body,
|
|
48523
48646
|
headers,
|
|
@@ -48534,11 +48657,11 @@ var require_request = __commonJS({
|
|
|
48534
48657
|
maxRedirections,
|
|
48535
48658
|
typeOfService
|
|
48536
48659
|
}, handler) {
|
|
48537
|
-
if (typeof
|
|
48660
|
+
if (typeof path110 !== "string") {
|
|
48538
48661
|
throw new InvalidArgumentError("path must be a string");
|
|
48539
|
-
} else if (
|
|
48662
|
+
} else if (path110[0] !== "/" && !(path110.startsWith("http://") || path110.startsWith("https://")) && method !== "CONNECT") {
|
|
48540
48663
|
throw new InvalidArgumentError("path must be an absolute URL or start with a slash");
|
|
48541
|
-
} else if (invalidPathRegex.test(
|
|
48664
|
+
} else if (invalidPathRegex.test(path110)) {
|
|
48542
48665
|
throw new InvalidArgumentError("invalid request path");
|
|
48543
48666
|
}
|
|
48544
48667
|
if (typeof method !== "string") {
|
|
@@ -48613,7 +48736,7 @@ var require_request = __commonJS({
|
|
|
48613
48736
|
this.completed = false;
|
|
48614
48737
|
this.aborted = false;
|
|
48615
48738
|
this.upgrade = upgrade || null;
|
|
48616
|
-
this.path = query ? serializePathWithQuery(
|
|
48739
|
+
this.path = query ? serializePathWithQuery(path110, query) : path110;
|
|
48617
48740
|
this.origin = origin;
|
|
48618
48741
|
this.protocol = getProtocolFromUrlString(origin);
|
|
48619
48742
|
this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent;
|
|
@@ -53860,7 +53983,7 @@ var require_client_h1 = __commonJS({
|
|
|
53860
53983
|
return method !== "GET" && method !== "HEAD" && method !== "OPTIONS" && method !== "TRACE" && method !== "CONNECT";
|
|
53861
53984
|
}
|
|
53862
53985
|
function writeH1(client, request2) {
|
|
53863
|
-
const { method, path:
|
|
53986
|
+
const { method, path: path110, host: host2, upgrade, blocking, reset } = request2;
|
|
53864
53987
|
let { body, headers, contentLength } = request2;
|
|
53865
53988
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH" || method === "QUERY" || method === "PROPFIND" || method === "PROPPATCH";
|
|
53866
53989
|
if (util.isFormDataLike(body)) {
|
|
@@ -53938,7 +54061,7 @@ var require_client_h1 = __commonJS({
|
|
|
53938
54061
|
if (socket.setTypeOfService) {
|
|
53939
54062
|
socket.setTypeOfService(request2.typeOfService);
|
|
53940
54063
|
}
|
|
53941
|
-
let header = `${method} ${
|
|
54064
|
+
let header = `${method} ${path110} HTTP/1.1\r
|
|
53942
54065
|
`;
|
|
53943
54066
|
if (typeof host2 === "string") {
|
|
53944
54067
|
header += `host: ${host2}\r
|
|
@@ -54616,7 +54739,7 @@ var require_client_h2 = __commonJS({
|
|
|
54616
54739
|
const headersTimeout = request2.headersTimeout ?? client[kHeadersTimeout];
|
|
54617
54740
|
const bodyTimeout = request2.bodyTimeout ?? client[kBodyTimeout];
|
|
54618
54741
|
const session = client[kHTTP2Session];
|
|
54619
|
-
const { method, path:
|
|
54742
|
+
const { method, path: path110, host: host2, upgrade, expectContinue, signal, protocol, headers: reqHeaders } = request2;
|
|
54620
54743
|
let { body } = request2;
|
|
54621
54744
|
if (upgrade != null && upgrade !== "websocket") {
|
|
54622
54745
|
util.errorRequest(client, request2, new InvalidArgumentError(`Custom upgrade "${upgrade}" not supported over HTTP/2`));
|
|
@@ -54685,7 +54808,7 @@ var require_client_h2 = __commonJS({
|
|
|
54685
54808
|
}
|
|
54686
54809
|
headers[HTTP2_HEADER_METHOD] = "CONNECT";
|
|
54687
54810
|
headers[HTTP2_HEADER_PROTOCOL] = "websocket";
|
|
54688
|
-
headers[HTTP2_HEADER_PATH] =
|
|
54811
|
+
headers[HTTP2_HEADER_PATH] = path110;
|
|
54689
54812
|
if (protocol === "ws:" || protocol === "wss:") {
|
|
54690
54813
|
headers[HTTP2_HEADER_SCHEME] = protocol === "ws:" ? "http" : "https";
|
|
54691
54814
|
} else {
|
|
@@ -54737,7 +54860,7 @@ var require_client_h2 = __commonJS({
|
|
|
54737
54860
|
stream.setTimeout(headersTimeout);
|
|
54738
54861
|
return true;
|
|
54739
54862
|
}
|
|
54740
|
-
headers[HTTP2_HEADER_PATH] =
|
|
54863
|
+
headers[HTTP2_HEADER_PATH] = path110;
|
|
54741
54864
|
headers[HTTP2_HEADER_SCHEME] = protocol === "http:" ? "http" : "https";
|
|
54742
54865
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
|
|
54743
54866
|
if (body && typeof body.read === "function") {
|
|
@@ -57104,10 +57227,10 @@ var require_proxy_agent = __commonJS({
|
|
|
57104
57227
|
};
|
|
57105
57228
|
const {
|
|
57106
57229
|
origin,
|
|
57107
|
-
path:
|
|
57230
|
+
path: path110 = "/",
|
|
57108
57231
|
headers = {}
|
|
57109
57232
|
} = opts;
|
|
57110
|
-
opts.path = origin +
|
|
57233
|
+
opts.path = origin + path110;
|
|
57111
57234
|
if (!("host" in headers) && !("Host" in headers)) {
|
|
57112
57235
|
const { host: host2 } = new URL(origin);
|
|
57113
57236
|
headers.host = host2;
|
|
@@ -59282,20 +59405,20 @@ var require_mock_utils = __commonJS({
|
|
|
59282
59405
|
}
|
|
59283
59406
|
return normalizedQp;
|
|
59284
59407
|
}
|
|
59285
|
-
function safeUrl(
|
|
59286
|
-
if (typeof
|
|
59287
|
-
return
|
|
59408
|
+
function safeUrl(path110) {
|
|
59409
|
+
if (typeof path110 !== "string") {
|
|
59410
|
+
return path110;
|
|
59288
59411
|
}
|
|
59289
|
-
const pathSegments =
|
|
59412
|
+
const pathSegments = path110.split("?", 3);
|
|
59290
59413
|
if (pathSegments.length !== 2) {
|
|
59291
|
-
return
|
|
59414
|
+
return path110;
|
|
59292
59415
|
}
|
|
59293
59416
|
const qp = new URLSearchParams(pathSegments.pop());
|
|
59294
59417
|
qp.sort();
|
|
59295
59418
|
return [...pathSegments, qp.toString()].join("?");
|
|
59296
59419
|
}
|
|
59297
|
-
function matchKey(mockDispatch2, { path:
|
|
59298
|
-
const pathMatch = matchValue(mockDispatch2.path,
|
|
59420
|
+
function matchKey(mockDispatch2, { path: path110, method, body, headers }) {
|
|
59421
|
+
const pathMatch = matchValue(mockDispatch2.path, path110);
|
|
59299
59422
|
const methodMatch = matchValue(mockDispatch2.method, method);
|
|
59300
59423
|
const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body) : true;
|
|
59301
59424
|
const headersMatch = matchHeaders(mockDispatch2, headers);
|
|
@@ -59320,8 +59443,8 @@ var require_mock_utils = __commonJS({
|
|
|
59320
59443
|
const basePath = key.query ? serializePathWithQuery(key.path, key.query) : key.path;
|
|
59321
59444
|
const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath;
|
|
59322
59445
|
const resolvedPathWithoutTrailingSlash = removeTrailingSlash(resolvedPath);
|
|
59323
|
-
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path:
|
|
59324
|
-
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);
|
|
59325
59448
|
});
|
|
59326
59449
|
if (matchedMockDispatches.length === 0) {
|
|
59327
59450
|
throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`);
|
|
@@ -59360,19 +59483,19 @@ var require_mock_utils = __commonJS({
|
|
|
59360
59483
|
mockDispatches.splice(index, 1);
|
|
59361
59484
|
}
|
|
59362
59485
|
}
|
|
59363
|
-
function removeTrailingSlash(
|
|
59364
|
-
while (
|
|
59365
|
-
|
|
59486
|
+
function removeTrailingSlash(path110) {
|
|
59487
|
+
while (path110.endsWith("/")) {
|
|
59488
|
+
path110 = path110.slice(0, -1);
|
|
59366
59489
|
}
|
|
59367
|
-
if (
|
|
59368
|
-
|
|
59490
|
+
if (path110.length === 0) {
|
|
59491
|
+
path110 = "/";
|
|
59369
59492
|
}
|
|
59370
|
-
return
|
|
59493
|
+
return path110;
|
|
59371
59494
|
}
|
|
59372
59495
|
function buildKey(opts) {
|
|
59373
|
-
const { path:
|
|
59496
|
+
const { path: path110, method, body, headers, query } = opts;
|
|
59374
59497
|
return {
|
|
59375
|
-
path:
|
|
59498
|
+
path: path110,
|
|
59376
59499
|
method,
|
|
59377
59500
|
body,
|
|
59378
59501
|
headers,
|
|
@@ -60067,10 +60190,10 @@ var require_pending_interceptors_formatter = __commonJS({
|
|
|
60067
60190
|
}
|
|
60068
60191
|
format(pendingInterceptors) {
|
|
60069
60192
|
const withPrettyHeaders = pendingInterceptors.map(
|
|
60070
|
-
({ method, path:
|
|
60193
|
+
({ method, path: path110, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
|
|
60071
60194
|
Method: method,
|
|
60072
60195
|
Origin: origin,
|
|
60073
|
-
Path:
|
|
60196
|
+
Path: path110,
|
|
60074
60197
|
"Status code": statusCode,
|
|
60075
60198
|
Persistent: persist ? PERSISTENT : NOT_PERSISTENT,
|
|
60076
60199
|
Invocations: timesInvoked,
|
|
@@ -60153,9 +60276,9 @@ var require_mock_agent = __commonJS({
|
|
|
60153
60276
|
const acceptNonStandardSearchParameters = this[kMockAgentAcceptsNonStandardSearchParameters];
|
|
60154
60277
|
const dispatchOpts = { ...opts };
|
|
60155
60278
|
if (acceptNonStandardSearchParameters && dispatchOpts.path) {
|
|
60156
|
-
const [
|
|
60279
|
+
const [path110, searchParams] = dispatchOpts.path.split("?");
|
|
60157
60280
|
const normalizedSearchParams = normalizeSearchParams(searchParams, acceptNonStandardSearchParameters);
|
|
60158
|
-
dispatchOpts.path = `${
|
|
60281
|
+
dispatchOpts.path = `${path110}?${normalizedSearchParams}`;
|
|
60159
60282
|
}
|
|
60160
60283
|
return this[kAgent].dispatch(dispatchOpts, handler);
|
|
60161
60284
|
}
|
|
@@ -60558,12 +60681,12 @@ var require_snapshot_recorder = __commonJS({
|
|
|
60558
60681
|
* @return {Promise<void>} - Resolves when snapshots are loaded
|
|
60559
60682
|
*/
|
|
60560
60683
|
async loadSnapshots(filePath) {
|
|
60561
|
-
const
|
|
60562
|
-
if (!
|
|
60684
|
+
const path110 = filePath || this.#snapshotPath;
|
|
60685
|
+
if (!path110) {
|
|
60563
60686
|
throw new InvalidArgumentError("Snapshot path is required");
|
|
60564
60687
|
}
|
|
60565
60688
|
try {
|
|
60566
|
-
const data = await readFile(resolve2(
|
|
60689
|
+
const data = await readFile(resolve2(path110), "utf8");
|
|
60567
60690
|
const parsed = JSON.parse(data);
|
|
60568
60691
|
if (Array.isArray(parsed)) {
|
|
60569
60692
|
this.#snapshots.clear();
|
|
@@ -60577,7 +60700,7 @@ var require_snapshot_recorder = __commonJS({
|
|
|
60577
60700
|
if (error.code === "ENOENT") {
|
|
60578
60701
|
this.#snapshots.clear();
|
|
60579
60702
|
} else {
|
|
60580
|
-
throw new UndiciError(`Failed to load snapshots from ${
|
|
60703
|
+
throw new UndiciError(`Failed to load snapshots from ${path110}`, { cause: error });
|
|
60581
60704
|
}
|
|
60582
60705
|
}
|
|
60583
60706
|
}
|
|
@@ -60588,11 +60711,11 @@ var require_snapshot_recorder = __commonJS({
|
|
|
60588
60711
|
* @returns {Promise<void>} - Resolves when snapshots are saved
|
|
60589
60712
|
*/
|
|
60590
60713
|
async saveSnapshots(filePath) {
|
|
60591
|
-
const
|
|
60592
|
-
if (!
|
|
60714
|
+
const path110 = filePath || this.#snapshotPath;
|
|
60715
|
+
if (!path110) {
|
|
60593
60716
|
throw new InvalidArgumentError("Snapshot path is required");
|
|
60594
60717
|
}
|
|
60595
|
-
const resolvedPath = resolve2(
|
|
60718
|
+
const resolvedPath = resolve2(path110);
|
|
60596
60719
|
await mkdir(dirname3(resolvedPath), { recursive: true });
|
|
60597
60720
|
const data = Array.from(this.#snapshots.entries()).map(([hash2, snapshot]) => ({
|
|
60598
60721
|
hash: hash2,
|
|
@@ -61233,15 +61356,15 @@ var require_redirect_handler = __commonJS({
|
|
|
61233
61356
|
}
|
|
61234
61357
|
this.history[kRedirectCacheControl].push(headers["cache-control"]);
|
|
61235
61358
|
const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin)));
|
|
61236
|
-
const
|
|
61237
|
-
const redirectUrlString = `${origin}${
|
|
61359
|
+
const path110 = search ? `${pathname}${search}` : pathname;
|
|
61360
|
+
const redirectUrlString = `${origin}${path110}`;
|
|
61238
61361
|
for (const historyUrl of this.history) {
|
|
61239
61362
|
if (historyUrl.toString() === redirectUrlString) {
|
|
61240
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.`);
|
|
61241
61364
|
}
|
|
61242
61365
|
}
|
|
61243
61366
|
this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin);
|
|
61244
|
-
this.opts.path =
|
|
61367
|
+
this.opts.path = path110;
|
|
61245
61368
|
this.opts.origin = origin;
|
|
61246
61369
|
this.opts.query = null;
|
|
61247
61370
|
}
|
|
@@ -63017,10 +63140,10 @@ var require_cache_handler = __commonJS({
|
|
|
63017
63140
|
}
|
|
63018
63141
|
return locationUrl.pathname + locationUrl.search;
|
|
63019
63142
|
}
|
|
63020
|
-
function deleteCachedUri(store, cacheKey,
|
|
63143
|
+
function deleteCachedUri(store, cacheKey, path110) {
|
|
63021
63144
|
deleteCachedValue(store, {
|
|
63022
63145
|
...cacheKey,
|
|
63023
|
-
path:
|
|
63146
|
+
path: path110
|
|
63024
63147
|
});
|
|
63025
63148
|
for (let i = 0; i < util.safeHTTPMethods.length; i++) {
|
|
63026
63149
|
const method = util.safeHTTPMethods[i];
|
|
@@ -63028,7 +63151,7 @@ var require_cache_handler = __commonJS({
|
|
|
63028
63151
|
deleteCachedValue(store, {
|
|
63029
63152
|
...cacheKey,
|
|
63030
63153
|
method,
|
|
63031
|
-
path:
|
|
63154
|
+
path: path110
|
|
63032
63155
|
});
|
|
63033
63156
|
}
|
|
63034
63157
|
}
|
|
@@ -63039,9 +63162,9 @@ var require_cache_handler = __commonJS({
|
|
|
63039
63162
|
}
|
|
63040
63163
|
const values = Array.isArray(headerValue) ? headerValue : [headerValue];
|
|
63041
63164
|
for (let i = 0; i < values.length; i++) {
|
|
63042
|
-
const
|
|
63043
|
-
if (
|
|
63044
|
-
deleteCachedUri(store, cacheKey,
|
|
63165
|
+
const path110 = getSameOriginPath(cacheKey, values[i]);
|
|
63166
|
+
if (path110 !== void 0) {
|
|
63167
|
+
deleteCachedUri(store, cacheKey, path110);
|
|
63045
63168
|
}
|
|
63046
63169
|
}
|
|
63047
63170
|
}
|
|
@@ -68264,11 +68387,11 @@ var require_fetch = __commonJS({
|
|
|
68264
68387
|
function dispatch({ body }) {
|
|
68265
68388
|
const url = requestCurrentURL(request2);
|
|
68266
68389
|
const agent = fetchParams.controller.dispatcher;
|
|
68267
|
-
const
|
|
68390
|
+
const path110 = url.pathname + url.search;
|
|
68268
68391
|
const hasTrailingQuestionMark = url.search.length === 0 && url.href[url.href.length - url.hash.length - 1] === "?";
|
|
68269
68392
|
return new Promise((resolve2, reject) => agent.dispatch(
|
|
68270
68393
|
{
|
|
68271
|
-
path: hasTrailingQuestionMark ? `${
|
|
68394
|
+
path: hasTrailingQuestionMark ? `${path110}?` : path110,
|
|
68272
68395
|
origin: url.origin,
|
|
68273
68396
|
method: request2.method,
|
|
68274
68397
|
body: agent.isMockActive ? request2.body && (request2.body.source || request2.body.stream) : body,
|
|
@@ -69220,9 +69343,9 @@ var require_util4 = __commonJS({
|
|
|
69220
69343
|
}
|
|
69221
69344
|
}
|
|
69222
69345
|
}
|
|
69223
|
-
function validateCookiePath(
|
|
69224
|
-
for (let i = 0; i <
|
|
69225
|
-
const code2 =
|
|
69346
|
+
function validateCookiePath(path110) {
|
|
69347
|
+
for (let i = 0; i < path110.length; ++i) {
|
|
69348
|
+
const code2 = path110.charCodeAt(i);
|
|
69226
69349
|
if (code2 < 32 || // exclude CTLs (0-31)
|
|
69227
69350
|
code2 > 126 || // exclude DEL and non-ascii
|
|
69228
69351
|
code2 === 59) {
|
|
@@ -72675,11 +72798,11 @@ var require_undici = __commonJS({
|
|
|
72675
72798
|
if (typeof opts.path !== "string") {
|
|
72676
72799
|
throw new InvalidArgumentError("invalid opts.path");
|
|
72677
72800
|
}
|
|
72678
|
-
let
|
|
72801
|
+
let path110 = opts.path;
|
|
72679
72802
|
if (!opts.path.startsWith("/")) {
|
|
72680
|
-
|
|
72803
|
+
path110 = `/${path110}`;
|
|
72681
72804
|
}
|
|
72682
|
-
url = new URL(util.parseOrigin(url).origin +
|
|
72805
|
+
url = new URL(util.parseOrigin(url).origin + path110);
|
|
72683
72806
|
} else {
|
|
72684
72807
|
if (!opts) {
|
|
72685
72808
|
opts = typeof url === "object" ? url : {};
|
|
@@ -72801,10 +72924,10 @@ function readFirstRunEnv() {
|
|
|
72801
72924
|
stdinTTY: !!process.stdin.isTTY,
|
|
72802
72925
|
stdoutTTY: !!process.stdout.isTTY,
|
|
72803
72926
|
ci: isCI() || process.env.NODE9_NONINTERACTIVE === "1",
|
|
72804
|
-
hasConfig:
|
|
72927
|
+
hasConfig: import_fs103.default.existsSync(import_path102.default.join(import_os83.default.homedir(), ".node9/config.json")),
|
|
72805
72928
|
// Any stored profile means this is not a never-configured machine. Treat
|
|
72806
72929
|
// malformed credential files conservatively and leave repair to explicit setup.
|
|
72807
|
-
hasCredentials: !!getCredentials() ||
|
|
72930
|
+
hasCredentials: !!getCredentials() || import_fs103.default.existsSync(import_path102.default.join(import_os83.default.homedir(), ".node9/credentials.json"))
|
|
72808
72931
|
};
|
|
72809
72932
|
}
|
|
72810
72933
|
function shouldOfferFirstRun(env) {
|
|
@@ -72909,14 +73032,14 @@ async function runSetupWizard(opts) {
|
|
|
72909
73032
|
process.exitCode = 130;
|
|
72910
73033
|
}
|
|
72911
73034
|
}
|
|
72912
|
-
var
|
|
73035
|
+
var import_fs103, import_os83, import_path102;
|
|
72913
73036
|
var init_first_run = __esm({
|
|
72914
73037
|
"src/cli/first-run.ts"() {
|
|
72915
73038
|
"use strict";
|
|
72916
73039
|
init_cjs_shims();
|
|
72917
|
-
|
|
72918
|
-
|
|
72919
|
-
|
|
73040
|
+
import_fs103 = __toESM(require("fs"));
|
|
73041
|
+
import_os83 = __toESM(require("os"));
|
|
73042
|
+
import_path102 = __toESM(require("path"));
|
|
72920
73043
|
init_config();
|
|
72921
73044
|
init_agent_wiring();
|
|
72922
73045
|
init_browser_login();
|
|
@@ -72962,20 +73085,20 @@ function getModelContextLimit(model) {
|
|
|
72962
73085
|
return 2e5;
|
|
72963
73086
|
}
|
|
72964
73087
|
function readSessionUsage() {
|
|
72965
|
-
const projectsDir =
|
|
72966
|
-
if (!
|
|
73088
|
+
const projectsDir = import_path103.default.join(import_os84.default.homedir(), ".claude", "projects");
|
|
73089
|
+
if (!import_fs104.default.existsSync(projectsDir)) return null;
|
|
72967
73090
|
let latestFile = null;
|
|
72968
73091
|
let latestMtime = 0;
|
|
72969
73092
|
try {
|
|
72970
|
-
for (const dir2 of
|
|
72971
|
-
const dirPath =
|
|
73093
|
+
for (const dir2 of import_fs104.default.readdirSync(projectsDir)) {
|
|
73094
|
+
const dirPath = import_path103.default.join(projectsDir, dir2);
|
|
72972
73095
|
try {
|
|
72973
|
-
if (!
|
|
72974
|
-
for (const file2 of
|
|
73096
|
+
if (!import_fs104.default.statSync(dirPath).isDirectory()) continue;
|
|
73097
|
+
for (const file2 of import_fs104.default.readdirSync(dirPath)) {
|
|
72975
73098
|
if (!file2.endsWith(".jsonl") || file2.startsWith("agent-")) continue;
|
|
72976
|
-
const filePath =
|
|
73099
|
+
const filePath = import_path103.default.join(dirPath, file2);
|
|
72977
73100
|
try {
|
|
72978
|
-
const mtime =
|
|
73101
|
+
const mtime = import_fs104.default.statSync(filePath).mtimeMs;
|
|
72979
73102
|
if (mtime > latestMtime) {
|
|
72980
73103
|
latestMtime = mtime;
|
|
72981
73104
|
latestFile = filePath;
|
|
@@ -72990,7 +73113,7 @@ function readSessionUsage() {
|
|
|
72990
73113
|
}
|
|
72991
73114
|
if (!latestFile) return null;
|
|
72992
73115
|
try {
|
|
72993
|
-
const lines =
|
|
73116
|
+
const lines = import_fs104.default.readFileSync(latestFile, "utf-8").split("\n");
|
|
72994
73117
|
let lastModel = "";
|
|
72995
73118
|
let lastInput = 0;
|
|
72996
73119
|
let lastOutput = 0;
|
|
@@ -73051,7 +73174,7 @@ function formatBase(activity) {
|
|
|
73051
73174
|
const time = new Date(activity.ts).toLocaleTimeString([], { hour12: false });
|
|
73052
73175
|
const icon = getIcon(activity.tool);
|
|
73053
73176
|
const toolName = activity.tool.slice(0, 16).padEnd(16);
|
|
73054
|
-
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(), "~");
|
|
73055
73178
|
const argsPreview = argsStr.length > 70 ? argsStr.slice(0, 70) + "\u2026" : argsStr;
|
|
73056
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)}`;
|
|
73057
73180
|
}
|
|
@@ -73090,9 +73213,9 @@ function renderPending(activity) {
|
|
|
73090
73213
|
}
|
|
73091
73214
|
async function ensureDaemon() {
|
|
73092
73215
|
let pidPort = null;
|
|
73093
|
-
if (
|
|
73216
|
+
if (import_fs104.default.existsSync(PID_FILE)) {
|
|
73094
73217
|
try {
|
|
73095
|
-
const { port } = JSON.parse(
|
|
73218
|
+
const { port } = JSON.parse(import_fs104.default.readFileSync(PID_FILE, "utf-8"));
|
|
73096
73219
|
pidPort = port;
|
|
73097
73220
|
} catch {
|
|
73098
73221
|
console.error(import_chalk49.default.dim("\u26A0\uFE0F Could not read PID file; falling back to default port."));
|
|
@@ -73118,7 +73241,7 @@ async function ensureDaemon() {
|
|
|
73118
73241
|
child.unref();
|
|
73119
73242
|
if (startupFd !== void 0) {
|
|
73120
73243
|
try {
|
|
73121
|
-
|
|
73244
|
+
import_fs104.default.closeSync(startupFd);
|
|
73122
73245
|
} catch {
|
|
73123
73246
|
}
|
|
73124
73247
|
}
|
|
@@ -73488,8 +73611,8 @@ async function startTail(options = {}) {
|
|
|
73488
73611
|
);
|
|
73489
73612
|
}).catch((err2) => {
|
|
73490
73613
|
try {
|
|
73491
|
-
|
|
73492
|
-
|
|
73614
|
+
import_fs104.default.appendFileSync(
|
|
73615
|
+
import_path103.default.join(import_os84.default.homedir(), ".node9", "hook-debug.log"),
|
|
73493
73616
|
`[tail] POST /decision failed: ${String(err2)}
|
|
73494
73617
|
`
|
|
73495
73618
|
);
|
|
@@ -73555,9 +73678,9 @@ async function startTail(options = {}) {
|
|
|
73555
73678
|
};
|
|
73556
73679
|
process.stdin.on("keypress", onKeypress);
|
|
73557
73680
|
}
|
|
73558
|
-
const auditLog =
|
|
73681
|
+
const auditLog = import_path103.default.join(import_os84.default.homedir(), ".node9", "audit.log");
|
|
73559
73682
|
try {
|
|
73560
|
-
const unackedDlp =
|
|
73683
|
+
const unackedDlp = import_fs104.default.readFileSync(auditLog, "utf-8").split("\n").filter((l) => l.includes('"response-dlp"')).length;
|
|
73561
73684
|
if (unackedDlp > 0) {
|
|
73562
73685
|
console.log("");
|
|
73563
73686
|
console.log(
|
|
@@ -73597,7 +73720,7 @@ async function startTail(options = {}) {
|
|
|
73597
73720
|
if (stallWarned) return;
|
|
73598
73721
|
if (Date.now() - lastActivityFromDaemon < STALL_THRESHOLD_MS) return;
|
|
73599
73722
|
try {
|
|
73600
|
-
const auditMtime =
|
|
73723
|
+
const auditMtime = import_fs104.default.statSync(auditLog).mtimeMs;
|
|
73601
73724
|
if (Date.now() - auditMtime >= STALL_THRESHOLD_MS) return;
|
|
73602
73725
|
console.log("");
|
|
73603
73726
|
console.log(
|
|
@@ -73769,7 +73892,7 @@ async function startTail(options = {}) {
|
|
|
73769
73892
|
process.exit(1);
|
|
73770
73893
|
});
|
|
73771
73894
|
}
|
|
73772
|
-
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;
|
|
73773
73896
|
var init_tail = __esm({
|
|
73774
73897
|
"src/tui/tail.ts"() {
|
|
73775
73898
|
"use strict";
|
|
@@ -73777,16 +73900,16 @@ var init_tail = __esm({
|
|
|
73777
73900
|
import_http6 = __toESM(require("http"));
|
|
73778
73901
|
init_write();
|
|
73779
73902
|
import_chalk49 = __toESM(require("chalk"));
|
|
73780
|
-
|
|
73781
|
-
|
|
73782
|
-
|
|
73903
|
+
import_fs104 = __toESM(require("fs"));
|
|
73904
|
+
import_os84 = __toESM(require("os"));
|
|
73905
|
+
import_path103 = __toESM(require("path"));
|
|
73783
73906
|
import_readline5 = __toESM(require("readline"));
|
|
73784
73907
|
import_child_process17 = require("child_process");
|
|
73785
73908
|
init_startup_log();
|
|
73786
73909
|
init_daemon3();
|
|
73787
73910
|
init_daemon();
|
|
73788
73911
|
init_safe_text();
|
|
73789
|
-
PID_FILE =
|
|
73912
|
+
PID_FILE = import_path103.default.join(import_os84.default.homedir(), ".node9", "daemon.pid");
|
|
73790
73913
|
ICONS = {
|
|
73791
73914
|
bash: "\u{1F4BB}",
|
|
73792
73915
|
shell: "\u{1F4BB}",
|
|
@@ -73908,9 +74031,9 @@ function formatTimeLeft(resetsAt) {
|
|
|
73908
74031
|
return ` (${m}m left)`;
|
|
73909
74032
|
}
|
|
73910
74033
|
function safeReadJson(filePath) {
|
|
73911
|
-
if (!
|
|
74034
|
+
if (!import_fs105.default.existsSync(filePath)) return null;
|
|
73912
74035
|
try {
|
|
73913
|
-
return JSON.parse(
|
|
74036
|
+
return JSON.parse(import_fs105.default.readFileSync(filePath, "utf-8"));
|
|
73914
74037
|
} catch {
|
|
73915
74038
|
return null;
|
|
73916
74039
|
}
|
|
@@ -73931,12 +74054,12 @@ function countHooksInFile(filePath) {
|
|
|
73931
74054
|
return Object.keys(cfg.hooks).length;
|
|
73932
74055
|
}
|
|
73933
74056
|
function countRulesInDir(rulesDir) {
|
|
73934
|
-
if (!
|
|
74057
|
+
if (!import_fs105.default.existsSync(rulesDir)) return 0;
|
|
73935
74058
|
let count = 0;
|
|
73936
74059
|
try {
|
|
73937
|
-
for (const entry of
|
|
74060
|
+
for (const entry of import_fs105.default.readdirSync(rulesDir, { withFileTypes: true })) {
|
|
73938
74061
|
if (entry.isDirectory()) {
|
|
73939
|
-
count += countRulesInDir(
|
|
74062
|
+
count += countRulesInDir(import_path104.default.join(rulesDir, entry.name));
|
|
73940
74063
|
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
73941
74064
|
count++;
|
|
73942
74065
|
}
|
|
@@ -73947,46 +74070,46 @@ function countRulesInDir(rulesDir) {
|
|
|
73947
74070
|
}
|
|
73948
74071
|
function isSamePath(a, b) {
|
|
73949
74072
|
try {
|
|
73950
|
-
return
|
|
74073
|
+
return import_path104.default.resolve(a) === import_path104.default.resolve(b);
|
|
73951
74074
|
} catch {
|
|
73952
74075
|
return false;
|
|
73953
74076
|
}
|
|
73954
74077
|
}
|
|
73955
74078
|
function countConfigs(cwd) {
|
|
73956
|
-
const homeDir2 =
|
|
73957
|
-
const claudeDir =
|
|
74079
|
+
const homeDir2 = import_os85.default.homedir();
|
|
74080
|
+
const claudeDir = import_path104.default.join(homeDir2, ".claude");
|
|
73958
74081
|
let claudeMdCount = 0;
|
|
73959
74082
|
let rulesCount = 0;
|
|
73960
74083
|
let hooksCount = 0;
|
|
73961
74084
|
const userMcpServers = /* @__PURE__ */ new Set();
|
|
73962
74085
|
const projectMcpServers = /* @__PURE__ */ new Set();
|
|
73963
|
-
if (
|
|
73964
|
-
rulesCount += countRulesInDir(
|
|
73965
|
-
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");
|
|
73966
74089
|
for (const name of getMcpServerNames(userSettings)) userMcpServers.add(name);
|
|
73967
74090
|
hooksCount += countHooksInFile(userSettings);
|
|
73968
|
-
const userClaudeJson =
|
|
74091
|
+
const userClaudeJson = import_path104.default.join(homeDir2, ".claude.json");
|
|
73969
74092
|
for (const name of getMcpServerNames(userClaudeJson)) userMcpServers.add(name);
|
|
73970
74093
|
for (const name of getDisabledMcpServers(userClaudeJson, "disabledMcpServers")) {
|
|
73971
74094
|
userMcpServers.delete(name);
|
|
73972
74095
|
}
|
|
73973
74096
|
if (cwd) {
|
|
73974
|
-
if (
|
|
73975
|
-
if (
|
|
73976
|
-
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");
|
|
73977
74100
|
const overlapsUserScope = isSamePath(projectClaudeDir, claudeDir);
|
|
73978
74101
|
if (!overlapsUserScope) {
|
|
73979
|
-
if (
|
|
73980
|
-
rulesCount += countRulesInDir(
|
|
73981
|
-
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");
|
|
73982
74105
|
for (const name of getMcpServerNames(projSettings)) projectMcpServers.add(name);
|
|
73983
74106
|
hooksCount += countHooksInFile(projSettings);
|
|
73984
74107
|
}
|
|
73985
|
-
if (
|
|
73986
|
-
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");
|
|
73987
74110
|
for (const name of getMcpServerNames(localSettings)) projectMcpServers.add(name);
|
|
73988
74111
|
hooksCount += countHooksInFile(localSettings);
|
|
73989
|
-
const mcpJsonServers = getMcpServerNames(
|
|
74112
|
+
const mcpJsonServers = getMcpServerNames(import_path104.default.join(cwd, ".mcp.json"));
|
|
73990
74113
|
const disabledMcpJson = getDisabledMcpServers(localSettings, "disabledMcpjsonServers");
|
|
73991
74114
|
for (const name of disabledMcpJson) mcpJsonServers.delete(name);
|
|
73992
74115
|
for (const name of mcpJsonServers) projectMcpServers.add(name);
|
|
@@ -74019,12 +74142,12 @@ function readActiveShieldsHud() {
|
|
|
74019
74142
|
return shieldsCache.value;
|
|
74020
74143
|
}
|
|
74021
74144
|
try {
|
|
74022
|
-
const shieldsPath =
|
|
74023
|
-
if (!
|
|
74145
|
+
const shieldsPath = import_path104.default.join(import_os85.default.homedir(), ".node9", "shields.json");
|
|
74146
|
+
if (!import_fs105.default.existsSync(shieldsPath)) {
|
|
74024
74147
|
shieldsCache = { value: [], ts: now };
|
|
74025
74148
|
return [];
|
|
74026
74149
|
}
|
|
74027
|
-
const parsed = JSON.parse(
|
|
74150
|
+
const parsed = JSON.parse(import_fs105.default.readFileSync(shieldsPath, "utf-8"));
|
|
74028
74151
|
if (!Array.isArray(parsed.active)) {
|
|
74029
74152
|
shieldsCache = { value: [], ts: now };
|
|
74030
74153
|
return [];
|
|
@@ -74126,17 +74249,17 @@ function renderContextLine(stdin) {
|
|
|
74126
74249
|
async function main() {
|
|
74127
74250
|
try {
|
|
74128
74251
|
const [stdin, daemonStatus2] = await Promise.all([readStdin(), queryDaemon()]);
|
|
74129
|
-
if (
|
|
74252
|
+
if (import_fs105.default.existsSync(import_path104.default.join(import_os85.default.homedir(), ".node9", "hud-debug"))) {
|
|
74130
74253
|
try {
|
|
74131
|
-
const logPath =
|
|
74254
|
+
const logPath = import_path104.default.join(import_os85.default.homedir(), ".node9", "hud-debug.log");
|
|
74132
74255
|
const MAX_LOG_SIZE = 10 * 1024 * 1024;
|
|
74133
74256
|
let size = 0;
|
|
74134
74257
|
try {
|
|
74135
|
-
size =
|
|
74258
|
+
size = import_fs105.default.statSync(logPath).size;
|
|
74136
74259
|
} catch {
|
|
74137
74260
|
}
|
|
74138
74261
|
if (size < MAX_LOG_SIZE) {
|
|
74139
|
-
|
|
74262
|
+
import_fs105.default.appendFileSync(
|
|
74140
74263
|
logPath,
|
|
74141
74264
|
JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), stdin }) + "\n"
|
|
74142
74265
|
);
|
|
@@ -74157,11 +74280,11 @@ async function main() {
|
|
|
74157
74280
|
try {
|
|
74158
74281
|
const cwd = stdin.cwd ?? process.cwd();
|
|
74159
74282
|
for (const configPath2 of [
|
|
74160
|
-
|
|
74161
|
-
|
|
74283
|
+
import_path104.default.join(cwd, "node9.config.json"),
|
|
74284
|
+
import_path104.default.join(import_os85.default.homedir(), ".node9", "config.json")
|
|
74162
74285
|
]) {
|
|
74163
|
-
if (!
|
|
74164
|
-
const cfg = JSON.parse(
|
|
74286
|
+
if (!import_fs105.default.existsSync(configPath2)) continue;
|
|
74287
|
+
const cfg = JSON.parse(import_fs105.default.readFileSync(configPath2, "utf-8"));
|
|
74165
74288
|
const hud = cfg.settings?.hud;
|
|
74166
74289
|
if (hud && "showEnvironmentCounts" in hud) return hud.showEnvironmentCounts !== false;
|
|
74167
74290
|
}
|
|
@@ -74179,14 +74302,14 @@ async function main() {
|
|
|
74179
74302
|
renderOffline();
|
|
74180
74303
|
}
|
|
74181
74304
|
}
|
|
74182
|
-
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;
|
|
74183
74306
|
var init_hud = __esm({
|
|
74184
74307
|
"src/cli/hud.ts"() {
|
|
74185
74308
|
"use strict";
|
|
74186
74309
|
init_cjs_shims();
|
|
74187
|
-
|
|
74188
|
-
|
|
74189
|
-
|
|
74310
|
+
import_fs105 = __toESM(require("fs"));
|
|
74311
|
+
import_path104 = __toESM(require("path"));
|
|
74312
|
+
import_os85 = __toESM(require("os"));
|
|
74190
74313
|
import_http7 = __toESM(require("http"));
|
|
74191
74314
|
init_daemon();
|
|
74192
74315
|
init_dist();
|
|
@@ -74251,9 +74374,9 @@ init_agent_wiring();
|
|
|
74251
74374
|
init_credentials();
|
|
74252
74375
|
init_daemon3();
|
|
74253
74376
|
var import_chalk50 = __toESM(require("chalk"));
|
|
74254
|
-
var
|
|
74255
|
-
var
|
|
74256
|
-
var
|
|
74377
|
+
var import_fs106 = __toESM(require("fs"));
|
|
74378
|
+
var import_path105 = __toESM(require("path"));
|
|
74379
|
+
var import_os86 = __toESM(require("os"));
|
|
74257
74380
|
var import_prompts4 = require("@inquirer/prompts");
|
|
74258
74381
|
|
|
74259
74382
|
// src/utils/duration.ts
|
|
@@ -74341,7 +74464,8 @@ async function runProxy(targetCommand) {
|
|
|
74341
74464
|
{
|
|
74342
74465
|
kind: result.blockKind,
|
|
74343
74466
|
path: result.blockedPath,
|
|
74344
|
-
redirect: !!result.redirect
|
|
74467
|
+
redirect: !!result.redirect,
|
|
74468
|
+
ruleDescription: result.ruleDescription
|
|
74345
74469
|
}
|
|
74346
74470
|
);
|
|
74347
74471
|
const errorResponse = {
|
|
@@ -74461,10 +74585,10 @@ function buildExplainJsonError(message) {
|
|
|
74461
74585
|
// src/cli/commands/check.ts
|
|
74462
74586
|
init_cjs_shims();
|
|
74463
74587
|
var import_chalk14 = __toESM(require("chalk"));
|
|
74464
|
-
var
|
|
74588
|
+
var import_fs75 = __toESM(require("fs"));
|
|
74465
74589
|
var import_child_process9 = require("child_process");
|
|
74466
|
-
var
|
|
74467
|
-
var
|
|
74590
|
+
var import_path75 = __toESM(require("path"));
|
|
74591
|
+
var import_os62 = __toESM(require("os"));
|
|
74468
74592
|
init_orchestrator();
|
|
74469
74593
|
init_state();
|
|
74470
74594
|
init_daemon();
|
|
@@ -74750,6 +74874,159 @@ function discardPendingReview(key, now = Date.now()) {
|
|
|
74750
74874
|
// src/cli/commands/check.ts
|
|
74751
74875
|
init_hook_payload();
|
|
74752
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
|
+
init_atomic_write();
|
|
74928
|
+
var ICON2 = "\u{1F6E1}\uFE0F";
|
|
74929
|
+
var LEVEL_NAMES = {
|
|
74930
|
+
audit: "Audit",
|
|
74931
|
+
soft: "Soft",
|
|
74932
|
+
standard: "Standard",
|
|
74933
|
+
strict: "Strict",
|
|
74934
|
+
"block-all": "Block all"
|
|
74935
|
+
};
|
|
74936
|
+
var SESSION_NOTICE_NOTE = "node9 shows the user this line itself. Do not mention it unless the user asks about node9.";
|
|
74937
|
+
var FLAG_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
74938
|
+
var SAFE_SESSION_ID = /^[A-Za-z0-9_-]{1,128}$/;
|
|
74939
|
+
function sessionNoticeLine(mode, kind = "first") {
|
|
74940
|
+
const level = levelOf(mode);
|
|
74941
|
+
const name = LEVEL_NAMES[level];
|
|
74942
|
+
if (kind === "changed") {
|
|
74943
|
+
return level === "audit" ? `${ICON2} Node9 level changed to Audit: actions are logged, nothing is blocked.` : `${ICON2} Node9 level changed to ${name}. Every action in this session is checked.`;
|
|
74944
|
+
}
|
|
74945
|
+
if (level === "audit") {
|
|
74946
|
+
return `${ICON2} Node9 is in Audit mode: actions are logged, nothing is blocked.`;
|
|
74947
|
+
}
|
|
74948
|
+
return `${ICON2} Node9 is on (${name}). Every action in this session is checked.`;
|
|
74949
|
+
}
|
|
74950
|
+
function sessionNoticeOutput(mode, kind = "first") {
|
|
74951
|
+
const line = sessionNoticeLine(mode, kind);
|
|
74952
|
+
return JSON.stringify({
|
|
74953
|
+
hookSpecificOutput: {
|
|
74954
|
+
hookEventName: "PreToolUse",
|
|
74955
|
+
additionalContext: `${line}
|
|
74956
|
+
${SESSION_NOTICE_NOTE}`
|
|
74957
|
+
},
|
|
74958
|
+
systemMessage: line
|
|
74959
|
+
});
|
|
74960
|
+
}
|
|
74961
|
+
function sessionNoticeEnabled(env = process.env) {
|
|
74962
|
+
if (env.NODE9_SESSION_NOTICE === "1") return true;
|
|
74963
|
+
return env.NODE9_TESTING !== "1";
|
|
74964
|
+
}
|
|
74965
|
+
var FLAG_MAX_BYTES = 32;
|
|
74966
|
+
function claimSessionNotice(sessionId, home = import_os61.default.homedir(), level = "standard") {
|
|
74967
|
+
if (!sessionId || !SAFE_SESSION_ID.test(sessionId)) return null;
|
|
74968
|
+
const dir2 = import_path74.default.join(home, ".node9", "notice-sessions");
|
|
74969
|
+
const seen = ensureOwnDir(dir2);
|
|
74970
|
+
if (!seen) return null;
|
|
74971
|
+
const flag = import_path74.default.join(dir2, sessionId + SESSION_FLAG_SUFFIX);
|
|
74972
|
+
let created = false;
|
|
74973
|
+
try {
|
|
74974
|
+
if (!isSameOwnDir(dir2, seen)) return null;
|
|
74975
|
+
const fd = import_fs74.default.openSync(flag, "wx", 384);
|
|
74976
|
+
created = true;
|
|
74977
|
+
try {
|
|
74978
|
+
import_fs74.default.writeSync(fd, level);
|
|
74979
|
+
} finally {
|
|
74980
|
+
import_fs74.default.closeSync(fd);
|
|
74981
|
+
}
|
|
74982
|
+
} catch (err2) {
|
|
74983
|
+
if (created) {
|
|
74984
|
+
try {
|
|
74985
|
+
import_fs74.default.unlinkSync(flag);
|
|
74986
|
+
} catch {
|
|
74987
|
+
}
|
|
74988
|
+
return null;
|
|
74989
|
+
}
|
|
74990
|
+
if (err2.code !== "EEXIST") return null;
|
|
74991
|
+
return levelChange(dir2, seen, flag, level);
|
|
74992
|
+
}
|
|
74993
|
+
removeOldFlags(dir2, seen);
|
|
74994
|
+
return "first";
|
|
74995
|
+
}
|
|
74996
|
+
function levelChange(dir2, seen, flag, level) {
|
|
74997
|
+
try {
|
|
74998
|
+
const told = readFlag(flag);
|
|
74999
|
+
if (told === null) return null;
|
|
75000
|
+
if (told === level) return null;
|
|
75001
|
+
if (!isSameOwnDir(dir2, seen)) return null;
|
|
75002
|
+
atomicWriteSync(flag, level, { mode: 384 });
|
|
75003
|
+
return told === "" ? null : "changed";
|
|
75004
|
+
} catch {
|
|
75005
|
+
return null;
|
|
75006
|
+
}
|
|
75007
|
+
}
|
|
75008
|
+
function readFlag(flag) {
|
|
75009
|
+
const c = import_fs74.default.constants;
|
|
75010
|
+
const fd = import_fs74.default.openSync(flag, c.O_RDONLY | (c.O_NOFOLLOW ?? 0) | (c.O_NONBLOCK ?? 0));
|
|
75011
|
+
try {
|
|
75012
|
+
const st = import_fs74.default.fstatSync(fd);
|
|
75013
|
+
if (!st.isFile() || st.nlink !== 1 || st.size > FLAG_MAX_BYTES) return null;
|
|
75014
|
+
const buf = Buffer.alloc(FLAG_MAX_BYTES);
|
|
75015
|
+
const n = import_fs74.default.readSync(fd, buf, 0, FLAG_MAX_BYTES, 0);
|
|
75016
|
+
return buf.toString("utf8", 0, n).trim();
|
|
75017
|
+
} finally {
|
|
75018
|
+
import_fs74.default.closeSync(fd);
|
|
75019
|
+
}
|
|
75020
|
+
}
|
|
75021
|
+
function removeOldFlags(dir2, seen) {
|
|
75022
|
+
const cutoff = Date.now() - FLAG_TTL_MS;
|
|
75023
|
+
try {
|
|
75024
|
+
for (const name of import_fs74.default.readdirSync(dir2)) removeOldFlag(dir2, seen, name, cutoff);
|
|
75025
|
+
} catch {
|
|
75026
|
+
}
|
|
75027
|
+
}
|
|
75028
|
+
|
|
75029
|
+
// src/cli/commands/check.ts
|
|
74753
75030
|
function detectAiAgent(payload) {
|
|
74754
75031
|
const meta = payload.meta;
|
|
74755
75032
|
if (meta && typeof meta === "object") {
|
|
@@ -74827,9 +75104,9 @@ function registerCheckCommand(program2) {
|
|
|
74827
75104
|
} catch (err2) {
|
|
74828
75105
|
const tempConfig = getConfig();
|
|
74829
75106
|
if (process.env.NODE9_DEBUG === "1" || tempConfig.settings.enableHookLogDebug) {
|
|
74830
|
-
const logPath =
|
|
75107
|
+
const logPath = import_path75.default.join(import_os62.default.homedir(), ".node9", "hook-debug.log");
|
|
74831
75108
|
const errMsg = err2 instanceof Error ? err2.message : String(err2);
|
|
74832
|
-
|
|
75109
|
+
import_fs75.default.appendFileSync(
|
|
74833
75110
|
logPath,
|
|
74834
75111
|
`[${(/* @__PURE__ */ new Date()).toISOString()}] JSON_PARSE_ERROR: ${errMsg}
|
|
74835
75112
|
RAW: ${raw}
|
|
@@ -74842,14 +75119,14 @@ RAW: ${raw}
|
|
|
74842
75119
|
const prompt = typeof payload.prompt === "string" ? payload.prompt : "";
|
|
74843
75120
|
if (process.env.NODE9_DEBUG === "1") {
|
|
74844
75121
|
try {
|
|
74845
|
-
const logPath =
|
|
74846
|
-
if (!
|
|
74847
|
-
|
|
75122
|
+
const logPath = import_path75.default.join(import_os62.default.homedir(), ".node9", "hook-debug.log");
|
|
75123
|
+
if (!import_fs75.default.existsSync(import_path75.default.dirname(logPath)))
|
|
75124
|
+
import_fs75.default.mkdirSync(import_path75.default.dirname(logPath), { recursive: true });
|
|
74848
75125
|
const sanitized = JSON.stringify({
|
|
74849
75126
|
...payload,
|
|
74850
75127
|
prompt: `<redacted, ${prompt.length} bytes>`
|
|
74851
75128
|
});
|
|
74852
|
-
|
|
75129
|
+
import_fs75.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] STDIN: ${sanitized}
|
|
74853
75130
|
`);
|
|
74854
75131
|
} catch {
|
|
74855
75132
|
}
|
|
@@ -74867,7 +75144,7 @@ RAW: ${raw}
|
|
|
74867
75144
|
if (!dlpMatch && !canaryHit) {
|
|
74868
75145
|
try {
|
|
74869
75146
|
const sid = typeof payload.session_id === "string" ? payload.session_id : typeof payload.conversationId === "string" ? payload.conversationId : "";
|
|
74870
|
-
const promptCwd = typeof payload.cwd === "string" &&
|
|
75147
|
+
const promptCwd = typeof payload.cwd === "string" && import_path75.default.isAbsolute(payload.cwd) ? payload.cwd : void 0;
|
|
74871
75148
|
if (sid && getConfig(promptCwd).policy.untrustedContent?.enabled) {
|
|
74872
75149
|
await notifyUserMentions(sid, extractContentDestinations(prompt));
|
|
74873
75150
|
}
|
|
@@ -74908,8 +75185,8 @@ RAW: ${raw}
|
|
|
74908
75185
|
);
|
|
74909
75186
|
const reason = `\u{1F6A8} Node9 DLP: ${shownPattern} detected in prompt (${shownSample}). Prompt was not submitted \u2014 remove the credential and try again.`;
|
|
74910
75187
|
try {
|
|
74911
|
-
const ttyFd =
|
|
74912
|
-
|
|
75188
|
+
const ttyFd = import_fs75.default.openSync("/dev/tty", "w");
|
|
75189
|
+
import_fs75.default.writeSync(
|
|
74913
75190
|
ttyFd,
|
|
74914
75191
|
import_chalk14.default.bgRed.white.bold(`
|
|
74915
75192
|
\u{1F6A8} NODE9 DLP \u2014 PROMPT BLOCKED
|
|
@@ -74919,7 +75196,7 @@ RAW: ${raw}
|
|
|
74919
75196
|
|
|
74920
75197
|
`)
|
|
74921
75198
|
);
|
|
74922
|
-
|
|
75199
|
+
import_fs75.default.closeSync(ttyFd);
|
|
74923
75200
|
} catch {
|
|
74924
75201
|
}
|
|
74925
75202
|
const isCodex = agent2 === "Codex";
|
|
@@ -74938,17 +75215,17 @@ RAW: ${raw}
|
|
|
74938
75215
|
process.exit(2);
|
|
74939
75216
|
}
|
|
74940
75217
|
const payloadCwd = typeof payload.cwd === "string" ? payload.cwd : Array.isArray(payload.workspacePaths) && typeof payload.workspacePaths[0] === "string" ? payload.workspacePaths[0] : void 0;
|
|
74941
|
-
const safeCwdForConfig = typeof payloadCwd === "string" &&
|
|
75218
|
+
const safeCwdForConfig = typeof payloadCwd === "string" && import_path75.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
|
|
74942
75219
|
const config = getConfig(safeCwdForConfig);
|
|
74943
75220
|
const daemonDown = !isDaemonRunning();
|
|
74944
75221
|
if (config.settings.autoStartDaemon && daemonDown && !process.env.NODE9_NO_AUTO_DAEMON) {
|
|
74945
75222
|
try {
|
|
74946
75223
|
const scriptPath = process.argv[1];
|
|
74947
|
-
if (typeof scriptPath !== "string" || !
|
|
75224
|
+
if (typeof scriptPath !== "string" || !import_path75.default.isAbsolute(scriptPath))
|
|
74948
75225
|
throw new Error("node9: argv[1] is not an absolute path");
|
|
74949
|
-
const resolvedScript =
|
|
74950
|
-
const packageDist =
|
|
74951
|
-
if (!resolvedScript.startsWith(packageDist +
|
|
75226
|
+
const resolvedScript = import_fs75.default.realpathSync(scriptPath);
|
|
75227
|
+
const packageDist = import_fs75.default.realpathSync(import_path75.default.resolve(__dirname, "../.."));
|
|
75228
|
+
if (!resolvedScript.startsWith(packageDist + import_path75.default.sep) && resolvedScript !== packageDist)
|
|
74952
75229
|
throw new Error(
|
|
74953
75230
|
`node9: daemon spawn aborted \u2014 argv[1] (${resolvedScript}) is outside package dist (${packageDist})`
|
|
74954
75231
|
);
|
|
@@ -74978,17 +75255,17 @@ RAW: ${raw}
|
|
|
74978
75255
|
} finally {
|
|
74979
75256
|
if (startupFd !== void 0) {
|
|
74980
75257
|
try {
|
|
74981
|
-
|
|
75258
|
+
import_fs75.default.closeSync(startupFd);
|
|
74982
75259
|
} catch {
|
|
74983
75260
|
}
|
|
74984
75261
|
}
|
|
74985
75262
|
}
|
|
74986
75263
|
} catch (spawnErr) {
|
|
74987
|
-
const logPath =
|
|
75264
|
+
const logPath = import_path75.default.join(import_os62.default.homedir(), ".node9", "hook-debug.log");
|
|
74988
75265
|
const msg = spawnErr instanceof Error ? spawnErr.message : String(spawnErr);
|
|
74989
75266
|
recordStartupState("failed", "spawn-aborted", msg);
|
|
74990
75267
|
try {
|
|
74991
|
-
|
|
75268
|
+
import_fs75.default.appendFileSync(
|
|
74992
75269
|
logPath,
|
|
74993
75270
|
`[${(/* @__PURE__ */ new Date()).toISOString()}] daemon-autostart-failed: ${msg}
|
|
74994
75271
|
`
|
|
@@ -75002,10 +75279,10 @@ RAW: ${raw}
|
|
|
75002
75279
|
);
|
|
75003
75280
|
}
|
|
75004
75281
|
if (process.env.NODE9_DEBUG === "1" || config.settings.enableHookLogDebug) {
|
|
75005
|
-
const logPath =
|
|
75006
|
-
if (!
|
|
75007
|
-
|
|
75008
|
-
|
|
75282
|
+
const logPath = import_path75.default.join(import_os62.default.homedir(), ".node9", "hook-debug.log");
|
|
75283
|
+
if (!import_fs75.default.existsSync(import_path75.default.dirname(logPath)))
|
|
75284
|
+
import_fs75.default.mkdirSync(import_path75.default.dirname(logPath), { recursive: true });
|
|
75285
|
+
import_fs75.default.appendFileSync(
|
|
75009
75286
|
logPath,
|
|
75010
75287
|
`[${(/* @__PURE__ */ new Date()).toISOString()}] STDIN: ${JSON.stringify(raw)}
|
|
75011
75288
|
`
|
|
@@ -75026,8 +75303,8 @@ RAW: ${raw}
|
|
|
75026
75303
|
);
|
|
75027
75304
|
let ttyFd = null;
|
|
75028
75305
|
try {
|
|
75029
|
-
ttyFd =
|
|
75030
|
-
const writeTty = (line) =>
|
|
75306
|
+
ttyFd = import_fs75.default.openSync("/dev/tty", "w");
|
|
75307
|
+
const writeTty = (line) => import_fs75.default.writeSync(ttyFd, line + "\n");
|
|
75031
75308
|
if (result2?.blockKind === "protected-path") {
|
|
75032
75309
|
writeTty(
|
|
75033
75310
|
import_chalk14.default.red.bold(
|
|
@@ -75054,7 +75331,7 @@ RAW: ${raw}
|
|
|
75054
75331
|
} finally {
|
|
75055
75332
|
if (ttyFd !== null)
|
|
75056
75333
|
try {
|
|
75057
|
-
|
|
75334
|
+
import_fs75.default.closeSync(ttyFd);
|
|
75058
75335
|
} catch {
|
|
75059
75336
|
}
|
|
75060
75337
|
}
|
|
@@ -75063,7 +75340,12 @@ RAW: ${raw}
|
|
|
75063
75340
|
humanDecision,
|
|
75064
75341
|
msg,
|
|
75065
75342
|
result2?.recoveryCommand,
|
|
75066
|
-
{
|
|
75343
|
+
{
|
|
75344
|
+
kind: result2?.blockKind,
|
|
75345
|
+
path: result2?.blockedPath,
|
|
75346
|
+
redirect: !!result2?.redirect,
|
|
75347
|
+
ruleDescription: result2?.ruleDescription
|
|
75348
|
+
}
|
|
75067
75349
|
);
|
|
75068
75350
|
if (agent === "Antigravity") {
|
|
75069
75351
|
process.stdout.write(
|
|
@@ -75080,11 +75362,13 @@ RAW: ${raw}
|
|
|
75080
75362
|
);
|
|
75081
75363
|
process.exit(0);
|
|
75082
75364
|
}
|
|
75365
|
+
const userLine = userLineOf(aiFeedbackMessage);
|
|
75083
75366
|
process.stdout.write(
|
|
75084
75367
|
JSON.stringify({
|
|
75085
75368
|
decision: "block",
|
|
75086
75369
|
reason: aiFeedbackMessage,
|
|
75087
75370
|
// This is the core instruction
|
|
75371
|
+
...agent === "Claude Code" && userLine ? { systemMessage: userLine } : {},
|
|
75088
75372
|
hookSpecificOutput: {
|
|
75089
75373
|
hookEventName: "PreToolUse",
|
|
75090
75374
|
permissionDecision: "deny",
|
|
@@ -75118,8 +75402,8 @@ RAW: ${raw}
|
|
|
75118
75402
|
} catch {
|
|
75119
75403
|
}
|
|
75120
75404
|
try {
|
|
75121
|
-
const ttyFd =
|
|
75122
|
-
|
|
75405
|
+
const ttyFd = import_fs75.default.openSync("/dev/tty", "w");
|
|
75406
|
+
import_fs75.default.writeSync(
|
|
75123
75407
|
ttyFd,
|
|
75124
75408
|
import_chalk14.default.yellow(
|
|
75125
75409
|
`
|
|
@@ -75127,7 +75411,7 @@ RAW: ${raw}
|
|
|
75127
75411
|
`
|
|
75128
75412
|
)
|
|
75129
75413
|
);
|
|
75130
|
-
|
|
75414
|
+
import_fs75.default.closeSync(ttyFd);
|
|
75131
75415
|
} catch {
|
|
75132
75416
|
}
|
|
75133
75417
|
if (agent === "GitHub Copilot") {
|
|
@@ -75159,17 +75443,20 @@ RAW: ${raw}
|
|
|
75159
75443
|
const safeSessionId = /^[A-Za-z0-9_\-]{1,128}$/.test(rawSessionId) ? rawSessionId : "";
|
|
75160
75444
|
if (skillPinCfg.enabled && safeSessionId) {
|
|
75161
75445
|
try {
|
|
75162
|
-
const sessionsDir =
|
|
75163
|
-
const flagPath =
|
|
75446
|
+
const sessionsDir = import_path75.default.join(import_os62.default.homedir(), ".node9", "skill-sessions");
|
|
75447
|
+
const flagPath = import_path75.default.join(sessionsDir, `${safeSessionId}${SESSION_FLAG_SUFFIX}`);
|
|
75448
|
+
const memo = ensureOwnDir(sessionsDir);
|
|
75164
75449
|
let flag = null;
|
|
75165
75450
|
try {
|
|
75166
|
-
|
|
75451
|
+
const st = memo ? import_fs75.default.lstatSync(flagPath) : null;
|
|
75452
|
+
if (st && st.isFile() && st.nlink === 1)
|
|
75453
|
+
flag = JSON.parse(import_fs75.default.readFileSync(flagPath, "utf-8"));
|
|
75167
75454
|
} catch {
|
|
75168
75455
|
}
|
|
75169
75456
|
const writeFlag = (data2) => {
|
|
75457
|
+
if (!memo || !isSameOwnDir(sessionsDir, memo)) return;
|
|
75170
75458
|
try {
|
|
75171
|
-
|
|
75172
|
-
import_fs73.default.writeFileSync(
|
|
75459
|
+
atomicWriteSync(
|
|
75173
75460
|
flagPath,
|
|
75174
75461
|
JSON.stringify({ ...data2, timestamp: (/* @__PURE__ */ new Date()).toISOString() }, null, 2),
|
|
75175
75462
|
{ mode: 384 }
|
|
@@ -75180,8 +75467,8 @@ RAW: ${raw}
|
|
|
75180
75467
|
const sendSkillWarn = (detail, recoveryCmd) => {
|
|
75181
75468
|
let ttyFd = null;
|
|
75182
75469
|
try {
|
|
75183
|
-
ttyFd =
|
|
75184
|
-
const w = (line) =>
|
|
75470
|
+
ttyFd = import_fs75.default.openSync("/dev/tty", "w");
|
|
75471
|
+
const w = (line) => import_fs75.default.writeSync(ttyFd, line + "\n");
|
|
75185
75472
|
w(import_chalk14.default.yellow(`
|
|
75186
75473
|
\u26A0\uFE0F Node9: installed skill drift detected`));
|
|
75187
75474
|
w(import_chalk14.default.gray(` ${detail}`));
|
|
@@ -75196,7 +75483,7 @@ RAW: ${raw}
|
|
|
75196
75483
|
} finally {
|
|
75197
75484
|
if (ttyFd !== null)
|
|
75198
75485
|
try {
|
|
75199
|
-
|
|
75486
|
+
import_fs75.default.closeSync(ttyFd);
|
|
75200
75487
|
} catch {
|
|
75201
75488
|
}
|
|
75202
75489
|
}
|
|
@@ -75212,7 +75499,7 @@ RAW: ${raw}
|
|
|
75212
75499
|
return;
|
|
75213
75500
|
}
|
|
75214
75501
|
if (!flag || flag.state !== "verified" && flag.state !== "warned") {
|
|
75215
|
-
const absoluteCwd = typeof payloadCwd === "string" &&
|
|
75502
|
+
const absoluteCwd = typeof payloadCwd === "string" && import_path75.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
|
|
75216
75503
|
const extraRoots = skillPinCfg.roots;
|
|
75217
75504
|
const resolvedExtra = extraRoots.map((r) => resolveUserSkillRoot(r, absoluteCwd)).filter((r) => typeof r === "string");
|
|
75218
75505
|
const roots = [...defaultSkillRoots(absoluteCwd), ...resolvedExtra];
|
|
@@ -75251,31 +75538,27 @@ RAW: ${raw}
|
|
|
75251
75538
|
} else {
|
|
75252
75539
|
writeFlag({ state: "verified" });
|
|
75253
75540
|
}
|
|
75254
|
-
|
|
75255
|
-
|
|
75256
|
-
|
|
75257
|
-
const
|
|
75258
|
-
|
|
75259
|
-
|
|
75260
|
-
} catch {
|
|
75261
|
-
}
|
|
75541
|
+
if (memo)
|
|
75542
|
+
try {
|
|
75543
|
+
const cutoff = Date.now() - 7 * 24 * 60 * 60 * 1e3;
|
|
75544
|
+
for (const name of import_fs75.default.readdirSync(sessionsDir))
|
|
75545
|
+
removeOldFlag(sessionsDir, memo, name, cutoff);
|
|
75546
|
+
} catch {
|
|
75262
75547
|
}
|
|
75263
|
-
} catch {
|
|
75264
|
-
}
|
|
75265
75548
|
}
|
|
75266
75549
|
} catch (err2) {
|
|
75267
75550
|
if (process.env.NODE9_DEBUG === "1") {
|
|
75268
75551
|
try {
|
|
75269
|
-
const dbg =
|
|
75552
|
+
const dbg = import_path75.default.join(import_os62.default.homedir(), ".node9", "hook-debug.log");
|
|
75270
75553
|
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
75271
|
-
|
|
75554
|
+
import_fs75.default.appendFileSync(dbg, `[${(/* @__PURE__ */ new Date()).toISOString()}] SKILL_PIN_ERROR: ${msg}
|
|
75272
75555
|
`);
|
|
75273
75556
|
} catch {
|
|
75274
75557
|
}
|
|
75275
75558
|
}
|
|
75276
75559
|
}
|
|
75277
75560
|
}
|
|
75278
|
-
const safeCwdForAuth = typeof payloadCwd === "string" &&
|
|
75561
|
+
const safeCwdForAuth = typeof payloadCwd === "string" && import_path75.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
|
|
75279
75562
|
const askMode = resolveAskMode(agent, opts, config);
|
|
75280
75563
|
const result = await authorizeHeadless(toolName, toolInput, meta, {
|
|
75281
75564
|
cwd: safeCwdForAuth,
|
|
@@ -75288,11 +75571,22 @@ RAW: ${raw}
|
|
|
75288
75571
|
} catch {
|
|
75289
75572
|
}
|
|
75290
75573
|
}
|
|
75574
|
+
const isSubagentCall = typeof payload.agent_id === "string" && payload.agent_id !== "";
|
|
75575
|
+
const allowExit = (checkedBy) => {
|
|
75576
|
+
const notice = checkedBy !== "paused" && agent === "Claude Code" && !isSubagentCall && sessionNoticeEnabled() ? claimSessionNotice(safeSessionId, import_os62.default.homedir(), levelOf(config.settings.mode)) : null;
|
|
75577
|
+
if (notice) {
|
|
75578
|
+
try {
|
|
75579
|
+
import_fs75.default.writeSync(1, sessionNoticeOutput(config.settings.mode, notice) + "\n");
|
|
75580
|
+
} catch {
|
|
75581
|
+
}
|
|
75582
|
+
}
|
|
75583
|
+
process.exit(0);
|
|
75584
|
+
};
|
|
75291
75585
|
if (result.approved) {
|
|
75292
75586
|
if (result.checkedBy && process.env.NODE9_DEBUG === "1")
|
|
75293
75587
|
process.stderr.write(`\u2713 node9 [${result.checkedBy}]: "${toolName}" allowed
|
|
75294
75588
|
`);
|
|
75295
|
-
|
|
75589
|
+
allowExit(result.checkedBy);
|
|
75296
75590
|
}
|
|
75297
75591
|
if (result.review) {
|
|
75298
75592
|
sendAsk(result);
|
|
@@ -75300,12 +75594,12 @@ RAW: ${raw}
|
|
|
75300
75594
|
}
|
|
75301
75595
|
if (result.noApprovalMechanism && !isDaemonRunning() && !process.env.NODE9_NO_AUTO_DAEMON && !process.stdout.isTTY && config.settings.autoStartDaemon) {
|
|
75302
75596
|
try {
|
|
75303
|
-
const tty =
|
|
75304
|
-
|
|
75597
|
+
const tty = import_fs75.default.openSync("/dev/tty", "w");
|
|
75598
|
+
import_fs75.default.writeSync(
|
|
75305
75599
|
tty,
|
|
75306
75600
|
import_chalk14.default.cyan("\n\u{1F6E1}\uFE0F Node9: Starting approval daemon automatically...\n")
|
|
75307
75601
|
);
|
|
75308
|
-
|
|
75602
|
+
import_fs75.default.closeSync(tty);
|
|
75309
75603
|
} catch {
|
|
75310
75604
|
}
|
|
75311
75605
|
const daemonReady = await autoStartDaemonAndWait();
|
|
@@ -75317,7 +75611,7 @@ RAW: ${raw}
|
|
|
75317
75611
|
if (retry.checkedBy && process.env.NODE9_DEBUG === "1")
|
|
75318
75612
|
process.stderr.write(`\u2713 node9 [${retry.checkedBy}]: "${toolName}" allowed
|
|
75319
75613
|
`);
|
|
75320
|
-
|
|
75614
|
+
allowExit(retry.checkedBy);
|
|
75321
75615
|
}
|
|
75322
75616
|
sendBlock(retry.reason ?? `Node9 blocked "${toolName}".`, {
|
|
75323
75617
|
...retry,
|
|
@@ -75332,9 +75626,9 @@ RAW: ${raw}
|
|
|
75332
75626
|
});
|
|
75333
75627
|
} catch (err2) {
|
|
75334
75628
|
if (process.env.NODE9_DEBUG === "1") {
|
|
75335
|
-
const logPath =
|
|
75629
|
+
const logPath = import_path75.default.join(import_os62.default.homedir(), ".node9", "hook-debug.log");
|
|
75336
75630
|
const errMsg = err2 instanceof Error ? err2.message : String(err2);
|
|
75337
|
-
|
|
75631
|
+
import_fs75.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] ERROR: ${errMsg}
|
|
75338
75632
|
`);
|
|
75339
75633
|
}
|
|
75340
75634
|
process.exit(0);
|
|
@@ -75369,9 +75663,9 @@ RAW: ${raw}
|
|
|
75369
75663
|
|
|
75370
75664
|
// src/cli/commands/log.ts
|
|
75371
75665
|
init_cjs_shims();
|
|
75372
|
-
var
|
|
75373
|
-
var
|
|
75374
|
-
var
|
|
75666
|
+
var import_fs76 = __toESM(require("fs"));
|
|
75667
|
+
var import_path76 = __toESM(require("path"));
|
|
75668
|
+
var import_os63 = __toESM(require("os"));
|
|
75375
75669
|
init_audit();
|
|
75376
75670
|
init_config();
|
|
75377
75671
|
init_daemon();
|
|
@@ -75651,12 +75945,12 @@ function registerLogCommand(program2) {
|
|
|
75651
75945
|
if (rawToolName !== tool) entry.agentToolName = rawToolName;
|
|
75652
75946
|
const payloadSessionId = payload.session_id ?? payload.conversationId;
|
|
75653
75947
|
if (payloadSessionId) entry.sessionId = payloadSessionId;
|
|
75654
|
-
const logPath =
|
|
75655
|
-
if (!
|
|
75656
|
-
|
|
75657
|
-
|
|
75948
|
+
const logPath = import_path76.default.join(import_os63.default.homedir(), ".node9", "audit.log");
|
|
75949
|
+
if (!import_fs76.default.existsSync(import_path76.default.dirname(logPath)))
|
|
75950
|
+
import_fs76.default.mkdirSync(import_path76.default.dirname(logPath), { recursive: true });
|
|
75951
|
+
import_fs76.default.appendFileSync(logPath, JSON.stringify(entry) + "\n");
|
|
75658
75952
|
const payloadCwd = typeof payload.cwd === "string" ? payload.cwd : Array.isArray(payload.workspacePaths) && typeof payload.workspacePaths[0] === "string" ? payload.workspacePaths[0] : void 0;
|
|
75659
|
-
const safeCwd = typeof payloadCwd === "string" &&
|
|
75953
|
+
const safeCwd = typeof payloadCwd === "string" && import_path76.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
|
|
75660
75954
|
if ((tool === "Bash" || tool === "bash") && isDaemonRunning()) {
|
|
75661
75955
|
const command = typeof rawInput === "object" && rawInput !== null && "command" in rawInput && typeof rawInput.command === "string" ? rawInput.command : null;
|
|
75662
75956
|
if (command) {
|
|
@@ -75877,9 +76171,9 @@ function registerLogCommand(program2) {
|
|
|
75877
76171
|
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
75878
76172
|
process.stderr.write(`[Node9] audit log error: ${msg}
|
|
75879
76173
|
`);
|
|
75880
|
-
const debugPath =
|
|
76174
|
+
const debugPath = import_path76.default.join(import_os63.default.homedir(), ".node9", "hook-debug.log");
|
|
75881
76175
|
try {
|
|
75882
|
-
|
|
76176
|
+
import_fs76.default.appendFileSync(debugPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] LOG_ERROR: ${msg}
|
|
75883
76177
|
`);
|
|
75884
76178
|
} catch {
|
|
75885
76179
|
}
|
|
@@ -75902,9 +76196,9 @@ function registerLogCommand(program2) {
|
|
|
75902
76196
|
});
|
|
75903
76197
|
}
|
|
75904
76198
|
function absolutePathFor(spelled, cwd) {
|
|
75905
|
-
const expanded = spelled === "~" || spelled.startsWith("~/") ?
|
|
75906
|
-
if (
|
|
75907
|
-
return cwd ?
|
|
76199
|
+
const expanded = spelled === "~" || spelled.startsWith("~/") ? import_path76.default.join(import_os63.default.homedir(), spelled.slice(1)) : spelled;
|
|
76200
|
+
if (import_path76.default.isAbsolute(expanded)) return expanded;
|
|
76201
|
+
return cwd ? import_path76.default.resolve(cwd, expanded) : import_path76.default.resolve(expanded);
|
|
75908
76202
|
}
|
|
75909
76203
|
async function carryTaintAcrossWrites(command, cwd) {
|
|
75910
76204
|
let pairs;
|
|
@@ -75923,23 +76217,23 @@ async function carryTaintAcrossWrites(command, cwd) {
|
|
|
75923
76217
|
continue;
|
|
75924
76218
|
}
|
|
75925
76219
|
const sensitive = scanFilePath(src, cwd);
|
|
75926
|
-
if (sensitive) await notifyTaint(dst, `copy:${sensitive.patternName}:${
|
|
76220
|
+
if (sensitive) await notifyTaint(dst, `copy:${sensitive.patternName}:${import_path76.default.basename(src)}`);
|
|
75927
76221
|
}
|
|
75928
76222
|
}
|
|
75929
76223
|
|
|
75930
76224
|
// src/cli/commands/shield.ts
|
|
75931
76225
|
init_cjs_shims();
|
|
75932
76226
|
var import_chalk16 = __toESM(require("chalk"));
|
|
75933
|
-
var
|
|
75934
|
-
var
|
|
75935
|
-
var
|
|
76227
|
+
var import_fs78 = __toESM(require("fs"));
|
|
76228
|
+
var import_path78 = __toESM(require("path"));
|
|
76229
|
+
var import_os64 = __toESM(require("os"));
|
|
75936
76230
|
init_shields();
|
|
75937
76231
|
init_build();
|
|
75938
76232
|
|
|
75939
76233
|
// src/shields/create.ts
|
|
75940
76234
|
init_cjs_shims();
|
|
75941
|
-
var
|
|
75942
|
-
var
|
|
76235
|
+
var import_fs77 = __toESM(require("fs"));
|
|
76236
|
+
var import_path77 = __toESM(require("path"));
|
|
75943
76237
|
init_dist();
|
|
75944
76238
|
init_shields();
|
|
75945
76239
|
init_audit();
|
|
@@ -75959,8 +76253,8 @@ function createShield(def, opts = {}) {
|
|
|
75959
76253
|
error: `"${name}" is a built-in shield \u2014 choose a different name (a user shield with this name would shadow the built-in).`
|
|
75960
76254
|
};
|
|
75961
76255
|
}
|
|
75962
|
-
const filePath =
|
|
75963
|
-
if (!opts.overwrite &&
|
|
76256
|
+
const filePath = import_path77.default.join(USER_SHIELDS_DIR_PATH, `${name}.json`);
|
|
76257
|
+
if (!opts.overwrite && import_fs77.default.existsSync(filePath)) {
|
|
75964
76258
|
return {
|
|
75965
76259
|
ok: false,
|
|
75966
76260
|
error: `Shield "${name}" already exists at ${filePath}. Pass --overwrite to replace it.`
|
|
@@ -76058,8 +76352,8 @@ var COMMUNITY_INDEX_URL = "https://raw.githubusercontent.com/node9ai/node9-proxy
|
|
|
76058
76352
|
function readCloudShields() {
|
|
76059
76353
|
const out = /* @__PURE__ */ new Set();
|
|
76060
76354
|
try {
|
|
76061
|
-
const file2 =
|
|
76062
|
-
const raw = JSON.parse(
|
|
76355
|
+
const file2 = import_path78.default.join(import_os64.default.homedir(), ".node9", "rules-cache.json");
|
|
76356
|
+
const raw = JSON.parse(import_fs78.default.readFileSync(file2, "utf-8"));
|
|
76063
76357
|
for (const r of raw.rules ?? []) {
|
|
76064
76358
|
const rule = r;
|
|
76065
76359
|
const fromSource = rule.source?.startsWith("SHIELD:") ? rule.source.slice("SHIELD:".length).toLowerCase() : void 0;
|
|
@@ -76396,7 +76690,7 @@ function registerShieldCommand(program2) {
|
|
|
76396
76690
|
if (opts.fromFile) {
|
|
76397
76691
|
let raw;
|
|
76398
76692
|
try {
|
|
76399
|
-
raw = JSON.parse(
|
|
76693
|
+
raw = JSON.parse(import_fs78.default.readFileSync(opts.fromFile, "utf-8"));
|
|
76400
76694
|
} catch (err2) {
|
|
76401
76695
|
console.error(
|
|
76402
76696
|
import_chalk16.default.red(`
|
|
@@ -76744,9 +77038,9 @@ init_migrate();
|
|
|
76744
77038
|
// src/cli/commands/doctor.ts
|
|
76745
77039
|
init_cjs_shims();
|
|
76746
77040
|
var import_chalk19 = __toESM(require("chalk"));
|
|
76747
|
-
var
|
|
76748
|
-
var
|
|
76749
|
-
var
|
|
77041
|
+
var import_fs80 = __toESM(require("fs"));
|
|
77042
|
+
var import_path80 = __toESM(require("path"));
|
|
77043
|
+
var import_os66 = __toESM(require("os"));
|
|
76750
77044
|
var import_child_process10 = require("child_process");
|
|
76751
77045
|
init_daemon();
|
|
76752
77046
|
init_build_id();
|
|
@@ -76775,22 +77069,22 @@ init_startup_log();
|
|
|
76775
77069
|
|
|
76776
77070
|
// src/utils/undo-leftovers.ts
|
|
76777
77071
|
init_cjs_shims();
|
|
76778
|
-
var
|
|
76779
|
-
var
|
|
76780
|
-
var
|
|
77072
|
+
var import_fs79 = __toESM(require("fs"));
|
|
77073
|
+
var import_os65 = __toESM(require("os"));
|
|
77074
|
+
var import_path79 = __toESM(require("path"));
|
|
76781
77075
|
function candidates(homeDir2) {
|
|
76782
|
-
const node9Dir =
|
|
77076
|
+
const node9Dir = import_path79.default.join(homeDir2, ".node9");
|
|
76783
77077
|
return [
|
|
76784
|
-
|
|
76785
|
-
|
|
76786
|
-
|
|
77078
|
+
import_path79.default.join(node9Dir, "snapshots"),
|
|
77079
|
+
import_path79.default.join(node9Dir, "snapshots.json"),
|
|
77080
|
+
import_path79.default.join(node9Dir, "undo_latest.txt")
|
|
76787
77081
|
];
|
|
76788
77082
|
}
|
|
76789
|
-
function undoLeftoverPaths(homeDir2 =
|
|
77083
|
+
function undoLeftoverPaths(homeDir2 = import_os65.default.homedir()) {
|
|
76790
77084
|
const found = [];
|
|
76791
77085
|
for (const p of candidates(homeDir2)) {
|
|
76792
77086
|
try {
|
|
76793
|
-
|
|
77087
|
+
import_fs79.default.lstatSync(p);
|
|
76794
77088
|
found.push(p);
|
|
76795
77089
|
} catch (err2) {
|
|
76796
77090
|
if (err2.code !== "ENOENT") found.push(p);
|
|
@@ -76798,11 +77092,11 @@ function undoLeftoverPaths(homeDir2 = import_os64.default.homedir()) {
|
|
|
76798
77092
|
}
|
|
76799
77093
|
return found;
|
|
76800
77094
|
}
|
|
76801
|
-
function purgeUndoLeftovers(homeDir2 =
|
|
77095
|
+
function purgeUndoLeftovers(homeDir2 = import_os65.default.homedir()) {
|
|
76802
77096
|
const out = { deleted: [], skipped: [], failed: [] };
|
|
76803
77097
|
for (const p of undoLeftoverPaths(homeDir2)) {
|
|
76804
77098
|
try {
|
|
76805
|
-
if (
|
|
77099
|
+
if (import_fs79.default.lstatSync(p).isSymbolicLink()) {
|
|
76806
77100
|
out.skipped.push({
|
|
76807
77101
|
path: p,
|
|
76808
77102
|
reason: "is a symlink \u2014 remove it yourself so nothing else is followed"
|
|
@@ -76815,11 +77109,11 @@ function purgeUndoLeftovers(homeDir2 = import_os64.default.homedir()) {
|
|
|
76815
77109
|
}
|
|
76816
77110
|
let reason = null;
|
|
76817
77111
|
try {
|
|
76818
|
-
|
|
77112
|
+
import_fs79.default.rmSync(p, { recursive: true, force: true });
|
|
76819
77113
|
} catch (err2) {
|
|
76820
77114
|
reason = err2.message;
|
|
76821
77115
|
}
|
|
76822
|
-
if (
|
|
77116
|
+
if (import_fs79.default.existsSync(p)) {
|
|
76823
77117
|
out.failed.push({ path: p, reason: reason ?? "still present after removal" });
|
|
76824
77118
|
} else {
|
|
76825
77119
|
out.deleted.push(p);
|
|
@@ -76835,7 +77129,7 @@ function keyRejected(health) {
|
|
|
76835
77129
|
}
|
|
76836
77130
|
function registerDoctorCommand(program2, version2) {
|
|
76837
77131
|
program2.command("doctor").description("Check that Node9 is installed and configured correctly").action(async () => {
|
|
76838
|
-
const homeDir2 =
|
|
77132
|
+
const homeDir2 = import_os66.default.homedir();
|
|
76839
77133
|
let failures = 0;
|
|
76840
77134
|
let warnings = 0;
|
|
76841
77135
|
function pass(msg) {
|
|
@@ -76889,10 +77183,10 @@ function registerDoctorCommand(program2, version2) {
|
|
|
76889
77183
|
"Policy source: workspace config (app.node9.ai) \u2014 local config files govern operational settings only"
|
|
76890
77184
|
);
|
|
76891
77185
|
}
|
|
76892
|
-
const globalConfigPath2 =
|
|
76893
|
-
if (
|
|
77186
|
+
const globalConfigPath2 = import_path80.default.join(homeDir2, ".node9", "config.json");
|
|
77187
|
+
if (import_fs80.default.existsSync(globalConfigPath2)) {
|
|
76894
77188
|
try {
|
|
76895
|
-
JSON.parse(
|
|
77189
|
+
JSON.parse(import_fs80.default.readFileSync(globalConfigPath2, "utf-8"));
|
|
76896
77190
|
pass(
|
|
76897
77191
|
wsGoverned ? "~/.node9/config.json found and valid (policy fields ignored \u2014 workspace governs)" : "~/.node9/config.json found and valid"
|
|
76898
77192
|
);
|
|
@@ -76911,10 +77205,10 @@ function registerDoctorCommand(program2, version2) {
|
|
|
76911
77205
|
"Remove them when ready: node9 undo --purge"
|
|
76912
77206
|
);
|
|
76913
77207
|
}
|
|
76914
|
-
const projectConfigPath =
|
|
76915
|
-
if (
|
|
77208
|
+
const projectConfigPath = import_path80.default.join(process.cwd(), "node9.config.json");
|
|
77209
|
+
if (import_fs80.default.existsSync(projectConfigPath)) {
|
|
76916
77210
|
try {
|
|
76917
|
-
JSON.parse(
|
|
77211
|
+
JSON.parse(import_fs80.default.readFileSync(projectConfigPath, "utf-8"));
|
|
76918
77212
|
pass("node9.config.json found and valid (project)");
|
|
76919
77213
|
} catch {
|
|
76920
77214
|
fail2(
|
|
@@ -76923,8 +77217,8 @@ function registerDoctorCommand(program2, version2) {
|
|
|
76923
77217
|
);
|
|
76924
77218
|
}
|
|
76925
77219
|
}
|
|
76926
|
-
const credsPath =
|
|
76927
|
-
if (
|
|
77220
|
+
const credsPath = import_path80.default.join(homeDir2, ".node9", "credentials.json");
|
|
77221
|
+
if (import_fs80.default.existsSync(credsPath)) {
|
|
76928
77222
|
pass("Cloud credentials found (~/.node9/credentials.json)");
|
|
76929
77223
|
} else {
|
|
76930
77224
|
warn(
|
|
@@ -76978,7 +77272,7 @@ function registerDoctorCommand(program2, version2) {
|
|
|
76978
77272
|
)
|
|
76979
77273
|
);
|
|
76980
77274
|
}
|
|
76981
|
-
const cloudOn =
|
|
77275
|
+
const cloudOn = import_fs80.default.existsSync(import_path80.default.join(homeDir2, ".node9", "credentials.json")) && !!getConfig().settings.approvers?.cloud;
|
|
76982
77276
|
section(cloudOn ? "Daemon" : "Daemon (optional)");
|
|
76983
77277
|
if (isDaemonRunning()) {
|
|
76984
77278
|
pass(
|
|
@@ -77016,7 +77310,7 @@ function registerDoctorCommand(program2, version2) {
|
|
|
77016
77310
|
cloudEnabled: !!getConfig().settings.approvers?.cloud
|
|
77017
77311
|
});
|
|
77018
77312
|
if (autostart) warn(autostart.message, autostart.hint);
|
|
77019
|
-
if (
|
|
77313
|
+
if (import_fs80.default.existsSync(import_path80.default.join(import_os66.default.homedir(), ".node9", "credentials.json")) && getConfig().settings.approvers?.cloud) {
|
|
77020
77314
|
section("Policy sync");
|
|
77021
77315
|
const health = readSyncHealth();
|
|
77022
77316
|
if (keyRejected(health)) {
|
|
@@ -77042,7 +77336,7 @@ function registerDoctorCommand(program2, version2) {
|
|
|
77042
77336
|
try {
|
|
77043
77337
|
const { shipLagBytes: shipLagBytes2, readWatermark: readWatermark2, AUDIT_SHIP_WATERMARK: AUDIT_SHIP_WATERMARK2 } = await Promise.resolve().then(() => (init_audit_shipper(), audit_shipper_exports));
|
|
77044
77338
|
const cfg = getConfig();
|
|
77045
|
-
const creds =
|
|
77339
|
+
const creds = import_fs80.default.existsSync(import_path80.default.join(import_os66.default.homedir(), ".node9", "credentials.json"));
|
|
77046
77340
|
if (!creds) {
|
|
77047
77341
|
warn("Not logged in \u2014 audit rows stay local", "Run: node9 login <api-key>");
|
|
77048
77342
|
} else if (!cfg.settings.approvers.cloud) {
|
|
@@ -77108,10 +77402,10 @@ function registerDoctorCommand(program2, version2) {
|
|
|
77108
77402
|
// src/cli/commands/audit.ts
|
|
77109
77403
|
init_cjs_shims();
|
|
77110
77404
|
var import_chalk20 = __toESM(require("chalk"));
|
|
77111
|
-
var
|
|
77112
|
-
var
|
|
77405
|
+
var import_fs81 = __toESM(require("fs"));
|
|
77406
|
+
var import_path81 = __toESM(require("path"));
|
|
77113
77407
|
init_decision();
|
|
77114
|
-
var
|
|
77408
|
+
var import_os67 = __toESM(require("os"));
|
|
77115
77409
|
function formatRelativeTime(timestamp2) {
|
|
77116
77410
|
const diff = Date.now() - new Date(timestamp2).getTime();
|
|
77117
77411
|
const sec = Math.floor(diff / 1e3);
|
|
@@ -77124,14 +77418,14 @@ function formatRelativeTime(timestamp2) {
|
|
|
77124
77418
|
}
|
|
77125
77419
|
function registerAuditCommand(program2) {
|
|
77126
77420
|
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) => {
|
|
77127
|
-
const logPath =
|
|
77128
|
-
if (!
|
|
77421
|
+
const logPath = import_path81.default.join(import_os67.default.homedir(), ".node9", "audit.log");
|
|
77422
|
+
if (!import_fs81.default.existsSync(logPath)) {
|
|
77129
77423
|
console.log(
|
|
77130
77424
|
import_chalk20.default.yellow("No audit logs found. Run node9 with an agent to generate entries.")
|
|
77131
77425
|
);
|
|
77132
77426
|
return;
|
|
77133
77427
|
}
|
|
77134
|
-
const raw =
|
|
77428
|
+
const raw = import_fs81.default.readFileSync(logPath, "utf-8");
|
|
77135
77429
|
const lines = raw.split("\n").filter((l) => l.trim() !== "");
|
|
77136
77430
|
let entries = lines.flatMap((line) => {
|
|
77137
77431
|
try {
|
|
@@ -77194,7 +77488,7 @@ init_cjs_shims();
|
|
|
77194
77488
|
|
|
77195
77489
|
// src/apps/report.ts
|
|
77196
77490
|
init_cjs_shims();
|
|
77197
|
-
var
|
|
77491
|
+
var import_fs82 = __toESM(require("fs"));
|
|
77198
77492
|
init_catalog();
|
|
77199
77493
|
init_dist();
|
|
77200
77494
|
function appsReportLines(file2, activeShields, opts = {}) {
|
|
@@ -77224,17 +77518,17 @@ var AUDIT_TAIL_BYTES2 = 5 * 1024 * 1024;
|
|
|
77224
77518
|
function readTail2(file2) {
|
|
77225
77519
|
let fd;
|
|
77226
77520
|
try {
|
|
77227
|
-
fd =
|
|
77228
|
-
const size =
|
|
77521
|
+
fd = import_fs82.default.openSync(file2, "r");
|
|
77522
|
+
const size = import_fs82.default.fstatSync(fd).size;
|
|
77229
77523
|
const start = Math.max(0, size - AUDIT_TAIL_BYTES2);
|
|
77230
77524
|
const buf = Buffer.alloc(size - start);
|
|
77231
|
-
|
|
77525
|
+
import_fs82.default.readSync(fd, buf, 0, buf.length, start);
|
|
77232
77526
|
const text = buf.toString("utf8");
|
|
77233
77527
|
return start > 0 ? text.slice(text.indexOf("\n") + 1) : text;
|
|
77234
77528
|
} catch {
|
|
77235
77529
|
return "";
|
|
77236
77530
|
} finally {
|
|
77237
|
-
if (fd !== void 0)
|
|
77531
|
+
if (fd !== void 0) import_fs82.default.closeSync(fd);
|
|
77238
77532
|
}
|
|
77239
77533
|
}
|
|
77240
77534
|
function approvalsFromAudit(auditFile, sinceMs) {
|
|
@@ -77289,21 +77583,21 @@ init_detect();
|
|
|
77289
77583
|
|
|
77290
77584
|
// src/apps/nudges.ts
|
|
77291
77585
|
init_cjs_shims();
|
|
77292
|
-
var
|
|
77293
|
-
var
|
|
77294
|
-
var
|
|
77586
|
+
var import_fs83 = __toESM(require("fs"));
|
|
77587
|
+
var import_os68 = __toESM(require("os"));
|
|
77588
|
+
var import_path82 = __toESM(require("path"));
|
|
77295
77589
|
var import_child_process11 = require("child_process");
|
|
77296
77590
|
var UNANSWERED_AT = 3;
|
|
77297
77591
|
var QUESTIONS_AT = 10;
|
|
77298
77592
|
var TEAM_AUTHORS_AT = 2;
|
|
77299
77593
|
var TEAM_PROJECTS = 5;
|
|
77300
77594
|
var GIT_TIMEOUT_MS = 2e3;
|
|
77301
|
-
function nudgesFilePath(home =
|
|
77302
|
-
return
|
|
77595
|
+
function nudgesFilePath(home = import_os68.default.homedir()) {
|
|
77596
|
+
return import_path82.default.join(home, ".node9", "nudges.json");
|
|
77303
77597
|
}
|
|
77304
77598
|
function readShownNudges(home) {
|
|
77305
77599
|
try {
|
|
77306
|
-
const raw = JSON.parse(
|
|
77600
|
+
const raw = JSON.parse(import_fs83.default.readFileSync(nudgesFilePath(home), "utf8"));
|
|
77307
77601
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return /* @__PURE__ */ new Set();
|
|
77308
77602
|
return new Set(
|
|
77309
77603
|
Object.keys(raw).filter(
|
|
@@ -77318,14 +77612,14 @@ function markNudgeShown(key, home, now = /* @__PURE__ */ new Date()) {
|
|
|
77318
77612
|
const file2 = nudgesFilePath(home);
|
|
77319
77613
|
let data = {};
|
|
77320
77614
|
try {
|
|
77321
|
-
const raw = JSON.parse(
|
|
77615
|
+
const raw = JSON.parse(import_fs83.default.readFileSync(file2, "utf8"));
|
|
77322
77616
|
if (raw && typeof raw === "object" && !Array.isArray(raw)) data = raw;
|
|
77323
77617
|
} catch {
|
|
77324
77618
|
}
|
|
77325
77619
|
data[key] = now.toISOString();
|
|
77326
77620
|
try {
|
|
77327
|
-
|
|
77328
|
-
|
|
77621
|
+
import_fs83.default.mkdirSync(import_path82.default.dirname(file2), { recursive: true });
|
|
77622
|
+
import_fs83.default.writeFileSync(file2, JSON.stringify(data, null, 2) + "\n", { mode: 384 });
|
|
77329
77623
|
} catch {
|
|
77330
77624
|
}
|
|
77331
77625
|
}
|
|
@@ -77346,7 +77640,7 @@ function recentAuthorCount(dir2) {
|
|
|
77346
77640
|
}
|
|
77347
77641
|
function teamProject(dirs, countAuthors = recentAuthorCount) {
|
|
77348
77642
|
for (const dir2 of dirs.slice(0, TEAM_PROJECTS)) {
|
|
77349
|
-
if (countAuthors(dir2) >= TEAM_AUTHORS_AT) return
|
|
77643
|
+
if (countAuthors(dir2) >= TEAM_AUTHORS_AT) return import_path82.default.basename(dir2);
|
|
77350
77644
|
}
|
|
77351
77645
|
return void 0;
|
|
77352
77646
|
}
|
|
@@ -77381,9 +77675,9 @@ var import_chalk22 = __toESM(require("chalk"));
|
|
|
77381
77675
|
|
|
77382
77676
|
// src/cli/aggregate/report-audit.ts
|
|
77383
77677
|
init_cjs_shims();
|
|
77384
|
-
var
|
|
77385
|
-
var
|
|
77386
|
-
var
|
|
77678
|
+
var import_fs84 = __toESM(require("fs"));
|
|
77679
|
+
var import_os69 = __toESM(require("os"));
|
|
77680
|
+
var import_path83 = __toESM(require("path"));
|
|
77387
77681
|
init_costSync();
|
|
77388
77682
|
init_litellm();
|
|
77389
77683
|
init_cost_codex();
|
|
@@ -77468,8 +77762,8 @@ function getDateRange(period, now) {
|
|
|
77468
77762
|
}
|
|
77469
77763
|
}
|
|
77470
77764
|
function parseAuditLog(logPath) {
|
|
77471
|
-
if (!
|
|
77472
|
-
const raw =
|
|
77765
|
+
if (!import_fs84.default.existsSync(logPath)) return [];
|
|
77766
|
+
const raw = import_fs84.default.readFileSync(logPath, "utf-8");
|
|
77473
77767
|
return raw.split("\n").flatMap((line) => {
|
|
77474
77768
|
if (!line.trim()) return [];
|
|
77475
77769
|
try {
|
|
@@ -77523,10 +77817,10 @@ function freezeClaudeCost(acc) {
|
|
|
77523
77817
|
};
|
|
77524
77818
|
}
|
|
77525
77819
|
function processClaudeCostProject(proj, projectsDir, start, end, acc) {
|
|
77526
|
-
const projPath =
|
|
77820
|
+
const projPath = import_path83.default.join(projectsDir, proj);
|
|
77527
77821
|
let files;
|
|
77528
77822
|
try {
|
|
77529
|
-
const stat =
|
|
77823
|
+
const stat = import_fs84.default.statSync(projPath);
|
|
77530
77824
|
if (!stat.isDirectory()) return;
|
|
77531
77825
|
files = listSessionFiles(projPath);
|
|
77532
77826
|
} catch {
|
|
@@ -77534,14 +77828,14 @@ function processClaudeCostProject(proj, projectsDir, start, end, acc) {
|
|
|
77534
77828
|
}
|
|
77535
77829
|
const startMs = start.getTime();
|
|
77536
77830
|
for (const file2 of files) {
|
|
77537
|
-
const filePath =
|
|
77831
|
+
const filePath = import_path83.default.join(projPath, file2);
|
|
77538
77832
|
try {
|
|
77539
|
-
if (
|
|
77833
|
+
if (import_fs84.default.statSync(filePath).mtimeMs < startMs) continue;
|
|
77540
77834
|
} catch {
|
|
77541
77835
|
continue;
|
|
77542
77836
|
}
|
|
77543
77837
|
try {
|
|
77544
|
-
const raw =
|
|
77838
|
+
const raw = import_fs84.default.readFileSync(filePath, "utf-8");
|
|
77545
77839
|
for (const line of raw.split("\n")) {
|
|
77546
77840
|
if (!line.trim()) continue;
|
|
77547
77841
|
let entry;
|
|
@@ -77591,10 +77885,10 @@ function processClaudeCostProject(proj, projectsDir, start, end, acc) {
|
|
|
77591
77885
|
}
|
|
77592
77886
|
function loadClaudeCost(start, end, projectsDir) {
|
|
77593
77887
|
const acc = emptyClaudeCostAccumulator();
|
|
77594
|
-
if (!
|
|
77888
|
+
if (!import_fs84.default.existsSync(projectsDir)) return freezeClaudeCost(acc);
|
|
77595
77889
|
let dirs;
|
|
77596
77890
|
try {
|
|
77597
|
-
dirs =
|
|
77891
|
+
dirs = import_fs84.default.readdirSync(projectsDir);
|
|
77598
77892
|
} catch {
|
|
77599
77893
|
return freezeClaudeCost(acc);
|
|
77600
77894
|
}
|
|
@@ -77606,7 +77900,7 @@ function loadClaudeCost(start, end, projectsDir) {
|
|
|
77606
77900
|
function processCodexCostFile(filePath, start, end, acc) {
|
|
77607
77901
|
let lines;
|
|
77608
77902
|
try {
|
|
77609
|
-
lines =
|
|
77903
|
+
lines = import_fs84.default.readFileSync(filePath, "utf-8").split("\n");
|
|
77610
77904
|
} catch {
|
|
77611
77905
|
return;
|
|
77612
77906
|
}
|
|
@@ -77681,13 +77975,13 @@ function freezeGeminiCost(acc) {
|
|
|
77681
77975
|
function processGeminiCostFile(filePath, projectKey, start, end, acc) {
|
|
77682
77976
|
const startMs = start.getTime();
|
|
77683
77977
|
try {
|
|
77684
|
-
if (
|
|
77978
|
+
if (import_fs84.default.statSync(filePath).mtimeMs < startMs) return;
|
|
77685
77979
|
} catch {
|
|
77686
77980
|
return;
|
|
77687
77981
|
}
|
|
77688
77982
|
let raw;
|
|
77689
77983
|
try {
|
|
77690
|
-
raw =
|
|
77984
|
+
raw = import_fs84.default.readFileSync(filePath, "utf-8");
|
|
77691
77985
|
} catch {
|
|
77692
77986
|
return;
|
|
77693
77987
|
}
|
|
@@ -77736,30 +78030,30 @@ function listGeminiSessionFiles2(geminiTmpDir2) {
|
|
|
77736
78030
|
const out = [];
|
|
77737
78031
|
let dirs;
|
|
77738
78032
|
try {
|
|
77739
|
-
if (!
|
|
77740
|
-
dirs =
|
|
78033
|
+
if (!import_fs84.default.statSync(geminiTmpDir2).isDirectory()) return out;
|
|
78034
|
+
dirs = import_fs84.default.readdirSync(geminiTmpDir2);
|
|
77741
78035
|
} catch {
|
|
77742
78036
|
return out;
|
|
77743
78037
|
}
|
|
77744
78038
|
for (const proj of dirs) {
|
|
77745
|
-
const chatsDir =
|
|
78039
|
+
const chatsDir = import_path83.default.join(geminiTmpDir2, proj, "chats");
|
|
77746
78040
|
let files;
|
|
77747
78041
|
try {
|
|
77748
|
-
if (!
|
|
77749
|
-
files =
|
|
78042
|
+
if (!import_fs84.default.statSync(chatsDir).isDirectory()) continue;
|
|
78043
|
+
files = import_fs84.default.readdirSync(chatsDir);
|
|
77750
78044
|
} catch {
|
|
77751
78045
|
continue;
|
|
77752
78046
|
}
|
|
77753
78047
|
for (const f of files) {
|
|
77754
78048
|
if (!f.endsWith(".jsonl")) continue;
|
|
77755
|
-
out.push({ projectKey: proj, file:
|
|
78049
|
+
out.push({ projectKey: proj, file: import_path83.default.join(chatsDir, f) });
|
|
77756
78050
|
}
|
|
77757
78051
|
}
|
|
77758
78052
|
return out;
|
|
77759
78053
|
}
|
|
77760
78054
|
function loadGeminiCost(start, end, geminiTmpDir2) {
|
|
77761
78055
|
const acc = emptyGeminiAccumulator();
|
|
77762
|
-
if (!
|
|
78056
|
+
if (!import_fs84.default.existsSync(geminiTmpDir2)) return freezeGeminiCost(acc);
|
|
77763
78057
|
for (const { projectKey, file: file2 } of listGeminiSessionFiles2(geminiTmpDir2)) {
|
|
77764
78058
|
processGeminiCostFile(file2, projectKey, start, end, acc);
|
|
77765
78059
|
}
|
|
@@ -77780,11 +78074,11 @@ function dimensionOfBlock(checkedBy, ruleName) {
|
|
|
77780
78074
|
}
|
|
77781
78075
|
function aggregateReportFromAudit(period, opts = {}) {
|
|
77782
78076
|
const now = opts.now ?? /* @__PURE__ */ new Date();
|
|
77783
|
-
const auditLogPath = opts.auditLogPath ??
|
|
77784
|
-
const claudeProjectsDir = opts.claudeProjectsDir ??
|
|
78077
|
+
const auditLogPath = opts.auditLogPath ?? import_path83.default.join(import_os69.default.homedir(), ".node9", "audit.log");
|
|
78078
|
+
const claudeProjectsDir = opts.claudeProjectsDir ?? import_path83.default.join(import_os69.default.homedir(), ".claude", "projects");
|
|
77785
78079
|
const codexSessionsDir2 = opts.codexSessionsDir ?? codexSessionsDir();
|
|
77786
|
-
const geminiTmpDir2 = opts.geminiTmpDir ??
|
|
77787
|
-
const hasAuditFile =
|
|
78080
|
+
const geminiTmpDir2 = opts.geminiTmpDir ?? import_path83.default.join(import_os69.default.homedir(), ".gemini", "tmp");
|
|
78081
|
+
const hasAuditFile = import_fs84.default.existsSync(auditLogPath);
|
|
77788
78082
|
const allEntries = opts.preloadedAuditEntries ?? parseAuditLog(auditLogPath);
|
|
77789
78083
|
const unackedDlp = allEntries.filter((e) => e.source === "response-dlp");
|
|
77790
78084
|
const { start, end } = getDateRange(period, now);
|
|
@@ -78070,10 +78364,10 @@ function buildReportJson(input) {
|
|
|
78070
78364
|
// src/cli/commands/sessions.ts
|
|
78071
78365
|
init_cjs_shims();
|
|
78072
78366
|
var import_chalk21 = __toESM(require("chalk"));
|
|
78073
|
-
var
|
|
78074
|
-
var
|
|
78367
|
+
var import_fs85 = __toESM(require("fs"));
|
|
78368
|
+
var import_path84 = __toESM(require("path"));
|
|
78075
78369
|
init_decision();
|
|
78076
|
-
var
|
|
78370
|
+
var import_os70 = __toESM(require("os"));
|
|
78077
78371
|
init_scan_summary();
|
|
78078
78372
|
init_litellm();
|
|
78079
78373
|
init_cost_gemini();
|
|
@@ -78094,10 +78388,10 @@ function encodeProjectPath(projectPath) {
|
|
|
78094
78388
|
}
|
|
78095
78389
|
function sessionJsonlPath(projectPath, sessionId) {
|
|
78096
78390
|
const encoded = encodeProjectPath(projectPath);
|
|
78097
|
-
return
|
|
78391
|
+
return import_path84.default.join(import_os70.default.homedir(), ".claude", "projects", encoded, `${sessionId}.jsonl`);
|
|
78098
78392
|
}
|
|
78099
78393
|
function projectLabel(projectPath) {
|
|
78100
|
-
return projectPath.replace(
|
|
78394
|
+
return projectPath.replace(import_os70.default.homedir(), "~");
|
|
78101
78395
|
}
|
|
78102
78396
|
function parseHistoryLines(lines) {
|
|
78103
78397
|
const entries = [];
|
|
@@ -78166,10 +78460,10 @@ function parseSessionLines(lines) {
|
|
|
78166
78460
|
return { toolCalls, costUSD, hasSnapshot, modifiedFiles };
|
|
78167
78461
|
}
|
|
78168
78462
|
function loadAuditEntries(auditPath) {
|
|
78169
|
-
const aPath = auditPath ??
|
|
78463
|
+
const aPath = auditPath ?? import_path84.default.join(import_os70.default.homedir(), ".node9", "audit.log");
|
|
78170
78464
|
let raw;
|
|
78171
78465
|
try {
|
|
78172
|
-
raw =
|
|
78466
|
+
raw = import_fs85.default.readFileSync(aPath, "utf-8");
|
|
78173
78467
|
} catch {
|
|
78174
78468
|
return [];
|
|
78175
78469
|
}
|
|
@@ -78205,8 +78499,8 @@ function auditEntriesInWindow(entries, windowStart, windowEnd) {
|
|
|
78205
78499
|
return result;
|
|
78206
78500
|
}
|
|
78207
78501
|
function buildGeminiSessions(days, allAuditEntries) {
|
|
78208
|
-
const tmpDir =
|
|
78209
|
-
if (!
|
|
78502
|
+
const tmpDir = import_path84.default.join(import_os70.default.homedir(), ".gemini", "tmp");
|
|
78503
|
+
if (!import_fs85.default.existsSync(tmpDir)) return [];
|
|
78210
78504
|
const cutoff = days !== null ? (() => {
|
|
78211
78505
|
const d = /* @__PURE__ */ new Date();
|
|
78212
78506
|
d.setDate(d.getDate() - days);
|
|
@@ -78215,35 +78509,35 @@ function buildGeminiSessions(days, allAuditEntries) {
|
|
|
78215
78509
|
})() : null;
|
|
78216
78510
|
let slugDirs;
|
|
78217
78511
|
try {
|
|
78218
|
-
slugDirs =
|
|
78512
|
+
slugDirs = import_fs85.default.readdirSync(tmpDir);
|
|
78219
78513
|
} catch {
|
|
78220
78514
|
return [];
|
|
78221
78515
|
}
|
|
78222
78516
|
const summaries = [];
|
|
78223
78517
|
for (const slug2 of slugDirs) {
|
|
78224
|
-
const slugPath =
|
|
78518
|
+
const slugPath = import_path84.default.join(tmpDir, slug2);
|
|
78225
78519
|
try {
|
|
78226
|
-
if (!
|
|
78520
|
+
if (!import_fs85.default.statSync(slugPath).isDirectory()) continue;
|
|
78227
78521
|
} catch {
|
|
78228
78522
|
continue;
|
|
78229
78523
|
}
|
|
78230
|
-
let projectRoot =
|
|
78524
|
+
let projectRoot = import_path84.default.join(import_os70.default.homedir(), slug2);
|
|
78231
78525
|
try {
|
|
78232
|
-
projectRoot =
|
|
78526
|
+
projectRoot = import_fs85.default.readFileSync(import_path84.default.join(slugPath, ".project_root"), "utf-8").trim();
|
|
78233
78527
|
} catch {
|
|
78234
78528
|
}
|
|
78235
|
-
const chatsDir =
|
|
78236
|
-
if (!
|
|
78529
|
+
const chatsDir = import_path84.default.join(slugPath, "chats");
|
|
78530
|
+
if (!import_fs85.default.existsSync(chatsDir)) continue;
|
|
78237
78531
|
let chatFiles;
|
|
78238
78532
|
try {
|
|
78239
|
-
chatFiles =
|
|
78533
|
+
chatFiles = import_fs85.default.readdirSync(chatsDir).filter((f) => f.endsWith(".json"));
|
|
78240
78534
|
} catch {
|
|
78241
78535
|
continue;
|
|
78242
78536
|
}
|
|
78243
78537
|
for (const chatFile of chatFiles) {
|
|
78244
78538
|
let raw;
|
|
78245
78539
|
try {
|
|
78246
|
-
raw =
|
|
78540
|
+
raw = import_fs85.default.readFileSync(import_path84.default.join(chatsDir, chatFile), "utf-8");
|
|
78247
78541
|
} catch {
|
|
78248
78542
|
continue;
|
|
78249
78543
|
}
|
|
@@ -78334,7 +78628,7 @@ function buildCodexSessions(days, allAuditEntries) {
|
|
|
78334
78628
|
for (const filePath of jsonlFiles) {
|
|
78335
78629
|
let lines;
|
|
78336
78630
|
try {
|
|
78337
|
-
lines =
|
|
78631
|
+
lines = import_fs85.default.readFileSync(filePath, "utf-8").split("\n");
|
|
78338
78632
|
} catch {
|
|
78339
78633
|
continue;
|
|
78340
78634
|
}
|
|
@@ -78405,10 +78699,10 @@ function buildCodexSessions(days, allAuditEntries) {
|
|
|
78405
78699
|
return summaries;
|
|
78406
78700
|
}
|
|
78407
78701
|
function buildSessions(days, historyPath) {
|
|
78408
|
-
const hPath = historyPath ??
|
|
78702
|
+
const hPath = historyPath ?? import_path84.default.join(import_os70.default.homedir(), ".claude", "history.jsonl");
|
|
78409
78703
|
let historyRaw = "";
|
|
78410
78704
|
try {
|
|
78411
|
-
historyRaw =
|
|
78705
|
+
historyRaw = import_fs85.default.readFileSync(hPath, "utf-8");
|
|
78412
78706
|
} catch {
|
|
78413
78707
|
}
|
|
78414
78708
|
const cutoff = days !== null ? (() => {
|
|
@@ -78432,7 +78726,7 @@ function buildSessions(days, historyPath) {
|
|
|
78432
78726
|
const jsonlFile = sessionJsonlPath(entry.project, entry.sessionId);
|
|
78433
78727
|
let sessionLines = [];
|
|
78434
78728
|
try {
|
|
78435
|
-
sessionLines =
|
|
78729
|
+
sessionLines = import_fs85.default.readFileSync(jsonlFile, "utf-8").split("\n");
|
|
78436
78730
|
} catch {
|
|
78437
78731
|
}
|
|
78438
78732
|
const { toolCalls, costUSD, hasSnapshot, modifiedFiles } = parseSessionLines(sessionLines);
|
|
@@ -79223,7 +79517,7 @@ init_cjs_shims();
|
|
|
79223
79517
|
var import_chalk23 = __toESM(require("chalk"));
|
|
79224
79518
|
var import_child_process12 = require("child_process");
|
|
79225
79519
|
init_daemon();
|
|
79226
|
-
var
|
|
79520
|
+
var import_fs86 = __toESM(require("fs"));
|
|
79227
79521
|
init_startup_log();
|
|
79228
79522
|
init_daemon3();
|
|
79229
79523
|
init_service();
|
|
@@ -79300,7 +79594,7 @@ function registerDaemonCommand(program2) {
|
|
|
79300
79594
|
child.unref();
|
|
79301
79595
|
if (restartFd !== void 0) {
|
|
79302
79596
|
try {
|
|
79303
|
-
|
|
79597
|
+
import_fs86.default.closeSync(restartFd);
|
|
79304
79598
|
} catch {
|
|
79305
79599
|
}
|
|
79306
79600
|
}
|
|
@@ -79351,7 +79645,7 @@ function registerDaemonCommand(program2) {
|
|
|
79351
79645
|
} finally {
|
|
79352
79646
|
if (startupFd !== void 0) {
|
|
79353
79647
|
try {
|
|
79354
|
-
|
|
79648
|
+
import_fs86.default.closeSync(startupFd);
|
|
79355
79649
|
} catch {
|
|
79356
79650
|
}
|
|
79357
79651
|
}
|
|
@@ -79366,9 +79660,9 @@ function registerDaemonCommand(program2) {
|
|
|
79366
79660
|
// src/cli/commands/status.ts
|
|
79367
79661
|
init_cjs_shims();
|
|
79368
79662
|
var import_chalk24 = __toESM(require("chalk"));
|
|
79369
|
-
var
|
|
79370
|
-
var
|
|
79371
|
-
var
|
|
79663
|
+
var import_fs87 = __toESM(require("fs"));
|
|
79664
|
+
var import_path85 = __toESM(require("path"));
|
|
79665
|
+
var import_os71 = __toESM(require("os"));
|
|
79372
79666
|
init_core();
|
|
79373
79667
|
init_daemon();
|
|
79374
79668
|
init_build_id();
|
|
@@ -79469,20 +79763,20 @@ function registerStatusCommand(program2) {
|
|
|
79469
79763
|
console.log(` Policy: ${import_chalk24.default.cyan("Workspace config (app.node9.ai)")}`);
|
|
79470
79764
|
}
|
|
79471
79765
|
const ignoredLabel = import_chalk24.default.gray("Present \u2014 ignored (workspace config governs)");
|
|
79472
|
-
const projectConfig =
|
|
79473
|
-
const globalConfig =
|
|
79766
|
+
const projectConfig = import_path85.default.join(process.cwd(), "node9.config.json");
|
|
79767
|
+
const globalConfig = import_path85.default.join(import_os71.default.homedir(), ".node9", "config.json");
|
|
79474
79768
|
console.log(
|
|
79475
|
-
` Local: ${
|
|
79769
|
+
` Local: ${import_fs87.default.existsSync(projectConfig) ? wsGoverned ? ignoredLabel : import_chalk24.default.green("Active (node9.config.json)") : import_chalk24.default.gray("Not present")}`
|
|
79476
79770
|
);
|
|
79477
79771
|
console.log(
|
|
79478
|
-
` Global: ${
|
|
79772
|
+
` Global: ${import_fs87.default.existsSync(globalConfig) ? wsGoverned ? ignoredLabel : import_chalk24.default.green("Active (~/.node9/config.json)") : import_chalk24.default.gray("Not present")}`
|
|
79479
79773
|
);
|
|
79480
79774
|
if (mergedConfig.policy.sandboxPaths.length > 0) {
|
|
79481
79775
|
console.log(
|
|
79482
79776
|
` Sandbox: ${import_chalk24.default.green(`${mergedConfig.policy.sandboxPaths.length} safe zones active`)}`
|
|
79483
79777
|
);
|
|
79484
79778
|
}
|
|
79485
|
-
const wiring = getAgentWiring(
|
|
79779
|
+
const wiring = getAgentWiring(import_os71.default.homedir()).filter((a) => a.present);
|
|
79486
79780
|
if (wiring.length > 0) {
|
|
79487
79781
|
console.log("");
|
|
79488
79782
|
console.log(import_chalk24.default.bold(" Agent Wiring:"));
|
|
@@ -79501,7 +79795,7 @@ function registerStatusCommand(program2) {
|
|
|
79501
79795
|
a.mcpServers
|
|
79502
79796
|
);
|
|
79503
79797
|
if (a.id === "codex" && a.hooks.some((h) => h.wired)) {
|
|
79504
|
-
const t = assessCodexTrust(
|
|
79798
|
+
const t = assessCodexTrust(import_os71.default.homedir());
|
|
79505
79799
|
if (t.state === "observed") {
|
|
79506
79800
|
console.log(
|
|
79507
79801
|
import_chalk24.default.green(
|
|
@@ -79545,7 +79839,7 @@ init_init();
|
|
|
79545
79839
|
// src/cli/commands/heal.ts
|
|
79546
79840
|
init_cjs_shims();
|
|
79547
79841
|
var import_chalk25 = __toESM(require("chalk"));
|
|
79548
|
-
var
|
|
79842
|
+
var import_fs90 = __toESM(require("fs"));
|
|
79549
79843
|
init_agent_wiring();
|
|
79550
79844
|
init_mcp_wrap();
|
|
79551
79845
|
init_setup();
|
|
@@ -79553,7 +79847,7 @@ init_hook_baseline();
|
|
|
79553
79847
|
var hasHookSurface = (a) => a.hooks.length > 0;
|
|
79554
79848
|
function backupForHeal(file2) {
|
|
79555
79849
|
try {
|
|
79556
|
-
if (file2 &&
|
|
79850
|
+
if (file2 && import_fs90.default.existsSync(file2)) import_fs90.default.copyFileSync(file2, `${file2}.node9-heal-bak`);
|
|
79557
79851
|
} catch {
|
|
79558
79852
|
}
|
|
79559
79853
|
}
|
|
@@ -80174,7 +80468,12 @@ async function runMcpGateway(upstreamCommand, configName) {
|
|
|
80174
80468
|
humanDecision,
|
|
80175
80469
|
result.reason,
|
|
80176
80470
|
void 0,
|
|
80177
|
-
{
|
|
80471
|
+
{
|
|
80472
|
+
kind: result.blockKind,
|
|
80473
|
+
path: result.blockedPath,
|
|
80474
|
+
redirect: !!result.redirect,
|
|
80475
|
+
ruleDescription: result.ruleDescription
|
|
80476
|
+
}
|
|
80178
80477
|
);
|
|
80179
80478
|
const errorResponse = {
|
|
80180
80479
|
jsonrpc: "2.0",
|
|
@@ -80518,9 +80817,9 @@ init_cjs_shims();
|
|
|
80518
80817
|
init_cjs_shims();
|
|
80519
80818
|
var import_readline4 = __toESM(require("readline"));
|
|
80520
80819
|
init_write();
|
|
80521
|
-
var
|
|
80522
|
-
var
|
|
80523
|
-
var
|
|
80820
|
+
var import_fs91 = __toESM(require("fs"));
|
|
80821
|
+
var import_os76 = __toESM(require("os"));
|
|
80822
|
+
var import_path90 = __toESM(require("path"));
|
|
80524
80823
|
var import_child_process14 = require("child_process");
|
|
80525
80824
|
init_decision();
|
|
80526
80825
|
init_core();
|
|
@@ -81071,14 +81370,14 @@ function handleStatus() {
|
|
|
81071
81370
|
const state = !a.installed ? "not installed" : hooked ? "wired" : a.isProtected ? "protected through MCP" : "not wired";
|
|
81072
81371
|
lines.push(` ${a.label}: ${state}`);
|
|
81073
81372
|
}
|
|
81074
|
-
const projectConfig =
|
|
81075
|
-
const globalConfig =
|
|
81373
|
+
const projectConfig = import_path90.default.join(process.cwd(), "node9.config.json");
|
|
81374
|
+
const globalConfig = import_path90.default.join(import_os76.default.homedir(), ".node9", "config.json");
|
|
81076
81375
|
const presentLabel = wsGoverned ? "present \u2014 ignored (workspace config governs)" : "present";
|
|
81077
81376
|
lines.push(
|
|
81078
|
-
`Project config (node9.config.json): ${
|
|
81377
|
+
`Project config (node9.config.json): ${import_fs91.default.existsSync(projectConfig) ? presentLabel : "not found"}`
|
|
81079
81378
|
);
|
|
81080
81379
|
lines.push(
|
|
81081
|
-
`Global config (~/.node9/config.json): ${
|
|
81380
|
+
`Global config (~/.node9/config.json): ${import_fs91.default.existsSync(globalConfig) ? presentLabel : "not found"}`
|
|
81082
81381
|
);
|
|
81083
81382
|
return lines.join("\n");
|
|
81084
81383
|
}
|
|
@@ -81215,7 +81514,7 @@ function handleEgressDeny(args) {
|
|
|
81215
81514
|
addEgressHost("deny", host2);
|
|
81216
81515
|
return `Denied egress to ${host2} (deny always wins over allow).`;
|
|
81217
81516
|
}
|
|
81218
|
-
var GLOBAL_CONFIG_PATH2 =
|
|
81517
|
+
var GLOBAL_CONFIG_PATH2 = import_path90.default.join(import_os76.default.homedir(), ".node9", "config.json");
|
|
81219
81518
|
var APPROVER_CHANNELS2 = ["native", "browser", "cloud", "terminal"];
|
|
81220
81519
|
function handleApproverList() {
|
|
81221
81520
|
const config = getConfig();
|
|
@@ -81256,9 +81555,9 @@ function handleApproverSet(args) {
|
|
|
81256
81555
|
function handleAuditGet(args) {
|
|
81257
81556
|
const limit = Math.min(typeof args.limit === "number" ? args.limit : 20, 100);
|
|
81258
81557
|
const filter = typeof args.filter === "string" && args.filter !== "all" ? args.filter : null;
|
|
81259
|
-
const auditPath =
|
|
81260
|
-
if (!
|
|
81261
|
-
const rawLines =
|
|
81558
|
+
const auditPath = import_path90.default.join(import_os76.default.homedir(), ".node9", "audit.log");
|
|
81559
|
+
if (!import_fs91.default.existsSync(auditPath)) return "No audit log found.";
|
|
81560
|
+
const rawLines = import_fs91.default.readFileSync(auditPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
81262
81561
|
const wanted = filter === "block" ? "deny" : filter;
|
|
81263
81562
|
const parsed = [];
|
|
81264
81563
|
for (const line of rawLines) {
|
|
@@ -81618,7 +81917,7 @@ function registerTrustCommand(program2) {
|
|
|
81618
81917
|
init_cjs_shims();
|
|
81619
81918
|
var import_chalk32 = __toESM(require("chalk"));
|
|
81620
81919
|
init_mcp_pin();
|
|
81621
|
-
var
|
|
81920
|
+
var import_fs92 = __toESM(require("fs"));
|
|
81622
81921
|
|
|
81623
81922
|
// src/cli/commands/mcp-gateway-cmd.ts
|
|
81624
81923
|
init_cjs_shims();
|
|
@@ -81827,7 +82126,7 @@ function registerMcpPinCommand(program2) {
|
|
|
81827
82126
|
let repoCorrupt = false;
|
|
81828
82127
|
if (found.source === "repo") {
|
|
81829
82128
|
try {
|
|
81830
|
-
const raw =
|
|
82129
|
+
const raw = import_fs92.default.readFileSync(found.path, "utf-8");
|
|
81831
82130
|
const parsed = JSON.parse(raw);
|
|
81832
82131
|
repoEntries = parsed.servers ?? {};
|
|
81833
82132
|
} catch {
|
|
@@ -82279,8 +82578,8 @@ init_cjs_shims();
|
|
|
82279
82578
|
|
|
82280
82579
|
// src/ci-check/fetch.ts
|
|
82281
82580
|
init_cjs_shims();
|
|
82282
|
-
var
|
|
82283
|
-
var
|
|
82581
|
+
var import_fs93 = __toESM(require("fs"));
|
|
82582
|
+
var import_path91 = __toESM(require("path"));
|
|
82284
82583
|
var import_node_child_process = require("child_process");
|
|
82285
82584
|
var import_undici = __toESM(require_undici());
|
|
82286
82585
|
|
|
@@ -82480,8 +82779,8 @@ function isOfficialInstaller(u) {
|
|
|
82480
82779
|
if (u.username || u.password) return false;
|
|
82481
82780
|
const host2 = u.hostname.toLowerCase().replace(/^www\./, "");
|
|
82482
82781
|
if (OFFICIAL_HOSTS.has(host2)) return true;
|
|
82483
|
-
const
|
|
82484
|
-
return !!
|
|
82782
|
+
const path110 = OFFICIAL_PATHS[host2];
|
|
82783
|
+
return !!path110 && path110.test(u.pathname);
|
|
82485
82784
|
}
|
|
82486
82785
|
function onlyOfficialInstaller(s) {
|
|
82487
82786
|
const urls = s.match(URL_RE3);
|
|
@@ -82672,21 +82971,21 @@ function appSkillDirsOf(paths, skillDirs) {
|
|
|
82672
82971
|
}
|
|
82673
82972
|
return apps;
|
|
82674
82973
|
}
|
|
82675
|
-
function isSkillSupportFile(
|
|
82676
|
-
if (!
|
|
82677
|
-
for (let d =
|
|
82678
|
-
const dir2 =
|
|
82974
|
+
function isSkillSupportFile(path110, skillDirs, appDirs) {
|
|
82975
|
+
if (!path110.endsWith(".md") || /(^|\/)[Ss][Kk][Ii][Ll][Ll]\.md$/.test(path110)) return false;
|
|
82976
|
+
for (let d = path110.lastIndexOf("/"); d > 0; d = path110.lastIndexOf("/", d - 1)) {
|
|
82977
|
+
const dir2 = path110.slice(0, d);
|
|
82679
82978
|
if (!skillDirs.has(dir2)) continue;
|
|
82680
|
-
return !appDirs?.has(dir2) || SKILL_LAYOUT_RE.test(
|
|
82979
|
+
return !appDirs?.has(dir2) || SKILL_LAYOUT_RE.test(path110.slice(d + 1));
|
|
82681
82980
|
}
|
|
82682
82981
|
return false;
|
|
82683
82982
|
}
|
|
82684
|
-
function isAppDoc(
|
|
82685
|
-
if (!
|
|
82686
|
-
for (let d =
|
|
82687
|
-
const dir2 =
|
|
82983
|
+
function isAppDoc(path110, skillDirs, appDirs) {
|
|
82984
|
+
if (!path110.endsWith(".md") || INSTRUCTION_FILE_RE.test(path110)) return false;
|
|
82985
|
+
for (let d = path110.lastIndexOf("/"); d > 0; d = path110.lastIndexOf("/", d - 1)) {
|
|
82986
|
+
const dir2 = path110.slice(0, d);
|
|
82688
82987
|
if (!skillDirs.has(dir2)) continue;
|
|
82689
|
-
return appDirs.has(dir2) && !SKILL_LAYOUT_RE.test(
|
|
82988
|
+
return appDirs.has(dir2) && !SKILL_LAYOUT_RE.test(path110.slice(d + 1));
|
|
82690
82989
|
}
|
|
82691
82990
|
return false;
|
|
82692
82991
|
}
|
|
@@ -82709,20 +83008,20 @@ function namedDocs(dir2, skillMd) {
|
|
|
82709
83008
|
return out;
|
|
82710
83009
|
}
|
|
82711
83010
|
var SCRIPT_EXT_RE = /\.(sh|bash|zsh|py|js|mjs|cjs|ts|rb|pl|ps1)$/i;
|
|
82712
|
-
function isHookScript(
|
|
82713
|
-
return /(^|\/)\.claude\/hooks\/.+/.test(
|
|
82714
|
-
}
|
|
82715
|
-
function isSkillScript(
|
|
82716
|
-
if (!SCRIPT_EXT_RE.test(
|
|
82717
|
-
for (let d =
|
|
82718
|
-
if (!skillDirs.has(
|
|
82719
|
-
const rel =
|
|
83011
|
+
function isHookScript(path110) {
|
|
83012
|
+
return /(^|\/)\.claude\/hooks\/.+/.test(path110) && SCRIPT_EXT_RE.test(path110);
|
|
83013
|
+
}
|
|
83014
|
+
function isSkillScript(path110, skillDirs) {
|
|
83015
|
+
if (!SCRIPT_EXT_RE.test(path110)) return false;
|
|
83016
|
+
for (let d = path110.lastIndexOf("/"); d > 0; d = path110.lastIndexOf("/", d - 1)) {
|
|
83017
|
+
if (!skillDirs.has(path110.slice(0, d))) continue;
|
|
83018
|
+
const rel = path110.slice(d + 1);
|
|
82720
83019
|
return !rel.includes("/") || /^(scripts|bin)\//.test(rel);
|
|
82721
83020
|
}
|
|
82722
83021
|
return false;
|
|
82723
83022
|
}
|
|
82724
|
-
function isInstructionFile(
|
|
82725
|
-
return INSTRUCTION_FILE_RE.test(
|
|
83023
|
+
function isInstructionFile(path110, skillDirs, appDirs) {
|
|
83024
|
+
return INSTRUCTION_FILE_RE.test(path110) || isSkillSupportFile(path110, skillDirs, appDirs);
|
|
82726
83025
|
}
|
|
82727
83026
|
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;
|
|
82728
83027
|
var FETCH_WORD_RE = /\b(curl|wget|iwr|invoke-webrequest)\b/gi;
|
|
@@ -82859,21 +83158,21 @@ function decodeSuspiciousBase64(text) {
|
|
|
82859
83158
|
}
|
|
82860
83159
|
return out;
|
|
82861
83160
|
}
|
|
82862
|
-
function mk2(rule, severity, title, signals, fix,
|
|
83161
|
+
function mk2(rule, severity, title, signals, fix, path110, line) {
|
|
82863
83162
|
return {
|
|
82864
83163
|
check: "CI-6",
|
|
82865
83164
|
rule,
|
|
82866
83165
|
dimension: "instructions",
|
|
82867
83166
|
severity,
|
|
82868
83167
|
title,
|
|
82869
|
-
file:
|
|
83168
|
+
file: path110,
|
|
82870
83169
|
...line ? { line } : {},
|
|
82871
83170
|
signals,
|
|
82872
83171
|
fix
|
|
82873
83172
|
};
|
|
82874
83173
|
}
|
|
82875
83174
|
var lineAt = (text, i) => i >= 0 ? lineAtIndex(text, i) : void 0;
|
|
82876
|
-
function analyzeInstructionFile(
|
|
83175
|
+
function analyzeInstructionFile(path110, content) {
|
|
82877
83176
|
const findings = [];
|
|
82878
83177
|
const decoded = decodeSuspiciousBase64(content);
|
|
82879
83178
|
const glyph = homoglyphWord(content);
|
|
@@ -82887,7 +83186,7 @@ function analyzeInstructionFile(path108, content) {
|
|
|
82887
83186
|
`\`${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`
|
|
82888
83187
|
],
|
|
82889
83188
|
"Spell the word with plain Latin letters, or explain on the same line why the look-alikes are there.",
|
|
82890
|
-
|
|
83189
|
+
path110,
|
|
82891
83190
|
glyph.line
|
|
82892
83191
|
)
|
|
82893
83192
|
);
|
|
@@ -82901,7 +83200,7 @@ function analyzeInstructionFile(path108, content) {
|
|
|
82901
83200
|
"contains Unicode tag characters (U+E0000\u2013E007F): an invisible instruction-smuggling channel with no legitimate use in text"
|
|
82902
83201
|
],
|
|
82903
83202
|
"Remove the tag characters. Instruction files must be plain, reviewable text.",
|
|
82904
|
-
|
|
83203
|
+
path110,
|
|
82905
83204
|
lineAt(content, content.search(TAG_CHARS))
|
|
82906
83205
|
)
|
|
82907
83206
|
);
|
|
@@ -82915,7 +83214,7 @@ function analyzeInstructionFile(path108, content) {
|
|
|
82915
83214
|
"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"
|
|
82916
83215
|
],
|
|
82917
83216
|
"Remove the bidi override characters.",
|
|
82918
|
-
|
|
83217
|
+
path110,
|
|
82919
83218
|
lineAt(content, content.search(BIDI_OVERRIDE))
|
|
82920
83219
|
)
|
|
82921
83220
|
);
|
|
@@ -82929,7 +83228,7 @@ function analyzeInstructionFile(path108, content) {
|
|
|
82929
83228
|
"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"
|
|
82930
83229
|
],
|
|
82931
83230
|
"Confirm the bidi marks are legitimate RTL formatting; remove otherwise.",
|
|
82932
|
-
|
|
83231
|
+
path110,
|
|
82933
83232
|
lineAt(content, content.search(BIDI_EMBED_ISOLATE))
|
|
82934
83233
|
)
|
|
82935
83234
|
);
|
|
@@ -82945,7 +83244,7 @@ function analyzeInstructionFile(path108, content) {
|
|
|
82945
83244
|
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)"
|
|
82946
83245
|
],
|
|
82947
83246
|
"Remove the zero-width characters. Instruction files must be plain, reviewable text.",
|
|
82948
|
-
|
|
83247
|
+
path110,
|
|
82949
83248
|
lineAt(content, zw.first)
|
|
82950
83249
|
)
|
|
82951
83250
|
);
|
|
@@ -82964,7 +83263,7 @@ function analyzeInstructionFile(path108, content) {
|
|
|
82964
83263
|
`contains a prompt-override / role-impersonation directive (\`${safeText(m[0].slice(0, 60).trim(), 60)}\`)${ovEnc ? ", concealed in a base64 blob" : ""}`
|
|
82965
83264
|
],
|
|
82966
83265
|
"Remove the override text. An instruction file should not tell the agent to ignore its own rules.",
|
|
82967
|
-
|
|
83266
|
+
path110,
|
|
82968
83267
|
ov ? lineAt(content, ov.index) : void 0
|
|
82969
83268
|
// concealed in base64: no line, never a wrong one
|
|
82970
83269
|
)
|
|
@@ -82981,7 +83280,7 @@ function analyzeInstructionFile(path108, content) {
|
|
|
82981
83280
|
`\`${safeText(fo[0].slice(0, 70).trim(), 70)}\`: fetch-and-obey, outside an install/setup section`
|
|
82982
83281
|
],
|
|
82983
83282
|
"Do not instruct the agent to pipe remote content into a shell; pin and vendor scripts instead.",
|
|
82984
|
-
|
|
83283
|
+
path110,
|
|
82985
83284
|
lineAt(content, fo.index)
|
|
82986
83285
|
)
|
|
82987
83286
|
);
|
|
@@ -82997,7 +83296,7 @@ function analyzeInstructionFile(path108, content) {
|
|
|
82997
83296
|
`references \`${safeText(sp[0].slice(0, 50).trim(), 50)}\`: directs the agent toward secrets`
|
|
82998
83297
|
],
|
|
82999
83298
|
"Do not reference credential files or paths in agent instructions.",
|
|
83000
|
-
|
|
83299
|
+
path110,
|
|
83001
83300
|
lineAt(content, sp.index)
|
|
83002
83301
|
)
|
|
83003
83302
|
);
|
|
@@ -83020,7 +83319,7 @@ function analyzeInstructionFile(path108, content) {
|
|
|
83020
83319
|
"Instruction directs the agent to send data to an external endpoint",
|
|
83021
83320
|
[`\`${safeText(ex[0].slice(0, 70).trim(), 70)}\`: possible exfiltration directive`],
|
|
83022
83321
|
"Remove external post/upload directives from agent instructions.",
|
|
83023
|
-
|
|
83322
|
+
path110,
|
|
83024
83323
|
lineAt(content, ex.index)
|
|
83025
83324
|
)
|
|
83026
83325
|
);
|
|
@@ -83031,18 +83330,18 @@ function analyzeInstructionFile(path108, content) {
|
|
|
83031
83330
|
// src/ci-check/route.ts
|
|
83032
83331
|
var MCP_CONFIG_RE = /\.mcp\.json$|\.cursor\/mcp\.json$|(^|\/)\.vscode\/mcp\.json$|(^|\/)\.kiro\/settings\/mcp\.json$|(^|\/)\.gemini\/settings\.json$|(^|\/)opencode\.json$|(^|\/)\.opencode\/config\.json$/;
|
|
83033
83332
|
var ISSUE_FORM_RE = /^\.github\/ISSUE_TEMPLATE\/[^/]+\.(ya?ml|md)$/i;
|
|
83034
|
-
function routeOf(
|
|
83035
|
-
if (
|
|
83036
|
-
if (/\.github\/workflows\/.+\.ya?ml$/.test(
|
|
83037
|
-
if (ISSUE_FORM_RE.test(
|
|
83038
|
-
if (
|
|
83039
|
-
if (/\.claude\/settings(\.local)?\.json$/.test(
|
|
83040
|
-
if (isHookScript(
|
|
83041
|
-
if (isSkillScript(
|
|
83042
|
-
if (MCP_CONFIG_RE.test(
|
|
83043
|
-
if (/(^|\/)\.codex\/config\.toml$/.test(
|
|
83044
|
-
if (isInstructionFile(
|
|
83045
|
-
if (isAppDoc(
|
|
83333
|
+
function routeOf(path110, skillDirs, appDirs = /* @__PURE__ */ new Set()) {
|
|
83334
|
+
if (path110 === SUPPRESSIONS_FILE) return "suppressions";
|
|
83335
|
+
if (/\.github\/workflows\/.+\.ya?ml$/.test(path110)) return "workflow";
|
|
83336
|
+
if (ISSUE_FORM_RE.test(path110)) return "issue-form";
|
|
83337
|
+
if (path110 === "package.json" || path110 === "pyproject.toml") return "manifest";
|
|
83338
|
+
if (/\.claude\/settings(\.local)?\.json$/.test(path110)) return "agent-config";
|
|
83339
|
+
if (isHookScript(path110)) return "hook-script";
|
|
83340
|
+
if (isSkillScript(path110, skillDirs)) return "skill-script";
|
|
83341
|
+
if (MCP_CONFIG_RE.test(path110)) return "mcp";
|
|
83342
|
+
if (/(^|\/)\.codex\/config\.toml$/.test(path110)) return "codex";
|
|
83343
|
+
if (isInstructionFile(path110, skillDirs, appDirs)) return "instruction";
|
|
83344
|
+
if (isAppDoc(path110, skillDirs, appDirs)) return "app-doc";
|
|
83046
83345
|
return null;
|
|
83047
83346
|
}
|
|
83048
83347
|
|
|
@@ -83171,7 +83470,7 @@ function parseRepoUrl(input) {
|
|
|
83171
83470
|
function isLocalPath(input) {
|
|
83172
83471
|
if (input.startsWith(".") || input.startsWith("/") || input.startsWith("~")) return true;
|
|
83173
83472
|
try {
|
|
83174
|
-
return
|
|
83473
|
+
return import_fs93.default.existsSync(input) && import_fs93.default.statSync(input).isDirectory();
|
|
83175
83474
|
} catch {
|
|
83176
83475
|
return false;
|
|
83177
83476
|
}
|
|
@@ -83532,7 +83831,7 @@ function capNested(reads, cap, notes) {
|
|
|
83532
83831
|
}
|
|
83533
83832
|
var overLimit = (text) => Buffer.byteLength(text, "utf8") > MAX_FILE_BYTES3;
|
|
83534
83833
|
var RAW_LIMIT = 2 * MAX_FILE_BYTES3;
|
|
83535
|
-
var OPEN_READ =
|
|
83834
|
+
var OPEN_READ = import_fs93.default.constants.O_RDONLY | (import_fs93.default.constants.O_NOFOLLOW ?? 0) | (import_fs93.default.constants.O_NONBLOCK ?? 0);
|
|
83536
83835
|
var MAX_WALK_ENTRIES = 1e6;
|
|
83537
83836
|
var direntKind = (e) => e.isSymbolicLink() ? "link" : e.isDirectory() ? "dir" : e.isFile() ? "file" : "other";
|
|
83538
83837
|
function walkDisk(root, notes) {
|
|
@@ -83547,7 +83846,7 @@ function walkDisk(root, notes) {
|
|
|
83547
83846
|
const relDir = stack.pop();
|
|
83548
83847
|
let dirents;
|
|
83549
83848
|
try {
|
|
83550
|
-
dirents =
|
|
83849
|
+
dirents = import_fs93.default.readdirSync(import_path91.default.join(root, relDir), { withFileTypes: true });
|
|
83551
83850
|
} catch (e) {
|
|
83552
83851
|
unlistable.push(`${relDir || "."} (${e?.code ?? "error"})`);
|
|
83553
83852
|
continue;
|
|
@@ -83561,7 +83860,7 @@ function walkDisk(root, notes) {
|
|
|
83561
83860
|
const k = direntKind(e);
|
|
83562
83861
|
kinds2.set(rel, k);
|
|
83563
83862
|
if (k !== "dir" || isUnwalked(`${rel}/`)) continue;
|
|
83564
|
-
if (
|
|
83863
|
+
if (import_fs93.default.existsSync(import_path91.default.join(root, rel, ".git"))) {
|
|
83565
83864
|
sealed.add(rel);
|
|
83566
83865
|
nestedRepos.push(rel);
|
|
83567
83866
|
} else stack.push(rel);
|
|
@@ -83584,7 +83883,7 @@ function walkDisk(root, notes) {
|
|
|
83584
83883
|
}
|
|
83585
83884
|
function gitmodulePaths(root) {
|
|
83586
83885
|
try {
|
|
83587
|
-
const text = readLocalFile(
|
|
83886
|
+
const text = readLocalFile(import_path91.default.join(root, ".gitmodules"), ".gitmodules");
|
|
83588
83887
|
return [...text.matchAll(/^\s*path\s*=\s*(.+?)\s*$/gm)].map((m) => m[1].replace(/\/+$/, ""));
|
|
83589
83888
|
} catch {
|
|
83590
83889
|
return [];
|
|
@@ -83592,9 +83891,9 @@ function gitmodulePaths(root) {
|
|
|
83592
83891
|
}
|
|
83593
83892
|
function localLinkText(root, rel) {
|
|
83594
83893
|
try {
|
|
83595
|
-
const t =
|
|
83894
|
+
const t = import_fs93.default.readlinkSync(import_path91.default.join(root, rel));
|
|
83596
83895
|
if (process.platform !== "win32") return t;
|
|
83597
|
-
return
|
|
83896
|
+
return import_path91.default.win32.isAbsolute(t) ? `/${t.replace(/\\/g, "/")}` : t.replace(/\\/g, "/");
|
|
83598
83897
|
} catch {
|
|
83599
83898
|
return null;
|
|
83600
83899
|
}
|
|
@@ -83602,11 +83901,11 @@ function localLinkText(root, rel) {
|
|
|
83602
83901
|
function readLocalFile(abs, rel) {
|
|
83603
83902
|
let fd;
|
|
83604
83903
|
try {
|
|
83605
|
-
fd =
|
|
83606
|
-
const st =
|
|
83904
|
+
fd = import_fs93.default.openSync(abs, OPEN_READ);
|
|
83905
|
+
const st = import_fs93.default.fstatSync(fd);
|
|
83607
83906
|
if (!st.isFile()) throw new Error(unreadNote(rel, "no longer a regular file"));
|
|
83608
83907
|
if (st.size > RAW_LIMIT) throw new Error(tooLargeNote(rel));
|
|
83609
|
-
const text = lf(
|
|
83908
|
+
const text = lf(import_fs93.default.readFileSync(fd, "utf8"));
|
|
83610
83909
|
if (overLimit(text)) throw new Error(tooLargeNote(rel));
|
|
83611
83910
|
return text;
|
|
83612
83911
|
} catch (e) {
|
|
@@ -83614,7 +83913,7 @@ function readLocalFile(abs, rel) {
|
|
|
83614
83913
|
if (msg.includes(INCOMPLETE)) throw e;
|
|
83615
83914
|
throw new Error(unreadNote(rel, e?.code ?? "error"));
|
|
83616
83915
|
} finally {
|
|
83617
|
-
if (fd !== void 0)
|
|
83916
|
+
if (fd !== void 0) import_fs93.default.closeSync(fd);
|
|
83618
83917
|
}
|
|
83619
83918
|
}
|
|
83620
83919
|
function localGitHubRepo(root) {
|
|
@@ -83635,10 +83934,10 @@ function readLocalTree(dir2) {
|
|
|
83635
83934
|
notes.push(...plan.notes);
|
|
83636
83935
|
const files = [];
|
|
83637
83936
|
for (const { rel, real, route } of plan.reads) {
|
|
83638
|
-
const abs =
|
|
83937
|
+
const abs = import_path91.default.join(root, real);
|
|
83639
83938
|
let size = 0;
|
|
83640
83939
|
try {
|
|
83641
|
-
size =
|
|
83940
|
+
size = import_fs93.default.lstatSync(abs).size;
|
|
83642
83941
|
} catch {
|
|
83643
83942
|
}
|
|
83644
83943
|
if (size > RAW_LIMIT) {
|
|
@@ -85146,17 +85445,17 @@ function localTarget(uses, self) {
|
|
|
85146
85445
|
if (!f) return null;
|
|
85147
85446
|
return f[1].toLowerCase() === self.owner.toLowerCase() && f[2].toLowerCase() === self.repo.toLowerCase() ? `.github/workflows/${f[3]}` : null;
|
|
85148
85447
|
}
|
|
85149
|
-
function localCallsOf(
|
|
85448
|
+
function localCallsOf(path110, content, autoLabels, trustedRunSources, self) {
|
|
85150
85449
|
AUTO_LABELS = autoLabels ?? /* @__PURE__ */ new Set();
|
|
85151
85450
|
TRUSTED_RUN_SOURCES = trustedRunSources ?? /* @__PURE__ */ new Set();
|
|
85152
85451
|
try {
|
|
85153
|
-
return localCallsOfInner(
|
|
85452
|
+
return localCallsOfInner(path110, content, self);
|
|
85154
85453
|
} finally {
|
|
85155
85454
|
AUTO_LABELS = /* @__PURE__ */ new Set();
|
|
85156
85455
|
TRUSTED_RUN_SOURCES = /* @__PURE__ */ new Set();
|
|
85157
85456
|
}
|
|
85158
85457
|
}
|
|
85159
|
-
function localCallsOfInner(
|
|
85458
|
+
function localCallsOfInner(path110, content, self) {
|
|
85160
85459
|
let raw;
|
|
85161
85460
|
try {
|
|
85162
85461
|
raw = loadWorkflow(content).raw;
|
|
@@ -85174,7 +85473,7 @@ function localCallsOfInner(path108, content, self) {
|
|
|
85174
85473
|
out.push({
|
|
85175
85474
|
target,
|
|
85176
85475
|
caller: {
|
|
85177
|
-
file:
|
|
85476
|
+
file: path110,
|
|
85178
85477
|
keys: reach.keys,
|
|
85179
85478
|
untrusted: reach.untrusted,
|
|
85180
85479
|
secretExposed: reach.secretExposed,
|
|
@@ -85410,7 +85709,7 @@ function upstreamRunTrusted(wf, raw) {
|
|
|
85410
85709
|
const names = Array.isArray(run?.workflows) ? run.workflows.map(String) : [];
|
|
85411
85710
|
return names.length > 0 && names.every((n) => TRUSTED_RUN_SOURCES.has(n));
|
|
85412
85711
|
}
|
|
85413
|
-
function runSourceOf(
|
|
85712
|
+
function runSourceOf(path110, content, autoLabels) {
|
|
85414
85713
|
AUTO_LABELS = autoLabels ?? /* @__PURE__ */ new Set();
|
|
85415
85714
|
try {
|
|
85416
85715
|
let raw;
|
|
@@ -85423,7 +85722,7 @@ function runSourceOf(path108, content, autoLabels) {
|
|
|
85423
85722
|
const wf = raw;
|
|
85424
85723
|
CALLERS.delete(wf);
|
|
85425
85724
|
const reach = triggerReach(wf, raw);
|
|
85426
|
-
const name = typeof raw["name"] === "string" && raw["name"] ? raw["name"] :
|
|
85725
|
+
const name = typeof raw["name"] === "string" && raw["name"] ? raw["name"] : path110;
|
|
85427
85726
|
return { name, trusted: !reach.untrusted && !reach.reusable };
|
|
85428
85727
|
} finally {
|
|
85429
85728
|
AUTO_LABELS = /* @__PURE__ */ new Set();
|
|
@@ -85893,18 +86192,18 @@ function severityFromScore(score) {
|
|
|
85893
86192
|
if (score >= 1) return "advisory";
|
|
85894
86193
|
return null;
|
|
85895
86194
|
}
|
|
85896
|
-
function analyzeWorkflow(
|
|
86195
|
+
function analyzeWorkflow(path110, content, callers, autoLabels, trustedRunSources) {
|
|
85897
86196
|
AUTO_LABELS = autoLabels ?? /* @__PURE__ */ new Set();
|
|
85898
86197
|
TRUSTED_RUN_SOURCES = trustedRunSources ?? /* @__PURE__ */ new Set();
|
|
85899
86198
|
try {
|
|
85900
|
-
return analyzeWorkflowInner(
|
|
86199
|
+
return analyzeWorkflowInner(path110, content, callers);
|
|
85901
86200
|
} finally {
|
|
85902
86201
|
AUTO_LABELS = /* @__PURE__ */ new Set();
|
|
85903
86202
|
TRUSTED_RUN_SOURCES = /* @__PURE__ */ new Set();
|
|
85904
86203
|
UPSTREAM_TRUSTED = false;
|
|
85905
86204
|
}
|
|
85906
86205
|
}
|
|
85907
|
-
function analyzeWorkflowInner(
|
|
86206
|
+
function analyzeWorkflowInner(path110, content, callers) {
|
|
85908
86207
|
let raw;
|
|
85909
86208
|
try {
|
|
85910
86209
|
raw = loadWorkflow(content).raw;
|
|
@@ -86113,7 +86412,7 @@ function analyzeWorkflowInner(path108, content, callers) {
|
|
|
86113
86412
|
dimension: "workflows",
|
|
86114
86413
|
severity,
|
|
86115
86414
|
title,
|
|
86116
|
-
file:
|
|
86415
|
+
file: path110,
|
|
86117
86416
|
signals,
|
|
86118
86417
|
mitigations: mitigations.length ? mitigations : void 0,
|
|
86119
86418
|
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."
|
|
@@ -86217,18 +86516,18 @@ function evalAgentJob(job, wf, raw, untrustedTrigger, reusable) {
|
|
|
86217
86516
|
if (reusable && !loadedGun && SEVERITY_RANK2[severity] > SEVERITY_RANK2.medium) severity = "medium";
|
|
86218
86517
|
return { severity, secrets, injectable, canReadEnv };
|
|
86219
86518
|
}
|
|
86220
|
-
function analyzeWorkflowSecrets(
|
|
86519
|
+
function analyzeWorkflowSecrets(path110, content, callers, autoLabels, trustedRunSources) {
|
|
86221
86520
|
AUTO_LABELS = autoLabels ?? /* @__PURE__ */ new Set();
|
|
86222
86521
|
TRUSTED_RUN_SOURCES = trustedRunSources ?? /* @__PURE__ */ new Set();
|
|
86223
86522
|
try {
|
|
86224
|
-
return analyzeWorkflowSecretsInner(
|
|
86523
|
+
return analyzeWorkflowSecretsInner(path110, content, callers);
|
|
86225
86524
|
} finally {
|
|
86226
86525
|
AUTO_LABELS = /* @__PURE__ */ new Set();
|
|
86227
86526
|
TRUSTED_RUN_SOURCES = /* @__PURE__ */ new Set();
|
|
86228
86527
|
UPSTREAM_TRUSTED = false;
|
|
86229
86528
|
}
|
|
86230
86529
|
}
|
|
86231
|
-
function analyzeWorkflowSecretsInner(
|
|
86530
|
+
function analyzeWorkflowSecretsInner(path110, content, callers) {
|
|
86232
86531
|
let raw;
|
|
86233
86532
|
try {
|
|
86234
86533
|
raw = loadWorkflow(content).raw;
|
|
@@ -86255,7 +86554,7 @@ function analyzeWorkflowSecretsInner(path108, content, callers) {
|
|
|
86255
86554
|
dimension: "data",
|
|
86256
86555
|
severity: worst.severity,
|
|
86257
86556
|
title: worst.severity === "advisory" ? "Secrets reachable by the agent: hardening" : "Exfiltratable secrets reachable by an injectable agent",
|
|
86258
|
-
file:
|
|
86557
|
+
file: path110,
|
|
86259
86558
|
signals: [
|
|
86260
86559
|
`agent can reach: ${worst.secrets.map((s) => s.name).join(", ")}`,
|
|
86261
86560
|
worst.injectable ? "the agent is externally triggerable (untrusted trigger, no gate)" : "gated / not externally triggerable: latent risk only",
|
|
@@ -86277,7 +86576,7 @@ function marketplaceOwner(market) {
|
|
|
86277
86576
|
market
|
|
86278
86577
|
)?.[1] ?? /^([\w.-]{1,100})\/[\w.-]{1,100}(?:[#@].*)?$/.exec(market)?.[1];
|
|
86279
86578
|
}
|
|
86280
|
-
function analyzeWorkflowPlugins(
|
|
86579
|
+
function analyzeWorkflowPlugins(path110, content, owner) {
|
|
86281
86580
|
let raw;
|
|
86282
86581
|
try {
|
|
86283
86582
|
raw = loadWorkflow(content).raw;
|
|
@@ -86307,7 +86606,7 @@ function analyzeWorkflowPlugins(path108, content, owner) {
|
|
|
86307
86606
|
dimension: "mcp",
|
|
86308
86607
|
severity: "medium",
|
|
86309
86608
|
title: "Agent installs plugins from a third-party marketplace on every run",
|
|
86310
|
-
file:
|
|
86609
|
+
file: path110,
|
|
86311
86610
|
signals: [
|
|
86312
86611
|
`\`plugin_marketplaces: ${safeText(market, 120)}\` is not pinned to a commit: whoever controls it changes the code and prompts the agent runs`
|
|
86313
86612
|
],
|
|
@@ -86323,11 +86622,11 @@ function readsItemList(text) {
|
|
|
86323
86622
|
if (text.length > 2e5) return ITEM_LIST_RE.test(text);
|
|
86324
86623
|
return text.replace(/\\\r?\n/g, " ").split("\n").some((l) => ITEM_LIST_RE.test(l) && !sanitizedListing(l));
|
|
86325
86624
|
}
|
|
86326
|
-
function analyzeTrustedReaders(
|
|
86625
|
+
function analyzeTrustedReaders(path110, content, autoLabels, callers, trustedRunSources) {
|
|
86327
86626
|
AUTO_LABELS = autoLabels ?? /* @__PURE__ */ new Set();
|
|
86328
86627
|
TRUSTED_RUN_SOURCES = trustedRunSources ?? /* @__PURE__ */ new Set();
|
|
86329
86628
|
try {
|
|
86330
|
-
return analyzeTrustedReadersInner(
|
|
86629
|
+
return analyzeTrustedReadersInner(path110, content, callers);
|
|
86331
86630
|
} finally {
|
|
86332
86631
|
AUTO_LABELS = /* @__PURE__ */ new Set();
|
|
86333
86632
|
TRUSTED_RUN_SOURCES = /* @__PURE__ */ new Set();
|
|
@@ -86336,7 +86635,7 @@ function analyzeTrustedReaders(path108, content, autoLabels, callers, trustedRun
|
|
|
86336
86635
|
function keysWithCallers(keys, callers) {
|
|
86337
86636
|
return [.../* @__PURE__ */ new Set([...keys, ...(callers ?? []).flatMap((c) => c.keys)])];
|
|
86338
86637
|
}
|
|
86339
|
-
function analyzeTrustedReadersInner(
|
|
86638
|
+
function analyzeTrustedReadersInner(path110, content, callers) {
|
|
86340
86639
|
let raw;
|
|
86341
86640
|
try {
|
|
86342
86641
|
raw = loadWorkflow(content).raw;
|
|
@@ -86397,7 +86696,7 @@ function analyzeTrustedReadersInner(path108, content, callers) {
|
|
|
86397
86696
|
dimension: "workflows",
|
|
86398
86697
|
severity: "advisory",
|
|
86399
86698
|
title: "Agent on a trusted trigger reads content strangers write, with a write token",
|
|
86400
|
-
file:
|
|
86699
|
+
file: path110,
|
|
86401
86700
|
signals: [
|
|
86402
86701
|
`runs on ${keys.map((k) => safeText(k, 40)).join(", ")}: no stranger starts it`,
|
|
86403
86702
|
...reads.map((r) => `the agent ${r}`),
|
|
@@ -86485,17 +86784,17 @@ function requiresTrustedAuthor(src) {
|
|
|
86485
86784
|
};
|
|
86486
86785
|
return req(x);
|
|
86487
86786
|
}
|
|
86488
|
-
function analyzeForkCodeOnTrust(
|
|
86787
|
+
function analyzeForkCodeOnTrust(path110, content, callers, autoLabels, trustedRunSources) {
|
|
86489
86788
|
AUTO_LABELS = autoLabels ?? /* @__PURE__ */ new Set();
|
|
86490
86789
|
TRUSTED_RUN_SOURCES = trustedRunSources ?? /* @__PURE__ */ new Set();
|
|
86491
86790
|
try {
|
|
86492
|
-
return analyzeForkCodeOnTrustInner(
|
|
86791
|
+
return analyzeForkCodeOnTrustInner(path110, content, callers);
|
|
86493
86792
|
} finally {
|
|
86494
86793
|
AUTO_LABELS = /* @__PURE__ */ new Set();
|
|
86495
86794
|
TRUSTED_RUN_SOURCES = /* @__PURE__ */ new Set();
|
|
86496
86795
|
}
|
|
86497
86796
|
}
|
|
86498
|
-
function analyzeForkCodeOnTrustInner(
|
|
86797
|
+
function analyzeForkCodeOnTrustInner(path110, content, callers) {
|
|
86499
86798
|
let raw;
|
|
86500
86799
|
try {
|
|
86501
86800
|
raw = loadWorkflow(content).raw;
|
|
@@ -86534,7 +86833,7 @@ function analyzeForkCodeOnTrustInner(path108, content, callers) {
|
|
|
86534
86833
|
dimension: "workflows",
|
|
86535
86834
|
severity: "advisory",
|
|
86536
86835
|
title: "A maintainer's action runs the agent inside the fork's code",
|
|
86537
|
-
file:
|
|
86836
|
+
file: path110,
|
|
86538
86837
|
signals: [
|
|
86539
86838
|
`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)`,
|
|
86540
86839
|
"checks out the untrusted PR head into the workspace root",
|
|
@@ -86566,18 +86865,18 @@ function laterSecrets(wf, job, from) {
|
|
|
86566
86865
|
if (!/^GITHUB_TOKEN$/i.test(m[1])) out.add(m[1]);
|
|
86567
86866
|
return [...out];
|
|
86568
86867
|
}
|
|
86569
|
-
function analyzeAgentOutputToEnv(
|
|
86868
|
+
function analyzeAgentOutputToEnv(path110, content, callers, autoLabels, trustedRunSources) {
|
|
86570
86869
|
AUTO_LABELS = autoLabels ?? /* @__PURE__ */ new Set();
|
|
86571
86870
|
TRUSTED_RUN_SOURCES = trustedRunSources ?? /* @__PURE__ */ new Set();
|
|
86572
86871
|
try {
|
|
86573
|
-
return analyzeAgentOutputToEnvInner(
|
|
86872
|
+
return analyzeAgentOutputToEnvInner(path110, content, callers);
|
|
86574
86873
|
} finally {
|
|
86575
86874
|
AUTO_LABELS = /* @__PURE__ */ new Set();
|
|
86576
86875
|
TRUSTED_RUN_SOURCES = /* @__PURE__ */ new Set();
|
|
86577
86876
|
UPSTREAM_TRUSTED = false;
|
|
86578
86877
|
}
|
|
86579
86878
|
}
|
|
86580
|
-
function analyzeAgentOutputToEnvInner(
|
|
86879
|
+
function analyzeAgentOutputToEnvInner(path110, content, callers) {
|
|
86581
86880
|
let raw;
|
|
86582
86881
|
try {
|
|
86583
86882
|
raw = loadWorkflow(content).raw;
|
|
@@ -86673,7 +86972,7 @@ function analyzeAgentOutputToEnvInner(path108, content, callers) {
|
|
|
86673
86972
|
dimension: "workflows",
|
|
86674
86973
|
severity,
|
|
86675
86974
|
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",
|
|
86676
|
-
file:
|
|
86975
|
+
file: path110,
|
|
86677
86976
|
signals,
|
|
86678
86977
|
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.`,
|
|
86679
86978
|
explain: explainAgentOutputEnv({
|
|
@@ -86701,7 +87000,7 @@ function analyzeAgentOutputToEnvInner(path108, content, callers) {
|
|
|
86701
87000
|
|
|
86702
87001
|
// src/ci-check/agent-config.ts
|
|
86703
87002
|
init_cjs_shims();
|
|
86704
|
-
var
|
|
87003
|
+
var import_path92 = __toESM(require("path"));
|
|
86705
87004
|
function asStrings(v) {
|
|
86706
87005
|
return Array.isArray(v) ? v.filter((x) => typeof x === "string") : [];
|
|
86707
87006
|
}
|
|
@@ -86809,7 +87108,7 @@ function hookScriptPath(cmd) {
|
|
|
86809
87108
|
if (/^(https?:|\$|-)/.test(t)) continue;
|
|
86810
87109
|
t = t.replace(/^\.\//, "");
|
|
86811
87110
|
if (!SCRIPT_EXT_RE.test(t) && !/(^|\/)\.claude\/hooks\//.test(t)) continue;
|
|
86812
|
-
const norm =
|
|
87111
|
+
const norm = import_path92.default.posix.normalize(t);
|
|
86813
87112
|
if (norm.startsWith("..") || norm.startsWith("/") || norm.includes("/../")) return null;
|
|
86814
87113
|
return norm;
|
|
86815
87114
|
}
|
|
@@ -86819,7 +87118,7 @@ function cmdLine(content, cmd) {
|
|
|
86819
87118
|
const i = jsonValueIndex(content, cmd);
|
|
86820
87119
|
return i >= 0 ? lineAtIndex(content, i) : void 0;
|
|
86821
87120
|
}
|
|
86822
|
-
function analyzeAgentConfig(
|
|
87121
|
+
function analyzeAgentConfig(path110, content, tree) {
|
|
86823
87122
|
let cfg;
|
|
86824
87123
|
try {
|
|
86825
87124
|
cfg = JSON.parse(content);
|
|
@@ -86842,7 +87141,7 @@ function analyzeAgentConfig(path108, content, tree) {
|
|
|
86842
87141
|
dimension: "toolRules",
|
|
86843
87142
|
severity: high ? "high" : "medium",
|
|
86844
87143
|
title: high ? "Agent hook runs UNPINNED/remote third-party code on every action" : "Agent hook runs third-party code in the agent hot path",
|
|
86845
|
-
file:
|
|
87144
|
+
file: path110,
|
|
86846
87145
|
...cmdLine(content, cmd) ? { line: cmdLine(content, cmd) } : {},
|
|
86847
87146
|
signals: [
|
|
86848
87147
|
`hook command: \`${safeText(cmd, 120)}\``,
|
|
@@ -86863,7 +87162,7 @@ function analyzeAgentConfig(path108, content, tree) {
|
|
|
86863
87162
|
dimension: "toolRules",
|
|
86864
87163
|
severity: "medium",
|
|
86865
87164
|
title: "Agent hook runs a script that is not committed",
|
|
86866
|
-
file:
|
|
87165
|
+
file: path110,
|
|
86867
87166
|
...cmdLine(content, cmd) ? { line: cmdLine(content, cmd) } : {},
|
|
86868
87167
|
signals: [
|
|
86869
87168
|
`hook command: \`${safeText(cmd, 120)}\``,
|
|
@@ -86879,7 +87178,7 @@ function analyzeAgentConfig(path108, content, tree) {
|
|
|
86879
87178
|
dimension: "toolRules",
|
|
86880
87179
|
severity: "advisory",
|
|
86881
87180
|
title: "Agent hook runs a committed script this scan did not read",
|
|
86882
|
-
file:
|
|
87181
|
+
file: path110,
|
|
86883
87182
|
...cmdLine(content, cmd) ? { line: cmdLine(content, cmd) } : {},
|
|
86884
87183
|
signals: [
|
|
86885
87184
|
`hook command: \`${safeText(cmd, 120)}\``,
|
|
@@ -86908,12 +87207,12 @@ function analyzeAgentConfig(path108, content, tree) {
|
|
|
86908
87207
|
dimension: "toolRules",
|
|
86909
87208
|
severity: high ? "high" : "medium",
|
|
86910
87209
|
title: high ? "Committed agent config pre-authorizes broad tools with no deny backstop" : "Committed agent config pre-authorizes broad tools",
|
|
86911
|
-
file:
|
|
87210
|
+
file: path110,
|
|
86912
87211
|
signals,
|
|
86913
87212
|
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.",
|
|
86914
87213
|
explain: explainGrant({
|
|
86915
87214
|
high,
|
|
86916
|
-
file:
|
|
87215
|
+
file: path110,
|
|
86917
87216
|
broad: grade.broad,
|
|
86918
87217
|
bareShell: grade.bareShell,
|
|
86919
87218
|
hasBackstop: grade.bareShell ? deny.some((d) => /^Bash\b/.test(d)) : deny.some((d) => /Bash|Write|Edit/.test(d))
|
|
@@ -86930,7 +87229,7 @@ function analyzeAgentConfig(path108, content, tree) {
|
|
|
86930
87229
|
dimension: "toolRules",
|
|
86931
87230
|
severity: "medium",
|
|
86932
87231
|
title: "Committed agent config pre-approves a command that can run other programs",
|
|
86933
|
-
file:
|
|
87232
|
+
file: path110,
|
|
86934
87233
|
signals: [
|
|
86935
87234
|
`pre-approved: ${escapes.slice(0, 5).map((e) => `\`${safeText(e, 80)}\``).join(", ")}`,
|
|
86936
87235
|
"`find -exec` and `make -n --eval` run other programs without a prompt"
|
|
@@ -86945,8 +87244,8 @@ var ROOT_SURFACE_RE = /^\.(claude|agents|github|codex|cursor|gemini)\//;
|
|
|
86945
87244
|
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/;
|
|
86946
87245
|
var PR_TEXT_RE = /gh\s+pr\s+(?:view|diff)\b|gh\s+api\s+[^\n]{0,120}\/pulls\b/;
|
|
86947
87246
|
var WEB_TEXT_RE = /\bsearch the web\b|\bfetch (?:the )?(?:url|page)\b/i;
|
|
86948
|
-
function skillReadsUntrusted(
|
|
86949
|
-
if (!ROOT_SURFACE_RE.test(
|
|
87247
|
+
function skillReadsUntrusted(path110, content, allow, broad) {
|
|
87248
|
+
if (!ROOT_SURFACE_RE.test(path110)) return null;
|
|
86950
87249
|
const body = content.replace(/^---[\s\S]*?\n---/, "");
|
|
86951
87250
|
const runsCode = broad.map((a) => a.replace(/^PowerShell(?=$|\()/, "Bash")).some((a) => /^Bash$|^Bash\(\s*\*/.test(a) || openRunner(a) && !/^Bash\(\s*gh\b/.test(a));
|
|
86952
87251
|
const webGrant = allow.some((a) => /^(WebFetch|WebSearch)\b/.test(a));
|
|
@@ -86961,8 +87260,8 @@ function skillReadsUntrusted(path108, content, allow, broad) {
|
|
|
86961
87260
|
return "it reads pull request text that strangers write, and may edit files and run git/gh on it";
|
|
86962
87261
|
return null;
|
|
86963
87262
|
}
|
|
86964
|
-
function analyzeSkillGrants(
|
|
86965
|
-
if (!GRANT_CARRIER_RE.test(
|
|
87263
|
+
function analyzeSkillGrants(path110, content) {
|
|
87264
|
+
if (!GRANT_CARRIER_RE.test(path110)) return [];
|
|
86966
87265
|
const allow = allowedToolsOf(parseFrontmatter(content));
|
|
86967
87266
|
if (allow.length === 0) return [];
|
|
86968
87267
|
const grade = gradeBroadGrant(allow, [], {
|
|
@@ -86970,9 +87269,9 @@ function analyzeSkillGrants(path108, content) {
|
|
|
86970
87269
|
scope: "whenever this skill or command is active, for everyone who opens this repo with the agent"
|
|
86971
87270
|
});
|
|
86972
87271
|
if (!grade) return [];
|
|
86973
|
-
const kind = /commands\//.test(
|
|
87272
|
+
const kind = /commands\//.test(path110) ? "slash command" : "skill";
|
|
86974
87273
|
const at = content.search(/^allowed-tools\s*:/m);
|
|
86975
|
-
const untrusted = skillReadsUntrusted(
|
|
87274
|
+
const untrusted = skillReadsUntrusted(path110, content, allow, grade.broad);
|
|
86976
87275
|
if (untrusted)
|
|
86977
87276
|
return [
|
|
86978
87277
|
{
|
|
@@ -86982,7 +87281,7 @@ function analyzeSkillGrants(path108, content) {
|
|
|
86982
87281
|
dimension: "toolRules",
|
|
86983
87282
|
severity: "advisory",
|
|
86984
87283
|
title: `Committed ${kind} runs code or writes with text strangers control`,
|
|
86985
|
-
file:
|
|
87284
|
+
file: path110,
|
|
86986
87285
|
signals: [...grade.signals, untrusted],
|
|
86987
87286
|
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."
|
|
86988
87287
|
}
|
|
@@ -86999,7 +87298,7 @@ function analyzeSkillGrants(path108, content) {
|
|
|
86999
87298
|
// shell — the cap is on reach, not on honesty.
|
|
87000
87299
|
severity: "medium",
|
|
87001
87300
|
title: grade.high ? `Committed ${kind} pre-authorizes an unrestricted shell while active` : `Committed ${kind} pre-authorizes broad tools while active`,
|
|
87002
|
-
file:
|
|
87301
|
+
file: path110,
|
|
87003
87302
|
signals: grade.signals,
|
|
87004
87303
|
fix: "Scope `allowed-tools` to the specific commands the skill needs (e.g. `Bash(git status:*)`); avoid a bare `Bash`, `Write` or `Edit`."
|
|
87005
87304
|
}
|
|
@@ -87131,7 +87430,7 @@ function ownPackageNames(manifests) {
|
|
|
87131
87430
|
}
|
|
87132
87431
|
return out;
|
|
87133
87432
|
}
|
|
87134
|
-
function analyzeMcp(
|
|
87433
|
+
function analyzeMcp(path110, content, own = /* @__PURE__ */ new Set()) {
|
|
87135
87434
|
let cfg;
|
|
87136
87435
|
try {
|
|
87137
87436
|
cfg = JSON.parse(content);
|
|
@@ -87167,9 +87466,9 @@ function analyzeMcp(path108, content, own = /* @__PURE__ */ new Set()) {
|
|
|
87167
87466
|
const key = (count.get(name) ?? 0) > 1 ? `${section}.${name}` : name;
|
|
87168
87467
|
servers[key] = { ...spec, anchor: name };
|
|
87169
87468
|
}
|
|
87170
|
-
return analyzeMcpServers(servers,
|
|
87469
|
+
return analyzeMcpServers(servers, path110, content, own);
|
|
87171
87470
|
}
|
|
87172
|
-
function analyzeMcpServers(servers,
|
|
87471
|
+
function analyzeMcpServers(servers, path110, content = "", own = /* @__PURE__ */ new Set()) {
|
|
87173
87472
|
const findings = [];
|
|
87174
87473
|
for (const [name, srv] of Object.entries(servers ?? {})) {
|
|
87175
87474
|
if (!srv || srv.disabled) continue;
|
|
@@ -87188,7 +87487,7 @@ function analyzeMcpServers(servers, path108, content = "", own = /* @__PURE__ */
|
|
|
87188
87487
|
dimension: "mcp",
|
|
87189
87488
|
severity: "medium",
|
|
87190
87489
|
title: `MCP server "${name}" runs an unpinned executable`,
|
|
87191
|
-
file:
|
|
87490
|
+
file: path110,
|
|
87192
87491
|
...line ? { line } : {},
|
|
87193
87492
|
signals: [
|
|
87194
87493
|
why.launcher === "npx" ? `\`${safeText(argv, 120)}\`: unversioned/@latest npx` : `\`${safeText(argv, 120)}\`: unversioned/latest ${why.launcher}`
|
|
@@ -87213,7 +87512,7 @@ function analyzeMcpServers(servers, path108, content = "", own = /* @__PURE__ */
|
|
|
87213
87512
|
dimension: "mcp",
|
|
87214
87513
|
severity: "high",
|
|
87215
87514
|
title: `MCP server "${name}" has an inline credential`,
|
|
87216
|
-
file:
|
|
87515
|
+
file: path110,
|
|
87217
87516
|
...line ? { line } : {},
|
|
87218
87517
|
signals: [
|
|
87219
87518
|
`env.${k} matches ${hit.patternName}: agent-reachable secret committed to the repo`
|
|
@@ -87229,7 +87528,7 @@ function analyzeMcpServers(servers, path108, content = "", own = /* @__PURE__ */
|
|
|
87229
87528
|
// src/ci-check/codex.ts
|
|
87230
87529
|
init_cjs_shims();
|
|
87231
87530
|
var import_smol_toml7 = require("smol-toml");
|
|
87232
|
-
function analyzeCodexConfig(
|
|
87531
|
+
function analyzeCodexConfig(path110, content, own = /* @__PURE__ */ new Set()) {
|
|
87233
87532
|
let cfg;
|
|
87234
87533
|
try {
|
|
87235
87534
|
cfg = (0, import_smol_toml7.parse)(content);
|
|
@@ -87237,7 +87536,7 @@ function analyzeCodexConfig(path108, content, own = /* @__PURE__ */ new Set()) {
|
|
|
87237
87536
|
return [];
|
|
87238
87537
|
}
|
|
87239
87538
|
const findings = [];
|
|
87240
|
-
findings.push(...analyzeMcpServers(cfg.mcp_servers ?? {},
|
|
87539
|
+
findings.push(...analyzeMcpServers(cfg.mcp_servers ?? {}, path110, content, own));
|
|
87241
87540
|
const sandbox = typeof cfg.sandbox_mode === "string" ? cfg.sandbox_mode : "";
|
|
87242
87541
|
const approval = typeof cfg.approval_policy === "string" ? cfg.approval_policy : "";
|
|
87243
87542
|
const fullAccess = /danger-full-access/i.test(sandbox);
|
|
@@ -87260,7 +87559,7 @@ function analyzeCodexConfig(path108, content, own = /* @__PURE__ */ new Set()) {
|
|
|
87260
87559
|
dimension: "toolRules",
|
|
87261
87560
|
severity: fullAccess ? "high" : "medium",
|
|
87262
87561
|
title: fullAccess ? "Codex config grants a full-access sandbox" : "Codex config never requires approval",
|
|
87263
|
-
file:
|
|
87562
|
+
file: path110,
|
|
87264
87563
|
signals,
|
|
87265
87564
|
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.'
|
|
87266
87565
|
});
|
|
@@ -87314,7 +87613,7 @@ function reviewQuestion(rule) {
|
|
|
87314
87613
|
return "Is this an instruction the agent follows, or text for a person?";
|
|
87315
87614
|
}
|
|
87316
87615
|
var RANK2 = { critical: 4, high: 3, medium: 2, advisory: 1 };
|
|
87317
|
-
var worstRank = (
|
|
87616
|
+
var worstRank = (fs111) => Math.max(...fs111.map((f) => RANK2[f.severity] ?? 0));
|
|
87318
87617
|
var fileOrder = (a, b) => worstRank(b[1]) - worstRank(a[1]) || b[1].length - a[1].length;
|
|
87319
87618
|
function groupReview(findings) {
|
|
87320
87619
|
const byFile = /* @__PURE__ */ new Map();
|
|
@@ -87379,7 +87678,7 @@ function logicalLines2(content) {
|
|
|
87379
87678
|
}
|
|
87380
87679
|
return out;
|
|
87381
87680
|
}
|
|
87382
|
-
function analyzeScript(
|
|
87681
|
+
function analyzeScript(path110, content, rulePrefix) {
|
|
87383
87682
|
const check = rulePrefix.startsWith("CI-1") ? "CI-1" : "CI-6";
|
|
87384
87683
|
const dimension = check === "CI-1" ? "toolRules" : "instructions";
|
|
87385
87684
|
const mk3 = (suffix, severity, title, signal, fix, line) => ({
|
|
@@ -87388,7 +87687,7 @@ function analyzeScript(path108, content, rulePrefix) {
|
|
|
87388
87687
|
dimension,
|
|
87389
87688
|
severity,
|
|
87390
87689
|
title,
|
|
87391
|
-
file:
|
|
87690
|
+
file: path110,
|
|
87392
87691
|
...line ? { line } : {},
|
|
87393
87692
|
signals: [signal],
|
|
87394
87693
|
fix
|
|
@@ -87814,7 +88113,7 @@ async function scanRepo(input, onProgress) {
|
|
|
87814
88113
|
// src/ci-check/render.ts
|
|
87815
88114
|
init_cjs_shims();
|
|
87816
88115
|
var import_chalk36 = __toESM(require("chalk"));
|
|
87817
|
-
var listed = (
|
|
88116
|
+
var listed = (fs111) => fs111.filter((f) => f.tier !== "review");
|
|
87818
88117
|
function excerpt(f) {
|
|
87819
88118
|
const m = /`([^`]+)`/.exec(f.signals[0] ?? "");
|
|
87820
88119
|
return safeText(m ? m[1] : f.title, 120).replace(/`/g, "'");
|
|
@@ -87830,14 +88129,14 @@ function reviewMd(findings) {
|
|
|
87830
88129
|
L.push("");
|
|
87831
88130
|
const files = [...byFile.keys()];
|
|
87832
88131
|
for (const file2 of files.slice(0, REVIEW_FILES)) {
|
|
87833
|
-
const
|
|
88132
|
+
const fs111 = byFile.get(file2);
|
|
87834
88133
|
L.push(`- \`${safeText(file2, 300)}\``);
|
|
87835
|
-
for (const f of
|
|
88134
|
+
for (const f of fs111.slice(0, REVIEW_LINES_PER_FILE))
|
|
87836
88135
|
L.push(
|
|
87837
88136
|
` - ${f.line ? `line ${Number(f.line)}: ` : ""}\`${excerpt(f)}\`. Check: ${reviewQuestion(f.rule)}`
|
|
87838
88137
|
);
|
|
87839
|
-
if (
|
|
87840
|
-
L.push(` - and ${
|
|
88138
|
+
if (fs111.length > REVIEW_LINES_PER_FILE)
|
|
88139
|
+
L.push(` - and ${fs111.length - REVIEW_LINES_PER_FILE} similar lines in this file`);
|
|
87841
88140
|
}
|
|
87842
88141
|
const more = files.length - REVIEW_FILES;
|
|
87843
88142
|
if (more > 0) L.push(`- and ${more} more file${more === 1 ? "" : "s"}`);
|
|
@@ -87853,7 +88152,7 @@ function reviewMd(findings) {
|
|
|
87853
88152
|
}
|
|
87854
88153
|
function reviewTerminal(findings) {
|
|
87855
88154
|
const { byFile, grants } = groupReview(findings);
|
|
87856
|
-
const items = [...byFile.values()].reduce((a,
|
|
88155
|
+
const items = [...byFile.values()].reduce((a, fs111) => a + fs111.length, 0);
|
|
87857
88156
|
if (!items && !grants) return [];
|
|
87858
88157
|
const L = [];
|
|
87859
88158
|
if (items) {
|
|
@@ -87862,12 +88161,12 @@ function reviewTerminal(findings) {
|
|
|
87862
88161
|
);
|
|
87863
88162
|
const files = [...byFile.keys()];
|
|
87864
88163
|
for (const file2 of files.slice(0, REVIEW_FILES)) {
|
|
87865
|
-
const
|
|
88164
|
+
const fs111 = byFile.get(file2);
|
|
87866
88165
|
L.push(import_chalk36.default.gray(` ${file2}`));
|
|
87867
|
-
for (const f of
|
|
88166
|
+
for (const f of fs111.slice(0, REVIEW_LINES_PER_FILE))
|
|
87868
88167
|
L.push(` \u2022 ${f.line ? `line ${f.line}: ` : ""}${excerpt(f)}`);
|
|
87869
|
-
if (
|
|
87870
|
-
L.push(import_chalk36.default.gray(` and ${
|
|
88168
|
+
if (fs111.length > REVIEW_LINES_PER_FILE)
|
|
88169
|
+
L.push(import_chalk36.default.gray(` and ${fs111.length - REVIEW_LINES_PER_FILE} similar lines`));
|
|
87871
88170
|
}
|
|
87872
88171
|
const more = files.length - REVIEW_FILES;
|
|
87873
88172
|
if (more > 0) L.push(import_chalk36.default.gray(` and ${more} more file${more === 1 ? "" : "s"}`));
|
|
@@ -87881,7 +88180,7 @@ function reviewTerminal(findings) {
|
|
|
87881
88180
|
L.push("");
|
|
87882
88181
|
return L;
|
|
87883
88182
|
}
|
|
87884
|
-
var
|
|
88183
|
+
var ICON3 = {
|
|
87885
88184
|
critical: "\u{1F534}",
|
|
87886
88185
|
high: "\u{1F534}",
|
|
87887
88186
|
medium: "\u{1F7E1}",
|
|
@@ -87941,7 +88240,7 @@ function mdLine(v) {
|
|
|
87941
88240
|
function findingMd(f, L) {
|
|
87942
88241
|
const ex = f.explain;
|
|
87943
88242
|
L.push(
|
|
87944
|
-
`**${
|
|
88243
|
+
`**${ICON3[f.severity]} ${f.severity.toUpperCase()}: ${mdLine(ex ? ex.headline : f.title)}**` + (f.suppressed ? ` _(suppressed: \`${safeText(f.suppressed.reason, 200)}\`)_` : "")
|
|
87945
88244
|
);
|
|
87946
88245
|
L.push(`\`${safeText(f.file, 300)}${f.line ? ":" + Number(f.line) : ""}\` \xB7 ${f.rule}`);
|
|
87947
88246
|
L.push("");
|
|
@@ -87997,7 +88296,7 @@ function renderScan(res, diff) {
|
|
|
87997
88296
|
for (const f of shown) {
|
|
87998
88297
|
const ex = f.explain;
|
|
87999
88298
|
L.push(
|
|
88000
|
-
`${
|
|
88299
|
+
`${ICON3[f.severity]} ${COLOR[f.severity](f.severity.toUpperCase())} ${import_chalk36.default.bold(ex ? ex.headline : f.title)}`
|
|
88001
88300
|
);
|
|
88002
88301
|
L.push(import_chalk36.default.gray(` ${f.file}${f.line ? ":" + f.line : ""} \xB7 ${f.check}`));
|
|
88003
88302
|
if (ex) {
|
|
@@ -88519,16 +88818,16 @@ var import_chalk40 = __toESM(require("chalk"));
|
|
|
88519
88818
|
|
|
88520
88819
|
// src/canary/plant.ts
|
|
88521
88820
|
init_cjs_shims();
|
|
88522
|
-
var
|
|
88523
|
-
var
|
|
88524
|
-
var
|
|
88821
|
+
var import_fs95 = __toESM(require("fs"));
|
|
88822
|
+
var import_os77 = __toESM(require("os"));
|
|
88823
|
+
var import_path94 = __toESM(require("path"));
|
|
88525
88824
|
init_jail();
|
|
88526
88825
|
init_registry2();
|
|
88527
88826
|
|
|
88528
88827
|
// src/canary/sites.ts
|
|
88529
88828
|
init_cjs_shims();
|
|
88530
|
-
var
|
|
88531
|
-
var
|
|
88829
|
+
var import_fs94 = __toESM(require("fs"));
|
|
88830
|
+
var import_path93 = __toESM(require("path"));
|
|
88532
88831
|
|
|
88533
88832
|
// src/canary/generate.ts
|
|
88534
88833
|
init_cjs_shims();
|
|
@@ -88623,26 +88922,26 @@ function generateSshKey() {
|
|
|
88623
88922
|
var SITES = {
|
|
88624
88923
|
"aws-profile": {
|
|
88625
88924
|
kind: "aws-profile",
|
|
88626
|
-
primary: (h) =>
|
|
88627
|
-
fallback: (h) =>
|
|
88925
|
+
primary: (h) => import_path93.default.join(h, ".aws", "credentials"),
|
|
88926
|
+
fallback: (h) => import_path93.default.join(h, ".aws", "credentials.bak"),
|
|
88628
88927
|
// SSO / profile-only / credential_process setups have ~/.aws/config and no
|
|
88629
88928
|
// credentials file; the SDK and CLI then parse ~/.aws/credentials on every
|
|
88630
88929
|
// profile lookup. A planted primary would be a file real tools read.
|
|
88631
|
-
preferFallback: (h) =>
|
|
88930
|
+
preferFallback: (h) => import_fs94.default.existsSync(import_path93.default.join(h, ".aws", "config")),
|
|
88632
88931
|
dirMode: 448,
|
|
88633
88932
|
generate: generateAwsProfile
|
|
88634
88933
|
},
|
|
88635
88934
|
"env-file": {
|
|
88636
88935
|
kind: "env-file",
|
|
88637
|
-
primary: (h) =>
|
|
88638
|
-
fallback: (h) =>
|
|
88936
|
+
primary: (h) => import_path93.default.join(h, ".env.bak"),
|
|
88937
|
+
fallback: (h) => import_path93.default.join(h, ".env.local.bak"),
|
|
88639
88938
|
dirMode: 493,
|
|
88640
88939
|
generate: generateEnvFile
|
|
88641
88940
|
},
|
|
88642
88941
|
"ssh-key": {
|
|
88643
88942
|
kind: "ssh-key",
|
|
88644
|
-
primary: (h) =>
|
|
88645
|
-
fallback: (h) =>
|
|
88943
|
+
primary: (h) => import_path93.default.join(h, ".ssh", "id_rsa_backup"),
|
|
88944
|
+
fallback: (h) => import_path93.default.join(h, ".ssh", "id_rsa.old"),
|
|
88646
88945
|
// ssh refuses a group-writable ~/.ssh for config / known_hosts reads.
|
|
88647
88946
|
dirMode: 448,
|
|
88648
88947
|
generate: generateSshKey
|
|
@@ -88655,12 +88954,12 @@ var isKind = (s) => ALL_KINDS.includes(s);
|
|
|
88655
88954
|
var liveRecords = (kind) => loadCanaries().filter((r) => r.kind === kind && !r.retiredAt);
|
|
88656
88955
|
var fileHashOf = (p) => {
|
|
88657
88956
|
try {
|
|
88658
|
-
return sha256Hex(
|
|
88957
|
+
return sha256Hex(import_fs95.default.readFileSync(p));
|
|
88659
88958
|
} catch {
|
|
88660
88959
|
return null;
|
|
88661
88960
|
}
|
|
88662
88961
|
};
|
|
88663
|
-
function plantKind(kind, home =
|
|
88962
|
+
function plantKind(kind, home = import_os77.default.homedir()) {
|
|
88664
88963
|
const site = SITES[kind];
|
|
88665
88964
|
const live = liveRecords(kind);
|
|
88666
88965
|
if (live.length > 0) {
|
|
@@ -88679,8 +88978,8 @@ function plantKind(kind, home = import_os76.default.homedir()) {
|
|
|
88679
88978
|
const primary = site.primary(home);
|
|
88680
88979
|
const fallback = site.fallback(home);
|
|
88681
88980
|
let target;
|
|
88682
|
-
if (!
|
|
88683
|
-
else if (!
|
|
88981
|
+
if (!import_fs95.default.existsSync(primary) && !site.preferFallback?.(home)) target = primary;
|
|
88982
|
+
else if (!import_fs95.default.existsSync(fallback)) target = fallback;
|
|
88684
88983
|
else {
|
|
88685
88984
|
return {
|
|
88686
88985
|
kind,
|
|
@@ -88691,11 +88990,11 @@ function plantKind(kind, home = import_os76.default.homedir()) {
|
|
|
88691
88990
|
recordIds: []
|
|
88692
88991
|
};
|
|
88693
88992
|
}
|
|
88694
|
-
const dir2 =
|
|
88993
|
+
const dir2 = import_path94.default.dirname(target);
|
|
88695
88994
|
const gen = site.generate();
|
|
88696
|
-
const createdDir =
|
|
88697
|
-
|
|
88698
|
-
|
|
88995
|
+
const createdDir = import_fs95.default.mkdirSync(dir2, { recursive: true, mode: site.dirMode }) !== void 0;
|
|
88996
|
+
import_fs95.default.writeFileSync(target, gen.text, { mode: 384, flag: "wx" });
|
|
88997
|
+
import_fs95.default.chmodSync(target, 384);
|
|
88699
88998
|
const fileHash = sha256Hex(gen.text);
|
|
88700
88999
|
regenerateUserJail(addJailPath(target, "block"));
|
|
88701
89000
|
const recordIds = gen.values.map(
|
|
@@ -88713,14 +89012,14 @@ function plantKind(kind, home = import_os76.default.homedir()) {
|
|
|
88713
89012
|
}
|
|
88714
89013
|
function allowedPathsFor(kind, home) {
|
|
88715
89014
|
const site = SITES[kind];
|
|
88716
|
-
return [site.primary(home), site.fallback(home)].map((x) =>
|
|
89015
|
+
return [site.primary(home), site.fallback(home)].map((x) => import_path94.default.resolve(x));
|
|
88717
89016
|
}
|
|
88718
|
-
function removeKind(kind, home =
|
|
89017
|
+
function removeKind(kind, home = import_os77.default.homedir()) {
|
|
88719
89018
|
const live = liveRecords(kind);
|
|
88720
89019
|
if (live.length === 0) return { kind, action: "absent" };
|
|
88721
89020
|
const p = live[0].path;
|
|
88722
89021
|
const { fileHash, createdDir } = live[0];
|
|
88723
|
-
if (!allowedPathsFor(kind, home).includes(
|
|
89022
|
+
if (!allowedPathsFor(kind, home).includes(import_path94.default.resolve(p))) {
|
|
88724
89023
|
return {
|
|
88725
89024
|
kind,
|
|
88726
89025
|
action: "refused",
|
|
@@ -88728,7 +89027,7 @@ function removeKind(kind, home = import_os76.default.homedir()) {
|
|
|
88728
89027
|
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.`
|
|
88729
89028
|
};
|
|
88730
89029
|
}
|
|
88731
|
-
if (!
|
|
89030
|
+
if (!import_fs95.default.existsSync(p)) {
|
|
88732
89031
|
for (const r of live) retireCanary(r.id);
|
|
88733
89032
|
unjail(p);
|
|
88734
89033
|
return { kind, action: "already-gone", path: p };
|
|
@@ -88741,13 +89040,13 @@ function removeKind(kind, home = import_os76.default.homedir()) {
|
|
|
88741
89040
|
reason: `${p} changed since node9 wrote it; inspect and remove it by hand`
|
|
88742
89041
|
};
|
|
88743
89042
|
}
|
|
88744
|
-
|
|
89043
|
+
import_fs95.default.unlinkSync(p);
|
|
88745
89044
|
let dirRemoved = false;
|
|
88746
89045
|
if (createdDir) {
|
|
88747
|
-
const dir2 =
|
|
89046
|
+
const dir2 = import_path94.default.dirname(p);
|
|
88748
89047
|
try {
|
|
88749
|
-
if (
|
|
88750
|
-
|
|
89048
|
+
if (import_fs95.default.readdirSync(dir2).length === 0) {
|
|
89049
|
+
import_fs95.default.rmdirSync(dir2);
|
|
88751
89050
|
dirRemoved = true;
|
|
88752
89051
|
}
|
|
88753
89052
|
} catch {
|
|
@@ -88771,14 +89070,14 @@ function statusAll() {
|
|
|
88771
89070
|
const p = live[0].path;
|
|
88772
89071
|
return {
|
|
88773
89072
|
kind,
|
|
88774
|
-
state:
|
|
89073
|
+
state: import_fs95.default.existsSync(p) ? "planted" : "missing",
|
|
88775
89074
|
path: p,
|
|
88776
89075
|
records: live.length,
|
|
88777
89076
|
plantedAt: live[0].plantedAt
|
|
88778
89077
|
};
|
|
88779
89078
|
});
|
|
88780
89079
|
}
|
|
88781
|
-
function rotateKind(kind, home =
|
|
89080
|
+
function rotateKind(kind, home = import_os77.default.homedir()) {
|
|
88782
89081
|
const removed = removeKind(kind);
|
|
88783
89082
|
if (removed.action === "refused") return { removed };
|
|
88784
89083
|
return { removed, planted: plantKind(kind, home) };
|
|
@@ -88867,15 +89166,15 @@ init_daemon3();
|
|
|
88867
89166
|
// src/cli/commands/sandbox.ts
|
|
88868
89167
|
init_cjs_shims();
|
|
88869
89168
|
var import_chalk41 = __toESM(require("chalk"));
|
|
88870
|
-
var
|
|
88871
|
-
var
|
|
89169
|
+
var import_fs98 = __toESM(require("fs"));
|
|
89170
|
+
var import_path97 = __toESM(require("path"));
|
|
88872
89171
|
var import_child_process16 = require("child_process");
|
|
88873
89172
|
init_config();
|
|
88874
89173
|
|
|
88875
89174
|
// src/sandbox/config.ts
|
|
88876
89175
|
init_cjs_shims();
|
|
88877
|
-
var
|
|
88878
|
-
var
|
|
89176
|
+
var import_fs96 = __toESM(require("fs"));
|
|
89177
|
+
var import_path95 = __toESM(require("path"));
|
|
88879
89178
|
var import_yaml2 = require("yaml");
|
|
88880
89179
|
var SANDBOX_CONFIG_FILE = "node9.sandbox.yaml";
|
|
88881
89180
|
var FORBIDDEN_ENV = /* @__PURE__ */ new Set(["NODE9_API_KEY", "NODE9_API_URL"]);
|
|
@@ -88948,16 +89247,16 @@ function scaffoldSandboxYaml(agent) {
|
|
|
88948
89247
|
return header + (0, import_yaml2.stringify)(defaultSandboxConfig(agent));
|
|
88949
89248
|
}
|
|
88950
89249
|
function sandboxConfigPath(cwd = process.cwd()) {
|
|
88951
|
-
return
|
|
89250
|
+
return import_path95.default.join(cwd, SANDBOX_CONFIG_FILE);
|
|
88952
89251
|
}
|
|
88953
89252
|
function loadSandboxConfig(cwd = process.cwd(), fallbackAgent = "claude") {
|
|
88954
89253
|
const p = sandboxConfigPath(cwd);
|
|
88955
|
-
if (!
|
|
89254
|
+
if (!import_fs96.default.existsSync(p)) {
|
|
88956
89255
|
throw new Error(`sandbox: ${SANDBOX_CONFIG_FILE} not found \u2014 run \`node9 sandbox new\` first.`);
|
|
88957
89256
|
}
|
|
88958
89257
|
let raw;
|
|
88959
89258
|
try {
|
|
88960
|
-
raw = (0, import_yaml2.parse)(
|
|
89259
|
+
raw = (0, import_yaml2.parse)(import_fs96.default.readFileSync(p, "utf-8"));
|
|
88961
89260
|
} catch (err2) {
|
|
88962
89261
|
throw new Error(
|
|
88963
89262
|
`sandbox: ${SANDBOX_CONFIG_FILE} is not valid YAML \u2014 ${err2.message}`
|
|
@@ -89018,14 +89317,14 @@ init_atomic_write();
|
|
|
89018
89317
|
|
|
89019
89318
|
// src/sandbox/runtime.ts
|
|
89020
89319
|
init_cjs_shims();
|
|
89021
|
-
var
|
|
89022
|
-
var
|
|
89023
|
-
var
|
|
89320
|
+
var import_fs97 = __toESM(require("fs"));
|
|
89321
|
+
var import_os78 = __toESM(require("os"));
|
|
89322
|
+
var import_path96 = __toESM(require("path"));
|
|
89024
89323
|
var import_crypto26 = __toESM(require("crypto"));
|
|
89025
89324
|
var import_child_process15 = require("child_process");
|
|
89026
89325
|
init_templates();
|
|
89027
89326
|
function sandboxDataDir(cwd = process.cwd()) {
|
|
89028
|
-
return
|
|
89327
|
+
return import_path96.default.join(cwd, ".node9", "sandbox", "data");
|
|
89029
89328
|
}
|
|
89030
89329
|
function detectEngine(engine) {
|
|
89031
89330
|
const r = (0, import_child_process15.spawnSync)(engine, ["--version"], { encoding: "utf-8" });
|
|
@@ -89036,7 +89335,7 @@ function detectEngine(engine) {
|
|
|
89036
89335
|
}
|
|
89037
89336
|
function agentCredentialsMount(agent) {
|
|
89038
89337
|
const rel = agent === "codex" ? ".codex/auth.json" : ".claude/.credentials.json";
|
|
89039
|
-
return { hostPath:
|
|
89338
|
+
return { hostPath: import_path96.default.join(import_os78.default.homedir(), rel), target: `/home/${RUN_AS_USER}/${rel}` };
|
|
89040
89339
|
}
|
|
89041
89340
|
function buildRunArgs(opts) {
|
|
89042
89341
|
const { config, workspaceHostPath, dataHostPath, allowlistHostPath, agentArgs } = opts;
|
|
@@ -89046,7 +89345,7 @@ function buildRunArgs(opts) {
|
|
|
89046
89345
|
args.push("-v", `${allowlistHostPath}:${ALLOWED_DOMAINS_PATH}:ro`);
|
|
89047
89346
|
if (config.node9.mountAgentCredentials) {
|
|
89048
89347
|
const creds = agentCredentialsMount(config.agent);
|
|
89049
|
-
if (
|
|
89348
|
+
if (import_fs97.default.existsSync(creds.hostPath)) {
|
|
89050
89349
|
args.push("-v", `${creds.hostPath}:${creds.target}`);
|
|
89051
89350
|
}
|
|
89052
89351
|
}
|
|
@@ -89064,30 +89363,30 @@ function imageContentHash(dockerfile, entrypoint) {
|
|
|
89064
89363
|
return import_crypto26.default.createHash("sha256").update(dockerfile).update("\0").update(entrypoint).digest("hex").slice(0, 16);
|
|
89065
89364
|
}
|
|
89066
89365
|
function sandboxBuildDir(cwd = process.cwd()) {
|
|
89067
|
-
return
|
|
89366
|
+
return import_path96.default.join(cwd, ".node9", "sandbox", "build");
|
|
89068
89367
|
}
|
|
89069
89368
|
function writeBuildContext(cwd, dockerfile, entrypoint) {
|
|
89070
89369
|
const dir2 = sandboxBuildDir(cwd);
|
|
89071
|
-
|
|
89072
|
-
|
|
89073
|
-
|
|
89370
|
+
import_fs97.default.mkdirSync(dir2, { recursive: true });
|
|
89371
|
+
import_fs97.default.writeFileSync(import_path96.default.join(dir2, "Dockerfile"), dockerfile);
|
|
89372
|
+
import_fs97.default.writeFileSync(import_path96.default.join(dir2, "entrypoint.sh"), entrypoint);
|
|
89074
89373
|
return dir2;
|
|
89075
89374
|
}
|
|
89076
89375
|
function writeAllowlist(cwd, hosts) {
|
|
89077
|
-
const dir2 =
|
|
89078
|
-
|
|
89079
|
-
const p =
|
|
89080
|
-
|
|
89376
|
+
const dir2 = import_path96.default.join(cwd, ".node9", "sandbox");
|
|
89377
|
+
import_fs97.default.mkdirSync(dir2, { recursive: true });
|
|
89378
|
+
const p = import_path96.default.join(dir2, "allowed-domains.txt");
|
|
89379
|
+
import_fs97.default.writeFileSync(p, hosts.join("\n") + "\n");
|
|
89081
89380
|
return p;
|
|
89082
89381
|
}
|
|
89083
89382
|
function resolveHomePath(p) {
|
|
89084
|
-
return p.startsWith("~") ?
|
|
89383
|
+
return p.startsWith("~") ? import_path96.default.join(import_os78.default.homedir(), p.slice(1)) : import_path96.default.resolve(p);
|
|
89085
89384
|
}
|
|
89086
89385
|
|
|
89087
89386
|
// src/cli/commands/sandbox.ts
|
|
89088
89387
|
function seedDataDirConfig(dataDir, sandbox) {
|
|
89089
|
-
|
|
89090
|
-
const configPath2 =
|
|
89388
|
+
import_fs98.default.mkdirSync(dataDir, { recursive: true });
|
|
89389
|
+
const configPath2 = import_path97.default.join(dataDir, "config.json");
|
|
89091
89390
|
const seed = {
|
|
89092
89391
|
settings: {
|
|
89093
89392
|
approvers: {
|
|
@@ -89098,7 +89397,7 @@ function seedDataDirConfig(dataDir, sandbox) {
|
|
|
89098
89397
|
}
|
|
89099
89398
|
}
|
|
89100
89399
|
};
|
|
89101
|
-
|
|
89400
|
+
import_fs98.default.writeFileSync(configPath2, JSON.stringify(seed, null, 2), { mode: 384 });
|
|
89102
89401
|
}
|
|
89103
89402
|
function registerSandboxCommand(program2, version2) {
|
|
89104
89403
|
const node9Version2 = pinnedNode9Version(version2);
|
|
@@ -89107,7 +89406,7 @@ function registerSandboxCommand(program2, version2) {
|
|
|
89107
89406
|
const agent = opts.agent === "codex" ? "codex" : "claude";
|
|
89108
89407
|
const p = sandboxConfigPath();
|
|
89109
89408
|
try {
|
|
89110
|
-
|
|
89409
|
+
import_fs98.default.writeFileSync(p, scaffoldSandboxYaml(agent), { flag: "wx" });
|
|
89111
89410
|
} catch (e) {
|
|
89112
89411
|
if (e.code !== "EEXIST") throw e;
|
|
89113
89412
|
console.log(
|
|
@@ -89154,8 +89453,8 @@ function registerSandboxCommand(program2, version2) {
|
|
|
89154
89453
|
const buildDir = writeBuildContext(cwd, dockerfile, entrypoint);
|
|
89155
89454
|
const hash2 = imageContentHash(dockerfile, entrypoint);
|
|
89156
89455
|
const image = sandbox.runtime.image;
|
|
89157
|
-
const hashFile =
|
|
89158
|
-
const lastHash =
|
|
89456
|
+
const hashFile = import_path97.default.join(sandboxBuildDir(cwd), ".image-hash");
|
|
89457
|
+
const lastHash = import_fs98.default.existsSync(hashFile) ? import_fs98.default.readFileSync(hashFile, "utf-8").trim() : "";
|
|
89159
89458
|
const imageExists = (0, import_child_process16.spawnSync)(sandbox.runtime.engine, ["image", "inspect", image], { stdio: "ignore" }).status === 0;
|
|
89160
89459
|
const needBuild = sandbox.runtime.rebuild === "always" || !imageExists || sandbox.runtime.rebuild !== "never" && lastHash !== hash2;
|
|
89161
89460
|
if (needBuild) {
|
|
@@ -89181,7 +89480,7 @@ function registerSandboxCommand(program2, version2) {
|
|
|
89181
89480
|
});
|
|
89182
89481
|
if (sandbox.node9.mountAgentCredentials) {
|
|
89183
89482
|
const creds = agentCredentialsMount(sandbox.agent);
|
|
89184
|
-
if (
|
|
89483
|
+
if (import_fs98.default.existsSync(creds.hostPath)) {
|
|
89185
89484
|
console.log(import_chalk41.default.dim(` mounting ${creds.hostPath} (agent credentials, rw)`));
|
|
89186
89485
|
} else {
|
|
89187
89486
|
console.log(
|
|
@@ -89197,20 +89496,20 @@ function registerSandboxCommand(program2, version2) {
|
|
|
89197
89496
|
process.exit(r.status ?? 0);
|
|
89198
89497
|
});
|
|
89199
89498
|
cmd.command("tail").description("Stream the sandbox's audit log (host-side)").action(() => {
|
|
89200
|
-
const auditPath =
|
|
89201
|
-
if (!
|
|
89499
|
+
const auditPath = import_path97.default.join(sandboxDataDir(), "audit.log");
|
|
89500
|
+
if (!import_fs98.default.existsSync(auditPath)) {
|
|
89202
89501
|
console.log(import_chalk41.default.dim(" no sandbox audit yet."));
|
|
89203
89502
|
return;
|
|
89204
89503
|
}
|
|
89205
89504
|
(0, import_child_process16.spawnSync)("tail", ["-f", auditPath], { stdio: "inherit" });
|
|
89206
89505
|
});
|
|
89207
89506
|
cmd.command("logs").description("Dump the sandbox's audit log").action(() => {
|
|
89208
|
-
const auditPath =
|
|
89209
|
-
if (!
|
|
89507
|
+
const auditPath = import_path97.default.join(sandboxDataDir(), "audit.log");
|
|
89508
|
+
if (!import_fs98.default.existsSync(auditPath)) {
|
|
89210
89509
|
console.log(import_chalk41.default.dim(" no sandbox audit yet."));
|
|
89211
89510
|
return;
|
|
89212
89511
|
}
|
|
89213
|
-
process.stdout.write(
|
|
89512
|
+
process.stdout.write(import_fs98.default.readFileSync(auditPath, "utf-8"));
|
|
89214
89513
|
});
|
|
89215
89514
|
cmd.command("clean").description("Remove the sandbox image, build context, and data").action(() => {
|
|
89216
89515
|
const cwd = process.cwd();
|
|
@@ -89224,7 +89523,7 @@ function registerSandboxCommand(program2, version2) {
|
|
|
89224
89523
|
stdio: "ignore"
|
|
89225
89524
|
});
|
|
89226
89525
|
}
|
|
89227
|
-
|
|
89526
|
+
import_fs98.default.rmSync(import_path97.default.join(cwd, ".node9", "sandbox"), { recursive: true, force: true });
|
|
89228
89527
|
console.log(import_chalk41.default.green(" \u2713 sandbox image + build + data removed."));
|
|
89229
89528
|
});
|
|
89230
89529
|
}
|
|
@@ -89453,12 +89752,12 @@ function registerPackageIndexCommand(program2) {
|
|
|
89453
89752
|
// src/cli/commands/skill-pin.ts
|
|
89454
89753
|
init_cjs_shims();
|
|
89455
89754
|
var import_chalk45 = __toESM(require("chalk"));
|
|
89456
|
-
var
|
|
89457
|
-
var
|
|
89458
|
-
var
|
|
89755
|
+
var import_fs99 = __toESM(require("fs"));
|
|
89756
|
+
var import_os79 = __toESM(require("os"));
|
|
89757
|
+
var import_path98 = __toESM(require("path"));
|
|
89459
89758
|
function wipeSkillSessions() {
|
|
89460
89759
|
try {
|
|
89461
|
-
|
|
89760
|
+
import_fs99.default.rmSync(import_path98.default.join(import_os79.default.homedir(), ".node9", "skill-sessions"), {
|
|
89462
89761
|
recursive: true,
|
|
89463
89762
|
force: true
|
|
89464
89763
|
});
|
|
@@ -89541,15 +89840,15 @@ function registerSkillPinCommand(program2) {
|
|
|
89541
89840
|
|
|
89542
89841
|
// src/cli/commands/decisions.ts
|
|
89543
89842
|
init_cjs_shims();
|
|
89544
|
-
var
|
|
89545
|
-
var
|
|
89546
|
-
var
|
|
89843
|
+
var import_fs100 = __toESM(require("fs"));
|
|
89844
|
+
var import_os80 = __toESM(require("os"));
|
|
89845
|
+
var import_path99 = __toESM(require("path"));
|
|
89547
89846
|
var import_chalk46 = __toESM(require("chalk"));
|
|
89548
|
-
var DECISIONS_FILE2 =
|
|
89847
|
+
var DECISIONS_FILE2 = import_path99.default.join(import_os80.default.homedir(), ".node9", "decisions.json");
|
|
89549
89848
|
function readDecisions() {
|
|
89550
89849
|
try {
|
|
89551
|
-
if (!
|
|
89552
|
-
const raw =
|
|
89850
|
+
if (!import_fs100.default.existsSync(DECISIONS_FILE2)) return {};
|
|
89851
|
+
const raw = import_fs100.default.readFileSync(DECISIONS_FILE2, "utf-8");
|
|
89553
89852
|
const parsed = JSON.parse(raw);
|
|
89554
89853
|
const out = {};
|
|
89555
89854
|
for (const [k, v] of Object.entries(parsed)) {
|
|
@@ -89561,11 +89860,11 @@ function readDecisions() {
|
|
|
89561
89860
|
}
|
|
89562
89861
|
}
|
|
89563
89862
|
function writeDecisions(d) {
|
|
89564
|
-
const dir2 =
|
|
89565
|
-
if (!
|
|
89863
|
+
const dir2 = import_path99.default.dirname(DECISIONS_FILE2);
|
|
89864
|
+
if (!import_fs100.default.existsSync(dir2)) import_fs100.default.mkdirSync(dir2, { recursive: true });
|
|
89566
89865
|
const tmp = `${DECISIONS_FILE2}.${process.pid}.tmp`;
|
|
89567
|
-
|
|
89568
|
-
|
|
89866
|
+
import_fs100.default.writeFileSync(tmp, JSON.stringify(d, null, 2));
|
|
89867
|
+
import_fs100.default.renameSync(tmp, DECISIONS_FILE2);
|
|
89569
89868
|
}
|
|
89570
89869
|
function registerDecisionsCommand(program2) {
|
|
89571
89870
|
const cmd = program2.command("decisions").description('Manage persistent "Always Allow" / "Always Deny" tool decisions');
|
|
@@ -89623,15 +89922,15 @@ Persistent decisions (${entries.length})
|
|
|
89623
89922
|
// src/cli/commands/dlp.ts
|
|
89624
89923
|
init_cjs_shims();
|
|
89625
89924
|
var import_chalk47 = __toESM(require("chalk"));
|
|
89626
|
-
var
|
|
89627
|
-
var
|
|
89628
|
-
var
|
|
89925
|
+
var import_fs101 = __toESM(require("fs"));
|
|
89926
|
+
var import_path100 = __toESM(require("path"));
|
|
89927
|
+
var import_os81 = __toESM(require("os"));
|
|
89629
89928
|
init_safe_text();
|
|
89630
|
-
var AUDIT_LOG =
|
|
89631
|
-
var RESOLVED_FILE =
|
|
89929
|
+
var AUDIT_LOG = import_path100.default.join(import_os81.default.homedir(), ".node9", "audit.log");
|
|
89930
|
+
var RESOLVED_FILE = import_path100.default.join(import_os81.default.homedir(), ".node9", "dlp-resolved.json");
|
|
89632
89931
|
function loadResolved() {
|
|
89633
89932
|
try {
|
|
89634
|
-
const raw = JSON.parse(
|
|
89933
|
+
const raw = JSON.parse(import_fs101.default.readFileSync(RESOLVED_FILE, "utf-8"));
|
|
89635
89934
|
return new Set(raw);
|
|
89636
89935
|
} catch {
|
|
89637
89936
|
return /* @__PURE__ */ new Set();
|
|
@@ -89639,13 +89938,13 @@ function loadResolved() {
|
|
|
89639
89938
|
}
|
|
89640
89939
|
function saveResolved(resolved) {
|
|
89641
89940
|
try {
|
|
89642
|
-
|
|
89941
|
+
import_fs101.default.writeFileSync(RESOLVED_FILE, JSON.stringify([...resolved], null, 2), { mode: 384 });
|
|
89643
89942
|
} catch {
|
|
89644
89943
|
}
|
|
89645
89944
|
}
|
|
89646
89945
|
function loadDlpFindings() {
|
|
89647
|
-
if (!
|
|
89648
|
-
return
|
|
89946
|
+
if (!import_fs101.default.existsSync(AUDIT_LOG)) return [];
|
|
89947
|
+
return import_fs101.default.readFileSync(AUDIT_LOG, "utf-8").split("\n").flatMap((line) => {
|
|
89649
89948
|
if (!line.trim()) return [];
|
|
89650
89949
|
try {
|
|
89651
89950
|
const e = JSON.parse(line);
|
|
@@ -89744,15 +90043,15 @@ function registerDlpCommand(program2) {
|
|
|
89744
90043
|
// src/cli/commands/mask.ts
|
|
89745
90044
|
init_cjs_shims();
|
|
89746
90045
|
var import_chalk48 = __toESM(require("chalk"));
|
|
89747
|
-
var
|
|
89748
|
-
var
|
|
89749
|
-
var
|
|
90046
|
+
var import_fs102 = __toESM(require("fs"));
|
|
90047
|
+
var import_path101 = __toESM(require("path"));
|
|
90048
|
+
var import_os82 = __toESM(require("os"));
|
|
89750
90049
|
init_dlp();
|
|
89751
90050
|
function findJsonlFiles(dir2) {
|
|
89752
90051
|
const results = [];
|
|
89753
|
-
if (!
|
|
89754
|
-
for (const entry of
|
|
89755
|
-
const full =
|
|
90052
|
+
if (!import_fs102.default.existsSync(dir2)) return results;
|
|
90053
|
+
for (const entry of import_fs102.default.readdirSync(dir2, { withFileTypes: true })) {
|
|
90054
|
+
const full = import_path101.default.join(dir2, entry.name);
|
|
89756
90055
|
if (entry.isDirectory()) results.push(...findJsonlFiles(full));
|
|
89757
90056
|
else if (entry.isFile() && entry.name.endsWith(".jsonl")) results.push(full);
|
|
89758
90057
|
}
|
|
@@ -89795,7 +90094,7 @@ function redactJson(obj) {
|
|
|
89795
90094
|
function processFile(filePath, dryRun) {
|
|
89796
90095
|
let raw;
|
|
89797
90096
|
try {
|
|
89798
|
-
raw =
|
|
90097
|
+
raw = import_fs102.default.readFileSync(filePath, "utf-8");
|
|
89799
90098
|
} catch {
|
|
89800
90099
|
return { redactedLines: 0, patterns: [] };
|
|
89801
90100
|
}
|
|
@@ -89827,14 +90126,14 @@ function processFile(filePath, dryRun) {
|
|
|
89827
90126
|
}
|
|
89828
90127
|
}
|
|
89829
90128
|
if (!dryRun && redactedLines > 0) {
|
|
89830
|
-
|
|
90129
|
+
import_fs102.default.writeFileSync(filePath, newLines.join("\n"), "utf-8");
|
|
89831
90130
|
}
|
|
89832
90131
|
return { redactedLines, patterns };
|
|
89833
90132
|
}
|
|
89834
90133
|
function processJsonFile(filePath, dryRun) {
|
|
89835
90134
|
let raw;
|
|
89836
90135
|
try {
|
|
89837
|
-
raw =
|
|
90136
|
+
raw = import_fs102.default.readFileSync(filePath, "utf-8");
|
|
89838
90137
|
} catch {
|
|
89839
90138
|
return { redactedLines: 0, patterns: [] };
|
|
89840
90139
|
}
|
|
@@ -89847,15 +90146,15 @@ function processJsonFile(filePath, dryRun) {
|
|
|
89847
90146
|
const { value, modified, found } = redactJson(parsed);
|
|
89848
90147
|
if (!modified) return { redactedLines: 0, patterns: [] };
|
|
89849
90148
|
if (!dryRun) {
|
|
89850
|
-
|
|
90149
|
+
import_fs102.default.writeFileSync(filePath, JSON.stringify(value, null, 2), "utf-8");
|
|
89851
90150
|
}
|
|
89852
90151
|
return { redactedLines: 1, patterns: found };
|
|
89853
90152
|
}
|
|
89854
90153
|
function findJsonFiles(dir2) {
|
|
89855
90154
|
const results = [];
|
|
89856
|
-
if (!
|
|
89857
|
-
for (const entry of
|
|
89858
|
-
const full =
|
|
90155
|
+
if (!import_fs102.default.existsSync(dir2)) return results;
|
|
90156
|
+
for (const entry of import_fs102.default.readdirSync(dir2, { withFileTypes: true })) {
|
|
90157
|
+
const full = import_path101.default.join(dir2, entry.name);
|
|
89859
90158
|
if (entry.isDirectory()) results.push(...findJsonFiles(full));
|
|
89860
90159
|
else if (entry.isFile() && entry.name.endsWith(".json")) results.push(full);
|
|
89861
90160
|
}
|
|
@@ -89864,9 +90163,9 @@ function findJsonFiles(dir2) {
|
|
|
89864
90163
|
function registerMaskCommand(program2) {
|
|
89865
90164
|
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) => {
|
|
89866
90165
|
const dryRun = !!options.dryRun;
|
|
89867
|
-
const home =
|
|
89868
|
-
const claudeDir =
|
|
89869
|
-
const geminiDir =
|
|
90166
|
+
const home = import_os82.default.homedir();
|
|
90167
|
+
const claudeDir = import_path101.default.join(home, ".claude", "projects");
|
|
90168
|
+
const geminiDir = import_path101.default.join(home, ".gemini", "tmp");
|
|
89870
90169
|
const allFiles = [
|
|
89871
90170
|
...findJsonlFiles(claudeDir).map((p) => ({ path: p, type: "jsonl" })),
|
|
89872
90171
|
...findJsonFiles(geminiDir).map((p) => ({ path: p, type: "json" }))
|
|
@@ -89874,7 +90173,7 @@ function registerMaskCommand(program2) {
|
|
|
89874
90173
|
const cutoff = options.all ? null : new Date(Date.now() - 30 * 24 * 60 * 60 * 1e3);
|
|
89875
90174
|
const filtered = cutoff ? allFiles.filter((f) => {
|
|
89876
90175
|
try {
|
|
89877
|
-
return
|
|
90176
|
+
return import_fs102.default.statSync(f.path).mtime >= cutoff;
|
|
89878
90177
|
} catch {
|
|
89879
90178
|
return false;
|
|
89880
90179
|
}
|
|
@@ -89931,7 +90230,7 @@ function registerMaskCommand(program2) {
|
|
|
89931
90230
|
init_blast();
|
|
89932
90231
|
init_safe_text();
|
|
89933
90232
|
var { version } = JSON.parse(
|
|
89934
|
-
|
|
90233
|
+
import_fs106.default.readFileSync(import_path105.default.join(__dirname, "../package.json"), "utf-8")
|
|
89935
90234
|
);
|
|
89936
90235
|
var program = new import_commander.Command();
|
|
89937
90236
|
program.name("node9").description("The Sudo Command for AI Agents").version(version);
|
|
@@ -90089,8 +90388,8 @@ function undoLeftoverNote() {
|
|
|
90089
90388
|
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) => {
|
|
90090
90389
|
console.log(import_chalk50.default.cyan("\n\u{1F6E1}\uFE0F Node9 Uninstall\n"));
|
|
90091
90390
|
try {
|
|
90092
|
-
const credRaw =
|
|
90093
|
-
|
|
90391
|
+
const credRaw = import_fs106.default.readFileSync(
|
|
90392
|
+
import_path105.default.join(import_os86.default.homedir(), ".node9", "credentials.json"),
|
|
90094
90393
|
"utf-8"
|
|
90095
90394
|
);
|
|
90096
90395
|
const prof = JSON.parse(credRaw)[process.env.NODE9_PROFILE || "default"];
|
|
@@ -90165,7 +90464,7 @@ program.command("uninstall").description("Remove all Node9 hooks and optionally
|
|
|
90165
90464
|
if (removed.length > 0 || refused.length > 0) {
|
|
90166
90465
|
console.log(import_chalk50.default.bold("\nRemoving decoy credentials..."));
|
|
90167
90466
|
for (const r of removed) {
|
|
90168
|
-
if (r.path) console.log(import_chalk50.default.green(` \u2705 ${r.path.replace(
|
|
90467
|
+
if (r.path) console.log(import_chalk50.default.green(` \u2705 ${r.path.replace(import_os86.default.homedir(), "~")}`));
|
|
90169
90468
|
}
|
|
90170
90469
|
for (const r of refused) {
|
|
90171
90470
|
decoysLeft.push(r.path ?? "(unknown path)");
|
|
@@ -90182,8 +90481,8 @@ program.command("uninstall").description("Remove all Node9 hooks and optionally
|
|
|
90182
90481
|
decoysLeft = ["(the decoy registry could not be read)"];
|
|
90183
90482
|
}
|
|
90184
90483
|
if (options.purge) {
|
|
90185
|
-
const node9Dir =
|
|
90186
|
-
if (
|
|
90484
|
+
const node9Dir = import_path105.default.join(import_os86.default.homedir(), ".node9");
|
|
90485
|
+
if (import_fs106.default.existsSync(node9Dir)) {
|
|
90187
90486
|
const alsoSnapshots = undoLeftoverPaths().length > 0 ? ", old undo snapshots" : "";
|
|
90188
90487
|
if (decoysLeft.length > 0) {
|
|
90189
90488
|
console.error(import_chalk50.default.red("\n \u26A0\uFE0F Decoy credential files are still on disk:"));
|
|
@@ -90199,8 +90498,8 @@ program.command("uninstall").description("Remove all Node9 hooks and optionally
|
|
|
90199
90498
|
default: false
|
|
90200
90499
|
});
|
|
90201
90500
|
if (confirmed) {
|
|
90202
|
-
|
|
90203
|
-
if (
|
|
90501
|
+
import_fs106.default.rmSync(node9Dir, { recursive: true });
|
|
90502
|
+
if (import_fs106.default.existsSync(node9Dir)) {
|
|
90204
90503
|
console.error(
|
|
90205
90504
|
import_chalk50.default.red("\n \u26A0\uFE0F ~/.node9/ could not be fully deleted \u2014 remove it manually.")
|
|
90206
90505
|
);
|
|
@@ -90356,7 +90655,7 @@ program.command("tail").description("Stream live agent activity to the terminal"
|
|
|
90356
90655
|
});
|
|
90357
90656
|
program.command("monitor").description("Live interactive dashboard \u2014 activity feed, approvals, security signals").action(async () => {
|
|
90358
90657
|
try {
|
|
90359
|
-
const dashboardPath =
|
|
90658
|
+
const dashboardPath = import_path105.default.join(__dirname, "dashboard.mjs");
|
|
90360
90659
|
const dynamicImport = new Function("id", "return import(id)");
|
|
90361
90660
|
const mod = await dynamicImport(`file://${dashboardPath}`);
|
|
90362
90661
|
await mod.startMonitor();
|
|
@@ -90394,14 +90693,14 @@ Claude Code spawns this command every ~300ms and writes a JSON payload to stdin.
|
|
|
90394
90693
|
Run "node9 addto claude" to register it as the statusLine.`
|
|
90395
90694
|
).argument("[subcommand]", 'Optional: "debug on" / "debug off" to toggle stdin logging').argument("[state]", 'on|off \u2014 used with "debug" subcommand').action(async (subcommand, state) => {
|
|
90396
90695
|
if (subcommand === "debug") {
|
|
90397
|
-
const flagFile =
|
|
90696
|
+
const flagFile = import_path105.default.join(import_os86.default.homedir(), ".node9", "hud-debug");
|
|
90398
90697
|
if (state === "on") {
|
|
90399
|
-
|
|
90400
|
-
|
|
90698
|
+
import_fs106.default.mkdirSync(import_path105.default.dirname(flagFile), { recursive: true });
|
|
90699
|
+
import_fs106.default.writeFileSync(flagFile, "");
|
|
90401
90700
|
console.log("HUD debug logging enabled \u2192 ~/.node9/hud-debug.log");
|
|
90402
90701
|
console.log("Tail it with: tail -f ~/.node9/hud-debug.log");
|
|
90403
90702
|
} else if (state === "off") {
|
|
90404
|
-
if (
|
|
90703
|
+
if (import_fs106.default.existsSync(flagFile)) import_fs106.default.unlinkSync(flagFile);
|
|
90405
90704
|
console.log("HUD debug logging disabled.");
|
|
90406
90705
|
} else {
|
|
90407
90706
|
console.error("Usage: node9 hud debug on|off");
|
|
@@ -90535,9 +90834,9 @@ if (process.argv[2] !== "daemon") {
|
|
|
90535
90834
|
const isCheckHook = process.argv[2] === "check";
|
|
90536
90835
|
if (isCheckHook) {
|
|
90537
90836
|
if (process.env.NODE9_DEBUG === "1" || getConfig().settings.enableHookLogDebug) {
|
|
90538
|
-
const logPath =
|
|
90837
|
+
const logPath = import_path105.default.join(import_os86.default.homedir(), ".node9", "hook-debug.log");
|
|
90539
90838
|
const msg = reason instanceof Error ? reason.message : String(reason);
|
|
90540
|
-
|
|
90839
|
+
import_fs106.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] UNHANDLED: ${msg}
|
|
90541
90840
|
`);
|
|
90542
90841
|
}
|
|
90543
90842
|
process.exit(0);
|