@node9/proxy 2.47.2 → 2.48.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli-main.js +911 -660
- package/dist/dashboard.mjs +1 -0
- package/dist/hook.js +360 -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 with the line above, exactly as written, on its own line.";
|
|
26969
|
+
USER_LINE_PART_MAX = 160;
|
|
26970
|
+
ONE_LINE_INPUT_MAX = 1e3;
|
|
26971
|
+
PICTOGRAPHS = /[\p{Extended_Pictographic}\u200D\uFE0F]/gu;
|
|
26972
|
+
IS_BLOCKED_BY = /^(.+?) (?:is|are) blocked by (.+?)\.?$/i;
|
|
26973
|
+
IS_BLOCKED = /^(.+?) (?:is|are) blocked\.?$/i;
|
|
26974
|
+
COMMA_BLOCKED_BY = /^(.+?), blocked by (.+?)\.?$/i;
|
|
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,112 @@ 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
|
+
var ICON2 = "\u{1F6E1}\uFE0F";
|
|
74928
|
+
var LEVEL_NAMES = {
|
|
74929
|
+
audit: "Audit",
|
|
74930
|
+
soft: "Soft",
|
|
74931
|
+
standard: "Standard",
|
|
74932
|
+
strict: "Strict",
|
|
74933
|
+
"block-all": "Block all"
|
|
74934
|
+
};
|
|
74935
|
+
var SESSION_NOTICE_INSTRUCTION = "Start your next reply to the user with the line above, exactly as written, on its own line.";
|
|
74936
|
+
var FLAG_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
74937
|
+
var SAFE_SESSION_ID = /^[A-Za-z0-9_-]{1,128}$/;
|
|
74938
|
+
function sessionNoticeLine(mode) {
|
|
74939
|
+
const level = levelOf(mode);
|
|
74940
|
+
if (level === "audit") {
|
|
74941
|
+
return `${ICON2} Node9 is in Audit mode: actions are logged, nothing is blocked.`;
|
|
74942
|
+
}
|
|
74943
|
+
return `${ICON2} Node9 is on (${LEVEL_NAMES[level]}). Every action in this session is checked.`;
|
|
74944
|
+
}
|
|
74945
|
+
function sessionNoticeOutput(mode) {
|
|
74946
|
+
const line = sessionNoticeLine(mode);
|
|
74947
|
+
return JSON.stringify({
|
|
74948
|
+
hookSpecificOutput: {
|
|
74949
|
+
hookEventName: "PreToolUse",
|
|
74950
|
+
additionalContext: `${line}
|
|
74951
|
+
${SESSION_NOTICE_INSTRUCTION}`
|
|
74952
|
+
},
|
|
74953
|
+
systemMessage: line
|
|
74954
|
+
});
|
|
74955
|
+
}
|
|
74956
|
+
function sessionNoticeEnabled(env = process.env) {
|
|
74957
|
+
if (env.NODE9_SESSION_NOTICE === "1") return true;
|
|
74958
|
+
return env.NODE9_TESTING !== "1";
|
|
74959
|
+
}
|
|
74960
|
+
function claimSessionNotice(sessionId, home = import_os61.default.homedir()) {
|
|
74961
|
+
if (!sessionId || !SAFE_SESSION_ID.test(sessionId)) return false;
|
|
74962
|
+
const dir2 = import_path74.default.join(home, ".node9", "notice-sessions");
|
|
74963
|
+
const seen = ensureOwnDir(dir2);
|
|
74964
|
+
if (!seen) return false;
|
|
74965
|
+
try {
|
|
74966
|
+
if (!isSameOwnDir(dir2, seen)) return false;
|
|
74967
|
+
import_fs74.default.closeSync(import_fs74.default.openSync(import_path74.default.join(dir2, sessionId + SESSION_FLAG_SUFFIX), "wx"));
|
|
74968
|
+
} catch {
|
|
74969
|
+
return false;
|
|
74970
|
+
}
|
|
74971
|
+
removeOldFlags(dir2, seen);
|
|
74972
|
+
return true;
|
|
74973
|
+
}
|
|
74974
|
+
function removeOldFlags(dir2, seen) {
|
|
74975
|
+
const cutoff = Date.now() - FLAG_TTL_MS;
|
|
74976
|
+
try {
|
|
74977
|
+
for (const name of import_fs74.default.readdirSync(dir2)) removeOldFlag(dir2, seen, name, cutoff);
|
|
74978
|
+
} catch {
|
|
74979
|
+
}
|
|
74980
|
+
}
|
|
74981
|
+
|
|
74982
|
+
// src/cli/commands/check.ts
|
|
74753
74983
|
function detectAiAgent(payload) {
|
|
74754
74984
|
const meta = payload.meta;
|
|
74755
74985
|
if (meta && typeof meta === "object") {
|
|
@@ -74827,9 +75057,9 @@ function registerCheckCommand(program2) {
|
|
|
74827
75057
|
} catch (err2) {
|
|
74828
75058
|
const tempConfig = getConfig();
|
|
74829
75059
|
if (process.env.NODE9_DEBUG === "1" || tempConfig.settings.enableHookLogDebug) {
|
|
74830
|
-
const logPath =
|
|
75060
|
+
const logPath = import_path75.default.join(import_os62.default.homedir(), ".node9", "hook-debug.log");
|
|
74831
75061
|
const errMsg = err2 instanceof Error ? err2.message : String(err2);
|
|
74832
|
-
|
|
75062
|
+
import_fs75.default.appendFileSync(
|
|
74833
75063
|
logPath,
|
|
74834
75064
|
`[${(/* @__PURE__ */ new Date()).toISOString()}] JSON_PARSE_ERROR: ${errMsg}
|
|
74835
75065
|
RAW: ${raw}
|
|
@@ -74842,14 +75072,14 @@ RAW: ${raw}
|
|
|
74842
75072
|
const prompt = typeof payload.prompt === "string" ? payload.prompt : "";
|
|
74843
75073
|
if (process.env.NODE9_DEBUG === "1") {
|
|
74844
75074
|
try {
|
|
74845
|
-
const logPath =
|
|
74846
|
-
if (!
|
|
74847
|
-
|
|
75075
|
+
const logPath = import_path75.default.join(import_os62.default.homedir(), ".node9", "hook-debug.log");
|
|
75076
|
+
if (!import_fs75.default.existsSync(import_path75.default.dirname(logPath)))
|
|
75077
|
+
import_fs75.default.mkdirSync(import_path75.default.dirname(logPath), { recursive: true });
|
|
74848
75078
|
const sanitized = JSON.stringify({
|
|
74849
75079
|
...payload,
|
|
74850
75080
|
prompt: `<redacted, ${prompt.length} bytes>`
|
|
74851
75081
|
});
|
|
74852
|
-
|
|
75082
|
+
import_fs75.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] STDIN: ${sanitized}
|
|
74853
75083
|
`);
|
|
74854
75084
|
} catch {
|
|
74855
75085
|
}
|
|
@@ -74867,7 +75097,7 @@ RAW: ${raw}
|
|
|
74867
75097
|
if (!dlpMatch && !canaryHit) {
|
|
74868
75098
|
try {
|
|
74869
75099
|
const sid = typeof payload.session_id === "string" ? payload.session_id : typeof payload.conversationId === "string" ? payload.conversationId : "";
|
|
74870
|
-
const promptCwd = typeof payload.cwd === "string" &&
|
|
75100
|
+
const promptCwd = typeof payload.cwd === "string" && import_path75.default.isAbsolute(payload.cwd) ? payload.cwd : void 0;
|
|
74871
75101
|
if (sid && getConfig(promptCwd).policy.untrustedContent?.enabled) {
|
|
74872
75102
|
await notifyUserMentions(sid, extractContentDestinations(prompt));
|
|
74873
75103
|
}
|
|
@@ -74908,8 +75138,8 @@ RAW: ${raw}
|
|
|
74908
75138
|
);
|
|
74909
75139
|
const reason = `\u{1F6A8} Node9 DLP: ${shownPattern} detected in prompt (${shownSample}). Prompt was not submitted \u2014 remove the credential and try again.`;
|
|
74910
75140
|
try {
|
|
74911
|
-
const ttyFd =
|
|
74912
|
-
|
|
75141
|
+
const ttyFd = import_fs75.default.openSync("/dev/tty", "w");
|
|
75142
|
+
import_fs75.default.writeSync(
|
|
74913
75143
|
ttyFd,
|
|
74914
75144
|
import_chalk14.default.bgRed.white.bold(`
|
|
74915
75145
|
\u{1F6A8} NODE9 DLP \u2014 PROMPT BLOCKED
|
|
@@ -74919,7 +75149,7 @@ RAW: ${raw}
|
|
|
74919
75149
|
|
|
74920
75150
|
`)
|
|
74921
75151
|
);
|
|
74922
|
-
|
|
75152
|
+
import_fs75.default.closeSync(ttyFd);
|
|
74923
75153
|
} catch {
|
|
74924
75154
|
}
|
|
74925
75155
|
const isCodex = agent2 === "Codex";
|
|
@@ -74938,17 +75168,17 @@ RAW: ${raw}
|
|
|
74938
75168
|
process.exit(2);
|
|
74939
75169
|
}
|
|
74940
75170
|
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" &&
|
|
75171
|
+
const safeCwdForConfig = typeof payloadCwd === "string" && import_path75.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
|
|
74942
75172
|
const config = getConfig(safeCwdForConfig);
|
|
74943
75173
|
const daemonDown = !isDaemonRunning();
|
|
74944
75174
|
if (config.settings.autoStartDaemon && daemonDown && !process.env.NODE9_NO_AUTO_DAEMON) {
|
|
74945
75175
|
try {
|
|
74946
75176
|
const scriptPath = process.argv[1];
|
|
74947
|
-
if (typeof scriptPath !== "string" || !
|
|
75177
|
+
if (typeof scriptPath !== "string" || !import_path75.default.isAbsolute(scriptPath))
|
|
74948
75178
|
throw new Error("node9: argv[1] is not an absolute path");
|
|
74949
|
-
const resolvedScript =
|
|
74950
|
-
const packageDist =
|
|
74951
|
-
if (!resolvedScript.startsWith(packageDist +
|
|
75179
|
+
const resolvedScript = import_fs75.default.realpathSync(scriptPath);
|
|
75180
|
+
const packageDist = import_fs75.default.realpathSync(import_path75.default.resolve(__dirname, "../.."));
|
|
75181
|
+
if (!resolvedScript.startsWith(packageDist + import_path75.default.sep) && resolvedScript !== packageDist)
|
|
74952
75182
|
throw new Error(
|
|
74953
75183
|
`node9: daemon spawn aborted \u2014 argv[1] (${resolvedScript}) is outside package dist (${packageDist})`
|
|
74954
75184
|
);
|
|
@@ -74978,17 +75208,17 @@ RAW: ${raw}
|
|
|
74978
75208
|
} finally {
|
|
74979
75209
|
if (startupFd !== void 0) {
|
|
74980
75210
|
try {
|
|
74981
|
-
|
|
75211
|
+
import_fs75.default.closeSync(startupFd);
|
|
74982
75212
|
} catch {
|
|
74983
75213
|
}
|
|
74984
75214
|
}
|
|
74985
75215
|
}
|
|
74986
75216
|
} catch (spawnErr) {
|
|
74987
|
-
const logPath =
|
|
75217
|
+
const logPath = import_path75.default.join(import_os62.default.homedir(), ".node9", "hook-debug.log");
|
|
74988
75218
|
const msg = spawnErr instanceof Error ? spawnErr.message : String(spawnErr);
|
|
74989
75219
|
recordStartupState("failed", "spawn-aborted", msg);
|
|
74990
75220
|
try {
|
|
74991
|
-
|
|
75221
|
+
import_fs75.default.appendFileSync(
|
|
74992
75222
|
logPath,
|
|
74993
75223
|
`[${(/* @__PURE__ */ new Date()).toISOString()}] daemon-autostart-failed: ${msg}
|
|
74994
75224
|
`
|
|
@@ -75002,10 +75232,10 @@ RAW: ${raw}
|
|
|
75002
75232
|
);
|
|
75003
75233
|
}
|
|
75004
75234
|
if (process.env.NODE9_DEBUG === "1" || config.settings.enableHookLogDebug) {
|
|
75005
|
-
const logPath =
|
|
75006
|
-
if (!
|
|
75007
|
-
|
|
75008
|
-
|
|
75235
|
+
const logPath = import_path75.default.join(import_os62.default.homedir(), ".node9", "hook-debug.log");
|
|
75236
|
+
if (!import_fs75.default.existsSync(import_path75.default.dirname(logPath)))
|
|
75237
|
+
import_fs75.default.mkdirSync(import_path75.default.dirname(logPath), { recursive: true });
|
|
75238
|
+
import_fs75.default.appendFileSync(
|
|
75009
75239
|
logPath,
|
|
75010
75240
|
`[${(/* @__PURE__ */ new Date()).toISOString()}] STDIN: ${JSON.stringify(raw)}
|
|
75011
75241
|
`
|
|
@@ -75026,8 +75256,8 @@ RAW: ${raw}
|
|
|
75026
75256
|
);
|
|
75027
75257
|
let ttyFd = null;
|
|
75028
75258
|
try {
|
|
75029
|
-
ttyFd =
|
|
75030
|
-
const writeTty = (line) =>
|
|
75259
|
+
ttyFd = import_fs75.default.openSync("/dev/tty", "w");
|
|
75260
|
+
const writeTty = (line) => import_fs75.default.writeSync(ttyFd, line + "\n");
|
|
75031
75261
|
if (result2?.blockKind === "protected-path") {
|
|
75032
75262
|
writeTty(
|
|
75033
75263
|
import_chalk14.default.red.bold(
|
|
@@ -75054,7 +75284,7 @@ RAW: ${raw}
|
|
|
75054
75284
|
} finally {
|
|
75055
75285
|
if (ttyFd !== null)
|
|
75056
75286
|
try {
|
|
75057
|
-
|
|
75287
|
+
import_fs75.default.closeSync(ttyFd);
|
|
75058
75288
|
} catch {
|
|
75059
75289
|
}
|
|
75060
75290
|
}
|
|
@@ -75063,7 +75293,12 @@ RAW: ${raw}
|
|
|
75063
75293
|
humanDecision,
|
|
75064
75294
|
msg,
|
|
75065
75295
|
result2?.recoveryCommand,
|
|
75066
|
-
{
|
|
75296
|
+
{
|
|
75297
|
+
kind: result2?.blockKind,
|
|
75298
|
+
path: result2?.blockedPath,
|
|
75299
|
+
redirect: !!result2?.redirect,
|
|
75300
|
+
ruleDescription: result2?.ruleDescription
|
|
75301
|
+
}
|
|
75067
75302
|
);
|
|
75068
75303
|
if (agent === "Antigravity") {
|
|
75069
75304
|
process.stdout.write(
|
|
@@ -75080,11 +75315,13 @@ RAW: ${raw}
|
|
|
75080
75315
|
);
|
|
75081
75316
|
process.exit(0);
|
|
75082
75317
|
}
|
|
75318
|
+
const userLine = userLineOf(aiFeedbackMessage);
|
|
75083
75319
|
process.stdout.write(
|
|
75084
75320
|
JSON.stringify({
|
|
75085
75321
|
decision: "block",
|
|
75086
75322
|
reason: aiFeedbackMessage,
|
|
75087
75323
|
// This is the core instruction
|
|
75324
|
+
...agent === "Claude Code" && userLine ? { systemMessage: userLine } : {},
|
|
75088
75325
|
hookSpecificOutput: {
|
|
75089
75326
|
hookEventName: "PreToolUse",
|
|
75090
75327
|
permissionDecision: "deny",
|
|
@@ -75118,8 +75355,8 @@ RAW: ${raw}
|
|
|
75118
75355
|
} catch {
|
|
75119
75356
|
}
|
|
75120
75357
|
try {
|
|
75121
|
-
const ttyFd =
|
|
75122
|
-
|
|
75358
|
+
const ttyFd = import_fs75.default.openSync("/dev/tty", "w");
|
|
75359
|
+
import_fs75.default.writeSync(
|
|
75123
75360
|
ttyFd,
|
|
75124
75361
|
import_chalk14.default.yellow(
|
|
75125
75362
|
`
|
|
@@ -75127,7 +75364,7 @@ RAW: ${raw}
|
|
|
75127
75364
|
`
|
|
75128
75365
|
)
|
|
75129
75366
|
);
|
|
75130
|
-
|
|
75367
|
+
import_fs75.default.closeSync(ttyFd);
|
|
75131
75368
|
} catch {
|
|
75132
75369
|
}
|
|
75133
75370
|
if (agent === "GitHub Copilot") {
|
|
@@ -75159,17 +75396,20 @@ RAW: ${raw}
|
|
|
75159
75396
|
const safeSessionId = /^[A-Za-z0-9_\-]{1,128}$/.test(rawSessionId) ? rawSessionId : "";
|
|
75160
75397
|
if (skillPinCfg.enabled && safeSessionId) {
|
|
75161
75398
|
try {
|
|
75162
|
-
const sessionsDir =
|
|
75163
|
-
const flagPath =
|
|
75399
|
+
const sessionsDir = import_path75.default.join(import_os62.default.homedir(), ".node9", "skill-sessions");
|
|
75400
|
+
const flagPath = import_path75.default.join(sessionsDir, `${safeSessionId}${SESSION_FLAG_SUFFIX}`);
|
|
75401
|
+
const memo = ensureOwnDir(sessionsDir);
|
|
75164
75402
|
let flag = null;
|
|
75165
75403
|
try {
|
|
75166
|
-
|
|
75404
|
+
const st = memo ? import_fs75.default.lstatSync(flagPath) : null;
|
|
75405
|
+
if (st && st.isFile() && st.nlink === 1)
|
|
75406
|
+
flag = JSON.parse(import_fs75.default.readFileSync(flagPath, "utf-8"));
|
|
75167
75407
|
} catch {
|
|
75168
75408
|
}
|
|
75169
75409
|
const writeFlag = (data2) => {
|
|
75410
|
+
if (!memo || !isSameOwnDir(sessionsDir, memo)) return;
|
|
75170
75411
|
try {
|
|
75171
|
-
|
|
75172
|
-
import_fs73.default.writeFileSync(
|
|
75412
|
+
atomicWriteSync(
|
|
75173
75413
|
flagPath,
|
|
75174
75414
|
JSON.stringify({ ...data2, timestamp: (/* @__PURE__ */ new Date()).toISOString() }, null, 2),
|
|
75175
75415
|
{ mode: 384 }
|
|
@@ -75180,8 +75420,8 @@ RAW: ${raw}
|
|
|
75180
75420
|
const sendSkillWarn = (detail, recoveryCmd) => {
|
|
75181
75421
|
let ttyFd = null;
|
|
75182
75422
|
try {
|
|
75183
|
-
ttyFd =
|
|
75184
|
-
const w = (line) =>
|
|
75423
|
+
ttyFd = import_fs75.default.openSync("/dev/tty", "w");
|
|
75424
|
+
const w = (line) => import_fs75.default.writeSync(ttyFd, line + "\n");
|
|
75185
75425
|
w(import_chalk14.default.yellow(`
|
|
75186
75426
|
\u26A0\uFE0F Node9: installed skill drift detected`));
|
|
75187
75427
|
w(import_chalk14.default.gray(` ${detail}`));
|
|
@@ -75196,7 +75436,7 @@ RAW: ${raw}
|
|
|
75196
75436
|
} finally {
|
|
75197
75437
|
if (ttyFd !== null)
|
|
75198
75438
|
try {
|
|
75199
|
-
|
|
75439
|
+
import_fs75.default.closeSync(ttyFd);
|
|
75200
75440
|
} catch {
|
|
75201
75441
|
}
|
|
75202
75442
|
}
|
|
@@ -75212,7 +75452,7 @@ RAW: ${raw}
|
|
|
75212
75452
|
return;
|
|
75213
75453
|
}
|
|
75214
75454
|
if (!flag || flag.state !== "verified" && flag.state !== "warned") {
|
|
75215
|
-
const absoluteCwd = typeof payloadCwd === "string" &&
|
|
75455
|
+
const absoluteCwd = typeof payloadCwd === "string" && import_path75.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
|
|
75216
75456
|
const extraRoots = skillPinCfg.roots;
|
|
75217
75457
|
const resolvedExtra = extraRoots.map((r) => resolveUserSkillRoot(r, absoluteCwd)).filter((r) => typeof r === "string");
|
|
75218
75458
|
const roots = [...defaultSkillRoots(absoluteCwd), ...resolvedExtra];
|
|
@@ -75251,31 +75491,27 @@ RAW: ${raw}
|
|
|
75251
75491
|
} else {
|
|
75252
75492
|
writeFlag({ state: "verified" });
|
|
75253
75493
|
}
|
|
75254
|
-
|
|
75255
|
-
|
|
75256
|
-
|
|
75257
|
-
const
|
|
75258
|
-
|
|
75259
|
-
|
|
75260
|
-
} catch {
|
|
75261
|
-
}
|
|
75494
|
+
if (memo)
|
|
75495
|
+
try {
|
|
75496
|
+
const cutoff = Date.now() - 7 * 24 * 60 * 60 * 1e3;
|
|
75497
|
+
for (const name of import_fs75.default.readdirSync(sessionsDir))
|
|
75498
|
+
removeOldFlag(sessionsDir, memo, name, cutoff);
|
|
75499
|
+
} catch {
|
|
75262
75500
|
}
|
|
75263
|
-
} catch {
|
|
75264
|
-
}
|
|
75265
75501
|
}
|
|
75266
75502
|
} catch (err2) {
|
|
75267
75503
|
if (process.env.NODE9_DEBUG === "1") {
|
|
75268
75504
|
try {
|
|
75269
|
-
const dbg =
|
|
75505
|
+
const dbg = import_path75.default.join(import_os62.default.homedir(), ".node9", "hook-debug.log");
|
|
75270
75506
|
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
75271
|
-
|
|
75507
|
+
import_fs75.default.appendFileSync(dbg, `[${(/* @__PURE__ */ new Date()).toISOString()}] SKILL_PIN_ERROR: ${msg}
|
|
75272
75508
|
`);
|
|
75273
75509
|
} catch {
|
|
75274
75510
|
}
|
|
75275
75511
|
}
|
|
75276
75512
|
}
|
|
75277
75513
|
}
|
|
75278
|
-
const safeCwdForAuth = typeof payloadCwd === "string" &&
|
|
75514
|
+
const safeCwdForAuth = typeof payloadCwd === "string" && import_path75.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
|
|
75279
75515
|
const askMode = resolveAskMode(agent, opts, config);
|
|
75280
75516
|
const result = await authorizeHeadless(toolName, toolInput, meta, {
|
|
75281
75517
|
cwd: safeCwdForAuth,
|
|
@@ -75288,11 +75524,21 @@ RAW: ${raw}
|
|
|
75288
75524
|
} catch {
|
|
75289
75525
|
}
|
|
75290
75526
|
}
|
|
75527
|
+
const isSubagentCall = typeof payload.agent_id === "string" && payload.agent_id !== "";
|
|
75528
|
+
const allowExit = (checkedBy) => {
|
|
75529
|
+
if (checkedBy !== "paused" && agent === "Claude Code" && !isSubagentCall && sessionNoticeEnabled() && claimSessionNotice(safeSessionId)) {
|
|
75530
|
+
try {
|
|
75531
|
+
import_fs75.default.writeSync(1, sessionNoticeOutput(config.settings.mode) + "\n");
|
|
75532
|
+
} catch {
|
|
75533
|
+
}
|
|
75534
|
+
}
|
|
75535
|
+
process.exit(0);
|
|
75536
|
+
};
|
|
75291
75537
|
if (result.approved) {
|
|
75292
75538
|
if (result.checkedBy && process.env.NODE9_DEBUG === "1")
|
|
75293
75539
|
process.stderr.write(`\u2713 node9 [${result.checkedBy}]: "${toolName}" allowed
|
|
75294
75540
|
`);
|
|
75295
|
-
|
|
75541
|
+
allowExit(result.checkedBy);
|
|
75296
75542
|
}
|
|
75297
75543
|
if (result.review) {
|
|
75298
75544
|
sendAsk(result);
|
|
@@ -75300,12 +75546,12 @@ RAW: ${raw}
|
|
|
75300
75546
|
}
|
|
75301
75547
|
if (result.noApprovalMechanism && !isDaemonRunning() && !process.env.NODE9_NO_AUTO_DAEMON && !process.stdout.isTTY && config.settings.autoStartDaemon) {
|
|
75302
75548
|
try {
|
|
75303
|
-
const tty =
|
|
75304
|
-
|
|
75549
|
+
const tty = import_fs75.default.openSync("/dev/tty", "w");
|
|
75550
|
+
import_fs75.default.writeSync(
|
|
75305
75551
|
tty,
|
|
75306
75552
|
import_chalk14.default.cyan("\n\u{1F6E1}\uFE0F Node9: Starting approval daemon automatically...\n")
|
|
75307
75553
|
);
|
|
75308
|
-
|
|
75554
|
+
import_fs75.default.closeSync(tty);
|
|
75309
75555
|
} catch {
|
|
75310
75556
|
}
|
|
75311
75557
|
const daemonReady = await autoStartDaemonAndWait();
|
|
@@ -75317,7 +75563,7 @@ RAW: ${raw}
|
|
|
75317
75563
|
if (retry.checkedBy && process.env.NODE9_DEBUG === "1")
|
|
75318
75564
|
process.stderr.write(`\u2713 node9 [${retry.checkedBy}]: "${toolName}" allowed
|
|
75319
75565
|
`);
|
|
75320
|
-
|
|
75566
|
+
allowExit(retry.checkedBy);
|
|
75321
75567
|
}
|
|
75322
75568
|
sendBlock(retry.reason ?? `Node9 blocked "${toolName}".`, {
|
|
75323
75569
|
...retry,
|
|
@@ -75332,9 +75578,9 @@ RAW: ${raw}
|
|
|
75332
75578
|
});
|
|
75333
75579
|
} catch (err2) {
|
|
75334
75580
|
if (process.env.NODE9_DEBUG === "1") {
|
|
75335
|
-
const logPath =
|
|
75581
|
+
const logPath = import_path75.default.join(import_os62.default.homedir(), ".node9", "hook-debug.log");
|
|
75336
75582
|
const errMsg = err2 instanceof Error ? err2.message : String(err2);
|
|
75337
|
-
|
|
75583
|
+
import_fs75.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] ERROR: ${errMsg}
|
|
75338
75584
|
`);
|
|
75339
75585
|
}
|
|
75340
75586
|
process.exit(0);
|
|
@@ -75369,9 +75615,9 @@ RAW: ${raw}
|
|
|
75369
75615
|
|
|
75370
75616
|
// src/cli/commands/log.ts
|
|
75371
75617
|
init_cjs_shims();
|
|
75372
|
-
var
|
|
75373
|
-
var
|
|
75374
|
-
var
|
|
75618
|
+
var import_fs76 = __toESM(require("fs"));
|
|
75619
|
+
var import_path76 = __toESM(require("path"));
|
|
75620
|
+
var import_os63 = __toESM(require("os"));
|
|
75375
75621
|
init_audit();
|
|
75376
75622
|
init_config();
|
|
75377
75623
|
init_daemon();
|
|
@@ -75651,12 +75897,12 @@ function registerLogCommand(program2) {
|
|
|
75651
75897
|
if (rawToolName !== tool) entry.agentToolName = rawToolName;
|
|
75652
75898
|
const payloadSessionId = payload.session_id ?? payload.conversationId;
|
|
75653
75899
|
if (payloadSessionId) entry.sessionId = payloadSessionId;
|
|
75654
|
-
const logPath =
|
|
75655
|
-
if (!
|
|
75656
|
-
|
|
75657
|
-
|
|
75900
|
+
const logPath = import_path76.default.join(import_os63.default.homedir(), ".node9", "audit.log");
|
|
75901
|
+
if (!import_fs76.default.existsSync(import_path76.default.dirname(logPath)))
|
|
75902
|
+
import_fs76.default.mkdirSync(import_path76.default.dirname(logPath), { recursive: true });
|
|
75903
|
+
import_fs76.default.appendFileSync(logPath, JSON.stringify(entry) + "\n");
|
|
75658
75904
|
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" &&
|
|
75905
|
+
const safeCwd = typeof payloadCwd === "string" && import_path76.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
|
|
75660
75906
|
if ((tool === "Bash" || tool === "bash") && isDaemonRunning()) {
|
|
75661
75907
|
const command = typeof rawInput === "object" && rawInput !== null && "command" in rawInput && typeof rawInput.command === "string" ? rawInput.command : null;
|
|
75662
75908
|
if (command) {
|
|
@@ -75877,9 +76123,9 @@ function registerLogCommand(program2) {
|
|
|
75877
76123
|
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
75878
76124
|
process.stderr.write(`[Node9] audit log error: ${msg}
|
|
75879
76125
|
`);
|
|
75880
|
-
const debugPath =
|
|
76126
|
+
const debugPath = import_path76.default.join(import_os63.default.homedir(), ".node9", "hook-debug.log");
|
|
75881
76127
|
try {
|
|
75882
|
-
|
|
76128
|
+
import_fs76.default.appendFileSync(debugPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] LOG_ERROR: ${msg}
|
|
75883
76129
|
`);
|
|
75884
76130
|
} catch {
|
|
75885
76131
|
}
|
|
@@ -75902,9 +76148,9 @@ function registerLogCommand(program2) {
|
|
|
75902
76148
|
});
|
|
75903
76149
|
}
|
|
75904
76150
|
function absolutePathFor(spelled, cwd) {
|
|
75905
|
-
const expanded = spelled === "~" || spelled.startsWith("~/") ?
|
|
75906
|
-
if (
|
|
75907
|
-
return cwd ?
|
|
76151
|
+
const expanded = spelled === "~" || spelled.startsWith("~/") ? import_path76.default.join(import_os63.default.homedir(), spelled.slice(1)) : spelled;
|
|
76152
|
+
if (import_path76.default.isAbsolute(expanded)) return expanded;
|
|
76153
|
+
return cwd ? import_path76.default.resolve(cwd, expanded) : import_path76.default.resolve(expanded);
|
|
75908
76154
|
}
|
|
75909
76155
|
async function carryTaintAcrossWrites(command, cwd) {
|
|
75910
76156
|
let pairs;
|
|
@@ -75923,23 +76169,23 @@ async function carryTaintAcrossWrites(command, cwd) {
|
|
|
75923
76169
|
continue;
|
|
75924
76170
|
}
|
|
75925
76171
|
const sensitive = scanFilePath(src, cwd);
|
|
75926
|
-
if (sensitive) await notifyTaint(dst, `copy:${sensitive.patternName}:${
|
|
76172
|
+
if (sensitive) await notifyTaint(dst, `copy:${sensitive.patternName}:${import_path76.default.basename(src)}`);
|
|
75927
76173
|
}
|
|
75928
76174
|
}
|
|
75929
76175
|
|
|
75930
76176
|
// src/cli/commands/shield.ts
|
|
75931
76177
|
init_cjs_shims();
|
|
75932
76178
|
var import_chalk16 = __toESM(require("chalk"));
|
|
75933
|
-
var
|
|
75934
|
-
var
|
|
75935
|
-
var
|
|
76179
|
+
var import_fs78 = __toESM(require("fs"));
|
|
76180
|
+
var import_path78 = __toESM(require("path"));
|
|
76181
|
+
var import_os64 = __toESM(require("os"));
|
|
75936
76182
|
init_shields();
|
|
75937
76183
|
init_build();
|
|
75938
76184
|
|
|
75939
76185
|
// src/shields/create.ts
|
|
75940
76186
|
init_cjs_shims();
|
|
75941
|
-
var
|
|
75942
|
-
var
|
|
76187
|
+
var import_fs77 = __toESM(require("fs"));
|
|
76188
|
+
var import_path77 = __toESM(require("path"));
|
|
75943
76189
|
init_dist();
|
|
75944
76190
|
init_shields();
|
|
75945
76191
|
init_audit();
|
|
@@ -75959,8 +76205,8 @@ function createShield(def, opts = {}) {
|
|
|
75959
76205
|
error: `"${name}" is a built-in shield \u2014 choose a different name (a user shield with this name would shadow the built-in).`
|
|
75960
76206
|
};
|
|
75961
76207
|
}
|
|
75962
|
-
const filePath =
|
|
75963
|
-
if (!opts.overwrite &&
|
|
76208
|
+
const filePath = import_path77.default.join(USER_SHIELDS_DIR_PATH, `${name}.json`);
|
|
76209
|
+
if (!opts.overwrite && import_fs77.default.existsSync(filePath)) {
|
|
75964
76210
|
return {
|
|
75965
76211
|
ok: false,
|
|
75966
76212
|
error: `Shield "${name}" already exists at ${filePath}. Pass --overwrite to replace it.`
|
|
@@ -76058,8 +76304,8 @@ var COMMUNITY_INDEX_URL = "https://raw.githubusercontent.com/node9ai/node9-proxy
|
|
|
76058
76304
|
function readCloudShields() {
|
|
76059
76305
|
const out = /* @__PURE__ */ new Set();
|
|
76060
76306
|
try {
|
|
76061
|
-
const file2 =
|
|
76062
|
-
const raw = JSON.parse(
|
|
76307
|
+
const file2 = import_path78.default.join(import_os64.default.homedir(), ".node9", "rules-cache.json");
|
|
76308
|
+
const raw = JSON.parse(import_fs78.default.readFileSync(file2, "utf-8"));
|
|
76063
76309
|
for (const r of raw.rules ?? []) {
|
|
76064
76310
|
const rule = r;
|
|
76065
76311
|
const fromSource = rule.source?.startsWith("SHIELD:") ? rule.source.slice("SHIELD:".length).toLowerCase() : void 0;
|
|
@@ -76396,7 +76642,7 @@ function registerShieldCommand(program2) {
|
|
|
76396
76642
|
if (opts.fromFile) {
|
|
76397
76643
|
let raw;
|
|
76398
76644
|
try {
|
|
76399
|
-
raw = JSON.parse(
|
|
76645
|
+
raw = JSON.parse(import_fs78.default.readFileSync(opts.fromFile, "utf-8"));
|
|
76400
76646
|
} catch (err2) {
|
|
76401
76647
|
console.error(
|
|
76402
76648
|
import_chalk16.default.red(`
|
|
@@ -76744,9 +76990,9 @@ init_migrate();
|
|
|
76744
76990
|
// src/cli/commands/doctor.ts
|
|
76745
76991
|
init_cjs_shims();
|
|
76746
76992
|
var import_chalk19 = __toESM(require("chalk"));
|
|
76747
|
-
var
|
|
76748
|
-
var
|
|
76749
|
-
var
|
|
76993
|
+
var import_fs80 = __toESM(require("fs"));
|
|
76994
|
+
var import_path80 = __toESM(require("path"));
|
|
76995
|
+
var import_os66 = __toESM(require("os"));
|
|
76750
76996
|
var import_child_process10 = require("child_process");
|
|
76751
76997
|
init_daemon();
|
|
76752
76998
|
init_build_id();
|
|
@@ -76775,22 +77021,22 @@ init_startup_log();
|
|
|
76775
77021
|
|
|
76776
77022
|
// src/utils/undo-leftovers.ts
|
|
76777
77023
|
init_cjs_shims();
|
|
76778
|
-
var
|
|
76779
|
-
var
|
|
76780
|
-
var
|
|
77024
|
+
var import_fs79 = __toESM(require("fs"));
|
|
77025
|
+
var import_os65 = __toESM(require("os"));
|
|
77026
|
+
var import_path79 = __toESM(require("path"));
|
|
76781
77027
|
function candidates(homeDir2) {
|
|
76782
|
-
const node9Dir =
|
|
77028
|
+
const node9Dir = import_path79.default.join(homeDir2, ".node9");
|
|
76783
77029
|
return [
|
|
76784
|
-
|
|
76785
|
-
|
|
76786
|
-
|
|
77030
|
+
import_path79.default.join(node9Dir, "snapshots"),
|
|
77031
|
+
import_path79.default.join(node9Dir, "snapshots.json"),
|
|
77032
|
+
import_path79.default.join(node9Dir, "undo_latest.txt")
|
|
76787
77033
|
];
|
|
76788
77034
|
}
|
|
76789
|
-
function undoLeftoverPaths(homeDir2 =
|
|
77035
|
+
function undoLeftoverPaths(homeDir2 = import_os65.default.homedir()) {
|
|
76790
77036
|
const found = [];
|
|
76791
77037
|
for (const p of candidates(homeDir2)) {
|
|
76792
77038
|
try {
|
|
76793
|
-
|
|
77039
|
+
import_fs79.default.lstatSync(p);
|
|
76794
77040
|
found.push(p);
|
|
76795
77041
|
} catch (err2) {
|
|
76796
77042
|
if (err2.code !== "ENOENT") found.push(p);
|
|
@@ -76798,11 +77044,11 @@ function undoLeftoverPaths(homeDir2 = import_os64.default.homedir()) {
|
|
|
76798
77044
|
}
|
|
76799
77045
|
return found;
|
|
76800
77046
|
}
|
|
76801
|
-
function purgeUndoLeftovers(homeDir2 =
|
|
77047
|
+
function purgeUndoLeftovers(homeDir2 = import_os65.default.homedir()) {
|
|
76802
77048
|
const out = { deleted: [], skipped: [], failed: [] };
|
|
76803
77049
|
for (const p of undoLeftoverPaths(homeDir2)) {
|
|
76804
77050
|
try {
|
|
76805
|
-
if (
|
|
77051
|
+
if (import_fs79.default.lstatSync(p).isSymbolicLink()) {
|
|
76806
77052
|
out.skipped.push({
|
|
76807
77053
|
path: p,
|
|
76808
77054
|
reason: "is a symlink \u2014 remove it yourself so nothing else is followed"
|
|
@@ -76815,11 +77061,11 @@ function purgeUndoLeftovers(homeDir2 = import_os64.default.homedir()) {
|
|
|
76815
77061
|
}
|
|
76816
77062
|
let reason = null;
|
|
76817
77063
|
try {
|
|
76818
|
-
|
|
77064
|
+
import_fs79.default.rmSync(p, { recursive: true, force: true });
|
|
76819
77065
|
} catch (err2) {
|
|
76820
77066
|
reason = err2.message;
|
|
76821
77067
|
}
|
|
76822
|
-
if (
|
|
77068
|
+
if (import_fs79.default.existsSync(p)) {
|
|
76823
77069
|
out.failed.push({ path: p, reason: reason ?? "still present after removal" });
|
|
76824
77070
|
} else {
|
|
76825
77071
|
out.deleted.push(p);
|
|
@@ -76835,7 +77081,7 @@ function keyRejected(health) {
|
|
|
76835
77081
|
}
|
|
76836
77082
|
function registerDoctorCommand(program2, version2) {
|
|
76837
77083
|
program2.command("doctor").description("Check that Node9 is installed and configured correctly").action(async () => {
|
|
76838
|
-
const homeDir2 =
|
|
77084
|
+
const homeDir2 = import_os66.default.homedir();
|
|
76839
77085
|
let failures = 0;
|
|
76840
77086
|
let warnings = 0;
|
|
76841
77087
|
function pass(msg) {
|
|
@@ -76889,10 +77135,10 @@ function registerDoctorCommand(program2, version2) {
|
|
|
76889
77135
|
"Policy source: workspace config (app.node9.ai) \u2014 local config files govern operational settings only"
|
|
76890
77136
|
);
|
|
76891
77137
|
}
|
|
76892
|
-
const globalConfigPath2 =
|
|
76893
|
-
if (
|
|
77138
|
+
const globalConfigPath2 = import_path80.default.join(homeDir2, ".node9", "config.json");
|
|
77139
|
+
if (import_fs80.default.existsSync(globalConfigPath2)) {
|
|
76894
77140
|
try {
|
|
76895
|
-
JSON.parse(
|
|
77141
|
+
JSON.parse(import_fs80.default.readFileSync(globalConfigPath2, "utf-8"));
|
|
76896
77142
|
pass(
|
|
76897
77143
|
wsGoverned ? "~/.node9/config.json found and valid (policy fields ignored \u2014 workspace governs)" : "~/.node9/config.json found and valid"
|
|
76898
77144
|
);
|
|
@@ -76911,10 +77157,10 @@ function registerDoctorCommand(program2, version2) {
|
|
|
76911
77157
|
"Remove them when ready: node9 undo --purge"
|
|
76912
77158
|
);
|
|
76913
77159
|
}
|
|
76914
|
-
const projectConfigPath =
|
|
76915
|
-
if (
|
|
77160
|
+
const projectConfigPath = import_path80.default.join(process.cwd(), "node9.config.json");
|
|
77161
|
+
if (import_fs80.default.existsSync(projectConfigPath)) {
|
|
76916
77162
|
try {
|
|
76917
|
-
JSON.parse(
|
|
77163
|
+
JSON.parse(import_fs80.default.readFileSync(projectConfigPath, "utf-8"));
|
|
76918
77164
|
pass("node9.config.json found and valid (project)");
|
|
76919
77165
|
} catch {
|
|
76920
77166
|
fail2(
|
|
@@ -76923,8 +77169,8 @@ function registerDoctorCommand(program2, version2) {
|
|
|
76923
77169
|
);
|
|
76924
77170
|
}
|
|
76925
77171
|
}
|
|
76926
|
-
const credsPath =
|
|
76927
|
-
if (
|
|
77172
|
+
const credsPath = import_path80.default.join(homeDir2, ".node9", "credentials.json");
|
|
77173
|
+
if (import_fs80.default.existsSync(credsPath)) {
|
|
76928
77174
|
pass("Cloud credentials found (~/.node9/credentials.json)");
|
|
76929
77175
|
} else {
|
|
76930
77176
|
warn(
|
|
@@ -76978,7 +77224,7 @@ function registerDoctorCommand(program2, version2) {
|
|
|
76978
77224
|
)
|
|
76979
77225
|
);
|
|
76980
77226
|
}
|
|
76981
|
-
const cloudOn =
|
|
77227
|
+
const cloudOn = import_fs80.default.existsSync(import_path80.default.join(homeDir2, ".node9", "credentials.json")) && !!getConfig().settings.approvers?.cloud;
|
|
76982
77228
|
section(cloudOn ? "Daemon" : "Daemon (optional)");
|
|
76983
77229
|
if (isDaemonRunning()) {
|
|
76984
77230
|
pass(
|
|
@@ -77016,7 +77262,7 @@ function registerDoctorCommand(program2, version2) {
|
|
|
77016
77262
|
cloudEnabled: !!getConfig().settings.approvers?.cloud
|
|
77017
77263
|
});
|
|
77018
77264
|
if (autostart) warn(autostart.message, autostart.hint);
|
|
77019
|
-
if (
|
|
77265
|
+
if (import_fs80.default.existsSync(import_path80.default.join(import_os66.default.homedir(), ".node9", "credentials.json")) && getConfig().settings.approvers?.cloud) {
|
|
77020
77266
|
section("Policy sync");
|
|
77021
77267
|
const health = readSyncHealth();
|
|
77022
77268
|
if (keyRejected(health)) {
|
|
@@ -77042,7 +77288,7 @@ function registerDoctorCommand(program2, version2) {
|
|
|
77042
77288
|
try {
|
|
77043
77289
|
const { shipLagBytes: shipLagBytes2, readWatermark: readWatermark2, AUDIT_SHIP_WATERMARK: AUDIT_SHIP_WATERMARK2 } = await Promise.resolve().then(() => (init_audit_shipper(), audit_shipper_exports));
|
|
77044
77290
|
const cfg = getConfig();
|
|
77045
|
-
const creds =
|
|
77291
|
+
const creds = import_fs80.default.existsSync(import_path80.default.join(import_os66.default.homedir(), ".node9", "credentials.json"));
|
|
77046
77292
|
if (!creds) {
|
|
77047
77293
|
warn("Not logged in \u2014 audit rows stay local", "Run: node9 login <api-key>");
|
|
77048
77294
|
} else if (!cfg.settings.approvers.cloud) {
|
|
@@ -77108,10 +77354,10 @@ function registerDoctorCommand(program2, version2) {
|
|
|
77108
77354
|
// src/cli/commands/audit.ts
|
|
77109
77355
|
init_cjs_shims();
|
|
77110
77356
|
var import_chalk20 = __toESM(require("chalk"));
|
|
77111
|
-
var
|
|
77112
|
-
var
|
|
77357
|
+
var import_fs81 = __toESM(require("fs"));
|
|
77358
|
+
var import_path81 = __toESM(require("path"));
|
|
77113
77359
|
init_decision();
|
|
77114
|
-
var
|
|
77360
|
+
var import_os67 = __toESM(require("os"));
|
|
77115
77361
|
function formatRelativeTime(timestamp2) {
|
|
77116
77362
|
const diff = Date.now() - new Date(timestamp2).getTime();
|
|
77117
77363
|
const sec = Math.floor(diff / 1e3);
|
|
@@ -77124,14 +77370,14 @@ function formatRelativeTime(timestamp2) {
|
|
|
77124
77370
|
}
|
|
77125
77371
|
function registerAuditCommand(program2) {
|
|
77126
77372
|
program2.command("audit").description("View local execution audit log").option("--tail <n>", "Number of entries to show", "20").option("--tool <pattern>", "Filter by tool name (substring match)").option("--deny", "Show only denied actions").option("--json", "Output raw JSON").action((options) => {
|
|
77127
|
-
const logPath =
|
|
77128
|
-
if (!
|
|
77373
|
+
const logPath = import_path81.default.join(import_os67.default.homedir(), ".node9", "audit.log");
|
|
77374
|
+
if (!import_fs81.default.existsSync(logPath)) {
|
|
77129
77375
|
console.log(
|
|
77130
77376
|
import_chalk20.default.yellow("No audit logs found. Run node9 with an agent to generate entries.")
|
|
77131
77377
|
);
|
|
77132
77378
|
return;
|
|
77133
77379
|
}
|
|
77134
|
-
const raw =
|
|
77380
|
+
const raw = import_fs81.default.readFileSync(logPath, "utf-8");
|
|
77135
77381
|
const lines = raw.split("\n").filter((l) => l.trim() !== "");
|
|
77136
77382
|
let entries = lines.flatMap((line) => {
|
|
77137
77383
|
try {
|
|
@@ -77194,7 +77440,7 @@ init_cjs_shims();
|
|
|
77194
77440
|
|
|
77195
77441
|
// src/apps/report.ts
|
|
77196
77442
|
init_cjs_shims();
|
|
77197
|
-
var
|
|
77443
|
+
var import_fs82 = __toESM(require("fs"));
|
|
77198
77444
|
init_catalog();
|
|
77199
77445
|
init_dist();
|
|
77200
77446
|
function appsReportLines(file2, activeShields, opts = {}) {
|
|
@@ -77224,17 +77470,17 @@ var AUDIT_TAIL_BYTES2 = 5 * 1024 * 1024;
|
|
|
77224
77470
|
function readTail2(file2) {
|
|
77225
77471
|
let fd;
|
|
77226
77472
|
try {
|
|
77227
|
-
fd =
|
|
77228
|
-
const size =
|
|
77473
|
+
fd = import_fs82.default.openSync(file2, "r");
|
|
77474
|
+
const size = import_fs82.default.fstatSync(fd).size;
|
|
77229
77475
|
const start = Math.max(0, size - AUDIT_TAIL_BYTES2);
|
|
77230
77476
|
const buf = Buffer.alloc(size - start);
|
|
77231
|
-
|
|
77477
|
+
import_fs82.default.readSync(fd, buf, 0, buf.length, start);
|
|
77232
77478
|
const text = buf.toString("utf8");
|
|
77233
77479
|
return start > 0 ? text.slice(text.indexOf("\n") + 1) : text;
|
|
77234
77480
|
} catch {
|
|
77235
77481
|
return "";
|
|
77236
77482
|
} finally {
|
|
77237
|
-
if (fd !== void 0)
|
|
77483
|
+
if (fd !== void 0) import_fs82.default.closeSync(fd);
|
|
77238
77484
|
}
|
|
77239
77485
|
}
|
|
77240
77486
|
function approvalsFromAudit(auditFile, sinceMs) {
|
|
@@ -77289,21 +77535,21 @@ init_detect();
|
|
|
77289
77535
|
|
|
77290
77536
|
// src/apps/nudges.ts
|
|
77291
77537
|
init_cjs_shims();
|
|
77292
|
-
var
|
|
77293
|
-
var
|
|
77294
|
-
var
|
|
77538
|
+
var import_fs83 = __toESM(require("fs"));
|
|
77539
|
+
var import_os68 = __toESM(require("os"));
|
|
77540
|
+
var import_path82 = __toESM(require("path"));
|
|
77295
77541
|
var import_child_process11 = require("child_process");
|
|
77296
77542
|
var UNANSWERED_AT = 3;
|
|
77297
77543
|
var QUESTIONS_AT = 10;
|
|
77298
77544
|
var TEAM_AUTHORS_AT = 2;
|
|
77299
77545
|
var TEAM_PROJECTS = 5;
|
|
77300
77546
|
var GIT_TIMEOUT_MS = 2e3;
|
|
77301
|
-
function nudgesFilePath(home =
|
|
77302
|
-
return
|
|
77547
|
+
function nudgesFilePath(home = import_os68.default.homedir()) {
|
|
77548
|
+
return import_path82.default.join(home, ".node9", "nudges.json");
|
|
77303
77549
|
}
|
|
77304
77550
|
function readShownNudges(home) {
|
|
77305
77551
|
try {
|
|
77306
|
-
const raw = JSON.parse(
|
|
77552
|
+
const raw = JSON.parse(import_fs83.default.readFileSync(nudgesFilePath(home), "utf8"));
|
|
77307
77553
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return /* @__PURE__ */ new Set();
|
|
77308
77554
|
return new Set(
|
|
77309
77555
|
Object.keys(raw).filter(
|
|
@@ -77318,14 +77564,14 @@ function markNudgeShown(key, home, now = /* @__PURE__ */ new Date()) {
|
|
|
77318
77564
|
const file2 = nudgesFilePath(home);
|
|
77319
77565
|
let data = {};
|
|
77320
77566
|
try {
|
|
77321
|
-
const raw = JSON.parse(
|
|
77567
|
+
const raw = JSON.parse(import_fs83.default.readFileSync(file2, "utf8"));
|
|
77322
77568
|
if (raw && typeof raw === "object" && !Array.isArray(raw)) data = raw;
|
|
77323
77569
|
} catch {
|
|
77324
77570
|
}
|
|
77325
77571
|
data[key] = now.toISOString();
|
|
77326
77572
|
try {
|
|
77327
|
-
|
|
77328
|
-
|
|
77573
|
+
import_fs83.default.mkdirSync(import_path82.default.dirname(file2), { recursive: true });
|
|
77574
|
+
import_fs83.default.writeFileSync(file2, JSON.stringify(data, null, 2) + "\n", { mode: 384 });
|
|
77329
77575
|
} catch {
|
|
77330
77576
|
}
|
|
77331
77577
|
}
|
|
@@ -77346,7 +77592,7 @@ function recentAuthorCount(dir2) {
|
|
|
77346
77592
|
}
|
|
77347
77593
|
function teamProject(dirs, countAuthors = recentAuthorCount) {
|
|
77348
77594
|
for (const dir2 of dirs.slice(0, TEAM_PROJECTS)) {
|
|
77349
|
-
if (countAuthors(dir2) >= TEAM_AUTHORS_AT) return
|
|
77595
|
+
if (countAuthors(dir2) >= TEAM_AUTHORS_AT) return import_path82.default.basename(dir2);
|
|
77350
77596
|
}
|
|
77351
77597
|
return void 0;
|
|
77352
77598
|
}
|
|
@@ -77381,9 +77627,9 @@ var import_chalk22 = __toESM(require("chalk"));
|
|
|
77381
77627
|
|
|
77382
77628
|
// src/cli/aggregate/report-audit.ts
|
|
77383
77629
|
init_cjs_shims();
|
|
77384
|
-
var
|
|
77385
|
-
var
|
|
77386
|
-
var
|
|
77630
|
+
var import_fs84 = __toESM(require("fs"));
|
|
77631
|
+
var import_os69 = __toESM(require("os"));
|
|
77632
|
+
var import_path83 = __toESM(require("path"));
|
|
77387
77633
|
init_costSync();
|
|
77388
77634
|
init_litellm();
|
|
77389
77635
|
init_cost_codex();
|
|
@@ -77468,8 +77714,8 @@ function getDateRange(period, now) {
|
|
|
77468
77714
|
}
|
|
77469
77715
|
}
|
|
77470
77716
|
function parseAuditLog(logPath) {
|
|
77471
|
-
if (!
|
|
77472
|
-
const raw =
|
|
77717
|
+
if (!import_fs84.default.existsSync(logPath)) return [];
|
|
77718
|
+
const raw = import_fs84.default.readFileSync(logPath, "utf-8");
|
|
77473
77719
|
return raw.split("\n").flatMap((line) => {
|
|
77474
77720
|
if (!line.trim()) return [];
|
|
77475
77721
|
try {
|
|
@@ -77523,10 +77769,10 @@ function freezeClaudeCost(acc) {
|
|
|
77523
77769
|
};
|
|
77524
77770
|
}
|
|
77525
77771
|
function processClaudeCostProject(proj, projectsDir, start, end, acc) {
|
|
77526
|
-
const projPath =
|
|
77772
|
+
const projPath = import_path83.default.join(projectsDir, proj);
|
|
77527
77773
|
let files;
|
|
77528
77774
|
try {
|
|
77529
|
-
const stat =
|
|
77775
|
+
const stat = import_fs84.default.statSync(projPath);
|
|
77530
77776
|
if (!stat.isDirectory()) return;
|
|
77531
77777
|
files = listSessionFiles(projPath);
|
|
77532
77778
|
} catch {
|
|
@@ -77534,14 +77780,14 @@ function processClaudeCostProject(proj, projectsDir, start, end, acc) {
|
|
|
77534
77780
|
}
|
|
77535
77781
|
const startMs = start.getTime();
|
|
77536
77782
|
for (const file2 of files) {
|
|
77537
|
-
const filePath =
|
|
77783
|
+
const filePath = import_path83.default.join(projPath, file2);
|
|
77538
77784
|
try {
|
|
77539
|
-
if (
|
|
77785
|
+
if (import_fs84.default.statSync(filePath).mtimeMs < startMs) continue;
|
|
77540
77786
|
} catch {
|
|
77541
77787
|
continue;
|
|
77542
77788
|
}
|
|
77543
77789
|
try {
|
|
77544
|
-
const raw =
|
|
77790
|
+
const raw = import_fs84.default.readFileSync(filePath, "utf-8");
|
|
77545
77791
|
for (const line of raw.split("\n")) {
|
|
77546
77792
|
if (!line.trim()) continue;
|
|
77547
77793
|
let entry;
|
|
@@ -77591,10 +77837,10 @@ function processClaudeCostProject(proj, projectsDir, start, end, acc) {
|
|
|
77591
77837
|
}
|
|
77592
77838
|
function loadClaudeCost(start, end, projectsDir) {
|
|
77593
77839
|
const acc = emptyClaudeCostAccumulator();
|
|
77594
|
-
if (!
|
|
77840
|
+
if (!import_fs84.default.existsSync(projectsDir)) return freezeClaudeCost(acc);
|
|
77595
77841
|
let dirs;
|
|
77596
77842
|
try {
|
|
77597
|
-
dirs =
|
|
77843
|
+
dirs = import_fs84.default.readdirSync(projectsDir);
|
|
77598
77844
|
} catch {
|
|
77599
77845
|
return freezeClaudeCost(acc);
|
|
77600
77846
|
}
|
|
@@ -77606,7 +77852,7 @@ function loadClaudeCost(start, end, projectsDir) {
|
|
|
77606
77852
|
function processCodexCostFile(filePath, start, end, acc) {
|
|
77607
77853
|
let lines;
|
|
77608
77854
|
try {
|
|
77609
|
-
lines =
|
|
77855
|
+
lines = import_fs84.default.readFileSync(filePath, "utf-8").split("\n");
|
|
77610
77856
|
} catch {
|
|
77611
77857
|
return;
|
|
77612
77858
|
}
|
|
@@ -77681,13 +77927,13 @@ function freezeGeminiCost(acc) {
|
|
|
77681
77927
|
function processGeminiCostFile(filePath, projectKey, start, end, acc) {
|
|
77682
77928
|
const startMs = start.getTime();
|
|
77683
77929
|
try {
|
|
77684
|
-
if (
|
|
77930
|
+
if (import_fs84.default.statSync(filePath).mtimeMs < startMs) return;
|
|
77685
77931
|
} catch {
|
|
77686
77932
|
return;
|
|
77687
77933
|
}
|
|
77688
77934
|
let raw;
|
|
77689
77935
|
try {
|
|
77690
|
-
raw =
|
|
77936
|
+
raw = import_fs84.default.readFileSync(filePath, "utf-8");
|
|
77691
77937
|
} catch {
|
|
77692
77938
|
return;
|
|
77693
77939
|
}
|
|
@@ -77736,30 +77982,30 @@ function listGeminiSessionFiles2(geminiTmpDir2) {
|
|
|
77736
77982
|
const out = [];
|
|
77737
77983
|
let dirs;
|
|
77738
77984
|
try {
|
|
77739
|
-
if (!
|
|
77740
|
-
dirs =
|
|
77985
|
+
if (!import_fs84.default.statSync(geminiTmpDir2).isDirectory()) return out;
|
|
77986
|
+
dirs = import_fs84.default.readdirSync(geminiTmpDir2);
|
|
77741
77987
|
} catch {
|
|
77742
77988
|
return out;
|
|
77743
77989
|
}
|
|
77744
77990
|
for (const proj of dirs) {
|
|
77745
|
-
const chatsDir =
|
|
77991
|
+
const chatsDir = import_path83.default.join(geminiTmpDir2, proj, "chats");
|
|
77746
77992
|
let files;
|
|
77747
77993
|
try {
|
|
77748
|
-
if (!
|
|
77749
|
-
files =
|
|
77994
|
+
if (!import_fs84.default.statSync(chatsDir).isDirectory()) continue;
|
|
77995
|
+
files = import_fs84.default.readdirSync(chatsDir);
|
|
77750
77996
|
} catch {
|
|
77751
77997
|
continue;
|
|
77752
77998
|
}
|
|
77753
77999
|
for (const f of files) {
|
|
77754
78000
|
if (!f.endsWith(".jsonl")) continue;
|
|
77755
|
-
out.push({ projectKey: proj, file:
|
|
78001
|
+
out.push({ projectKey: proj, file: import_path83.default.join(chatsDir, f) });
|
|
77756
78002
|
}
|
|
77757
78003
|
}
|
|
77758
78004
|
return out;
|
|
77759
78005
|
}
|
|
77760
78006
|
function loadGeminiCost(start, end, geminiTmpDir2) {
|
|
77761
78007
|
const acc = emptyGeminiAccumulator();
|
|
77762
|
-
if (!
|
|
78008
|
+
if (!import_fs84.default.existsSync(geminiTmpDir2)) return freezeGeminiCost(acc);
|
|
77763
78009
|
for (const { projectKey, file: file2 } of listGeminiSessionFiles2(geminiTmpDir2)) {
|
|
77764
78010
|
processGeminiCostFile(file2, projectKey, start, end, acc);
|
|
77765
78011
|
}
|
|
@@ -77780,11 +78026,11 @@ function dimensionOfBlock(checkedBy, ruleName) {
|
|
|
77780
78026
|
}
|
|
77781
78027
|
function aggregateReportFromAudit(period, opts = {}) {
|
|
77782
78028
|
const now = opts.now ?? /* @__PURE__ */ new Date();
|
|
77783
|
-
const auditLogPath = opts.auditLogPath ??
|
|
77784
|
-
const claudeProjectsDir = opts.claudeProjectsDir ??
|
|
78029
|
+
const auditLogPath = opts.auditLogPath ?? import_path83.default.join(import_os69.default.homedir(), ".node9", "audit.log");
|
|
78030
|
+
const claudeProjectsDir = opts.claudeProjectsDir ?? import_path83.default.join(import_os69.default.homedir(), ".claude", "projects");
|
|
77785
78031
|
const codexSessionsDir2 = opts.codexSessionsDir ?? codexSessionsDir();
|
|
77786
|
-
const geminiTmpDir2 = opts.geminiTmpDir ??
|
|
77787
|
-
const hasAuditFile =
|
|
78032
|
+
const geminiTmpDir2 = opts.geminiTmpDir ?? import_path83.default.join(import_os69.default.homedir(), ".gemini", "tmp");
|
|
78033
|
+
const hasAuditFile = import_fs84.default.existsSync(auditLogPath);
|
|
77788
78034
|
const allEntries = opts.preloadedAuditEntries ?? parseAuditLog(auditLogPath);
|
|
77789
78035
|
const unackedDlp = allEntries.filter((e) => e.source === "response-dlp");
|
|
77790
78036
|
const { start, end } = getDateRange(period, now);
|
|
@@ -78070,10 +78316,10 @@ function buildReportJson(input) {
|
|
|
78070
78316
|
// src/cli/commands/sessions.ts
|
|
78071
78317
|
init_cjs_shims();
|
|
78072
78318
|
var import_chalk21 = __toESM(require("chalk"));
|
|
78073
|
-
var
|
|
78074
|
-
var
|
|
78319
|
+
var import_fs85 = __toESM(require("fs"));
|
|
78320
|
+
var import_path84 = __toESM(require("path"));
|
|
78075
78321
|
init_decision();
|
|
78076
|
-
var
|
|
78322
|
+
var import_os70 = __toESM(require("os"));
|
|
78077
78323
|
init_scan_summary();
|
|
78078
78324
|
init_litellm();
|
|
78079
78325
|
init_cost_gemini();
|
|
@@ -78094,10 +78340,10 @@ function encodeProjectPath(projectPath) {
|
|
|
78094
78340
|
}
|
|
78095
78341
|
function sessionJsonlPath(projectPath, sessionId) {
|
|
78096
78342
|
const encoded = encodeProjectPath(projectPath);
|
|
78097
|
-
return
|
|
78343
|
+
return import_path84.default.join(import_os70.default.homedir(), ".claude", "projects", encoded, `${sessionId}.jsonl`);
|
|
78098
78344
|
}
|
|
78099
78345
|
function projectLabel(projectPath) {
|
|
78100
|
-
return projectPath.replace(
|
|
78346
|
+
return projectPath.replace(import_os70.default.homedir(), "~");
|
|
78101
78347
|
}
|
|
78102
78348
|
function parseHistoryLines(lines) {
|
|
78103
78349
|
const entries = [];
|
|
@@ -78166,10 +78412,10 @@ function parseSessionLines(lines) {
|
|
|
78166
78412
|
return { toolCalls, costUSD, hasSnapshot, modifiedFiles };
|
|
78167
78413
|
}
|
|
78168
78414
|
function loadAuditEntries(auditPath) {
|
|
78169
|
-
const aPath = auditPath ??
|
|
78415
|
+
const aPath = auditPath ?? import_path84.default.join(import_os70.default.homedir(), ".node9", "audit.log");
|
|
78170
78416
|
let raw;
|
|
78171
78417
|
try {
|
|
78172
|
-
raw =
|
|
78418
|
+
raw = import_fs85.default.readFileSync(aPath, "utf-8");
|
|
78173
78419
|
} catch {
|
|
78174
78420
|
return [];
|
|
78175
78421
|
}
|
|
@@ -78205,8 +78451,8 @@ function auditEntriesInWindow(entries, windowStart, windowEnd) {
|
|
|
78205
78451
|
return result;
|
|
78206
78452
|
}
|
|
78207
78453
|
function buildGeminiSessions(days, allAuditEntries) {
|
|
78208
|
-
const tmpDir =
|
|
78209
|
-
if (!
|
|
78454
|
+
const tmpDir = import_path84.default.join(import_os70.default.homedir(), ".gemini", "tmp");
|
|
78455
|
+
if (!import_fs85.default.existsSync(tmpDir)) return [];
|
|
78210
78456
|
const cutoff = days !== null ? (() => {
|
|
78211
78457
|
const d = /* @__PURE__ */ new Date();
|
|
78212
78458
|
d.setDate(d.getDate() - days);
|
|
@@ -78215,35 +78461,35 @@ function buildGeminiSessions(days, allAuditEntries) {
|
|
|
78215
78461
|
})() : null;
|
|
78216
78462
|
let slugDirs;
|
|
78217
78463
|
try {
|
|
78218
|
-
slugDirs =
|
|
78464
|
+
slugDirs = import_fs85.default.readdirSync(tmpDir);
|
|
78219
78465
|
} catch {
|
|
78220
78466
|
return [];
|
|
78221
78467
|
}
|
|
78222
78468
|
const summaries = [];
|
|
78223
78469
|
for (const slug2 of slugDirs) {
|
|
78224
|
-
const slugPath =
|
|
78470
|
+
const slugPath = import_path84.default.join(tmpDir, slug2);
|
|
78225
78471
|
try {
|
|
78226
|
-
if (!
|
|
78472
|
+
if (!import_fs85.default.statSync(slugPath).isDirectory()) continue;
|
|
78227
78473
|
} catch {
|
|
78228
78474
|
continue;
|
|
78229
78475
|
}
|
|
78230
|
-
let projectRoot =
|
|
78476
|
+
let projectRoot = import_path84.default.join(import_os70.default.homedir(), slug2);
|
|
78231
78477
|
try {
|
|
78232
|
-
projectRoot =
|
|
78478
|
+
projectRoot = import_fs85.default.readFileSync(import_path84.default.join(slugPath, ".project_root"), "utf-8").trim();
|
|
78233
78479
|
} catch {
|
|
78234
78480
|
}
|
|
78235
|
-
const chatsDir =
|
|
78236
|
-
if (!
|
|
78481
|
+
const chatsDir = import_path84.default.join(slugPath, "chats");
|
|
78482
|
+
if (!import_fs85.default.existsSync(chatsDir)) continue;
|
|
78237
78483
|
let chatFiles;
|
|
78238
78484
|
try {
|
|
78239
|
-
chatFiles =
|
|
78485
|
+
chatFiles = import_fs85.default.readdirSync(chatsDir).filter((f) => f.endsWith(".json"));
|
|
78240
78486
|
} catch {
|
|
78241
78487
|
continue;
|
|
78242
78488
|
}
|
|
78243
78489
|
for (const chatFile of chatFiles) {
|
|
78244
78490
|
let raw;
|
|
78245
78491
|
try {
|
|
78246
|
-
raw =
|
|
78492
|
+
raw = import_fs85.default.readFileSync(import_path84.default.join(chatsDir, chatFile), "utf-8");
|
|
78247
78493
|
} catch {
|
|
78248
78494
|
continue;
|
|
78249
78495
|
}
|
|
@@ -78334,7 +78580,7 @@ function buildCodexSessions(days, allAuditEntries) {
|
|
|
78334
78580
|
for (const filePath of jsonlFiles) {
|
|
78335
78581
|
let lines;
|
|
78336
78582
|
try {
|
|
78337
|
-
lines =
|
|
78583
|
+
lines = import_fs85.default.readFileSync(filePath, "utf-8").split("\n");
|
|
78338
78584
|
} catch {
|
|
78339
78585
|
continue;
|
|
78340
78586
|
}
|
|
@@ -78405,10 +78651,10 @@ function buildCodexSessions(days, allAuditEntries) {
|
|
|
78405
78651
|
return summaries;
|
|
78406
78652
|
}
|
|
78407
78653
|
function buildSessions(days, historyPath) {
|
|
78408
|
-
const hPath = historyPath ??
|
|
78654
|
+
const hPath = historyPath ?? import_path84.default.join(import_os70.default.homedir(), ".claude", "history.jsonl");
|
|
78409
78655
|
let historyRaw = "";
|
|
78410
78656
|
try {
|
|
78411
|
-
historyRaw =
|
|
78657
|
+
historyRaw = import_fs85.default.readFileSync(hPath, "utf-8");
|
|
78412
78658
|
} catch {
|
|
78413
78659
|
}
|
|
78414
78660
|
const cutoff = days !== null ? (() => {
|
|
@@ -78432,7 +78678,7 @@ function buildSessions(days, historyPath) {
|
|
|
78432
78678
|
const jsonlFile = sessionJsonlPath(entry.project, entry.sessionId);
|
|
78433
78679
|
let sessionLines = [];
|
|
78434
78680
|
try {
|
|
78435
|
-
sessionLines =
|
|
78681
|
+
sessionLines = import_fs85.default.readFileSync(jsonlFile, "utf-8").split("\n");
|
|
78436
78682
|
} catch {
|
|
78437
78683
|
}
|
|
78438
78684
|
const { toolCalls, costUSD, hasSnapshot, modifiedFiles } = parseSessionLines(sessionLines);
|
|
@@ -79223,7 +79469,7 @@ init_cjs_shims();
|
|
|
79223
79469
|
var import_chalk23 = __toESM(require("chalk"));
|
|
79224
79470
|
var import_child_process12 = require("child_process");
|
|
79225
79471
|
init_daemon();
|
|
79226
|
-
var
|
|
79472
|
+
var import_fs86 = __toESM(require("fs"));
|
|
79227
79473
|
init_startup_log();
|
|
79228
79474
|
init_daemon3();
|
|
79229
79475
|
init_service();
|
|
@@ -79300,7 +79546,7 @@ function registerDaemonCommand(program2) {
|
|
|
79300
79546
|
child.unref();
|
|
79301
79547
|
if (restartFd !== void 0) {
|
|
79302
79548
|
try {
|
|
79303
|
-
|
|
79549
|
+
import_fs86.default.closeSync(restartFd);
|
|
79304
79550
|
} catch {
|
|
79305
79551
|
}
|
|
79306
79552
|
}
|
|
@@ -79351,7 +79597,7 @@ function registerDaemonCommand(program2) {
|
|
|
79351
79597
|
} finally {
|
|
79352
79598
|
if (startupFd !== void 0) {
|
|
79353
79599
|
try {
|
|
79354
|
-
|
|
79600
|
+
import_fs86.default.closeSync(startupFd);
|
|
79355
79601
|
} catch {
|
|
79356
79602
|
}
|
|
79357
79603
|
}
|
|
@@ -79366,9 +79612,9 @@ function registerDaemonCommand(program2) {
|
|
|
79366
79612
|
// src/cli/commands/status.ts
|
|
79367
79613
|
init_cjs_shims();
|
|
79368
79614
|
var import_chalk24 = __toESM(require("chalk"));
|
|
79369
|
-
var
|
|
79370
|
-
var
|
|
79371
|
-
var
|
|
79615
|
+
var import_fs87 = __toESM(require("fs"));
|
|
79616
|
+
var import_path85 = __toESM(require("path"));
|
|
79617
|
+
var import_os71 = __toESM(require("os"));
|
|
79372
79618
|
init_core();
|
|
79373
79619
|
init_daemon();
|
|
79374
79620
|
init_build_id();
|
|
@@ -79469,20 +79715,20 @@ function registerStatusCommand(program2) {
|
|
|
79469
79715
|
console.log(` Policy: ${import_chalk24.default.cyan("Workspace config (app.node9.ai)")}`);
|
|
79470
79716
|
}
|
|
79471
79717
|
const ignoredLabel = import_chalk24.default.gray("Present \u2014 ignored (workspace config governs)");
|
|
79472
|
-
const projectConfig =
|
|
79473
|
-
const globalConfig =
|
|
79718
|
+
const projectConfig = import_path85.default.join(process.cwd(), "node9.config.json");
|
|
79719
|
+
const globalConfig = import_path85.default.join(import_os71.default.homedir(), ".node9", "config.json");
|
|
79474
79720
|
console.log(
|
|
79475
|
-
` Local: ${
|
|
79721
|
+
` Local: ${import_fs87.default.existsSync(projectConfig) ? wsGoverned ? ignoredLabel : import_chalk24.default.green("Active (node9.config.json)") : import_chalk24.default.gray("Not present")}`
|
|
79476
79722
|
);
|
|
79477
79723
|
console.log(
|
|
79478
|
-
` Global: ${
|
|
79724
|
+
` Global: ${import_fs87.default.existsSync(globalConfig) ? wsGoverned ? ignoredLabel : import_chalk24.default.green("Active (~/.node9/config.json)") : import_chalk24.default.gray("Not present")}`
|
|
79479
79725
|
);
|
|
79480
79726
|
if (mergedConfig.policy.sandboxPaths.length > 0) {
|
|
79481
79727
|
console.log(
|
|
79482
79728
|
` Sandbox: ${import_chalk24.default.green(`${mergedConfig.policy.sandboxPaths.length} safe zones active`)}`
|
|
79483
79729
|
);
|
|
79484
79730
|
}
|
|
79485
|
-
const wiring = getAgentWiring(
|
|
79731
|
+
const wiring = getAgentWiring(import_os71.default.homedir()).filter((a) => a.present);
|
|
79486
79732
|
if (wiring.length > 0) {
|
|
79487
79733
|
console.log("");
|
|
79488
79734
|
console.log(import_chalk24.default.bold(" Agent Wiring:"));
|
|
@@ -79501,7 +79747,7 @@ function registerStatusCommand(program2) {
|
|
|
79501
79747
|
a.mcpServers
|
|
79502
79748
|
);
|
|
79503
79749
|
if (a.id === "codex" && a.hooks.some((h) => h.wired)) {
|
|
79504
|
-
const t = assessCodexTrust(
|
|
79750
|
+
const t = assessCodexTrust(import_os71.default.homedir());
|
|
79505
79751
|
if (t.state === "observed") {
|
|
79506
79752
|
console.log(
|
|
79507
79753
|
import_chalk24.default.green(
|
|
@@ -79545,7 +79791,7 @@ init_init();
|
|
|
79545
79791
|
// src/cli/commands/heal.ts
|
|
79546
79792
|
init_cjs_shims();
|
|
79547
79793
|
var import_chalk25 = __toESM(require("chalk"));
|
|
79548
|
-
var
|
|
79794
|
+
var import_fs90 = __toESM(require("fs"));
|
|
79549
79795
|
init_agent_wiring();
|
|
79550
79796
|
init_mcp_wrap();
|
|
79551
79797
|
init_setup();
|
|
@@ -79553,7 +79799,7 @@ init_hook_baseline();
|
|
|
79553
79799
|
var hasHookSurface = (a) => a.hooks.length > 0;
|
|
79554
79800
|
function backupForHeal(file2) {
|
|
79555
79801
|
try {
|
|
79556
|
-
if (file2 &&
|
|
79802
|
+
if (file2 && import_fs90.default.existsSync(file2)) import_fs90.default.copyFileSync(file2, `${file2}.node9-heal-bak`);
|
|
79557
79803
|
} catch {
|
|
79558
79804
|
}
|
|
79559
79805
|
}
|
|
@@ -80174,7 +80420,12 @@ async function runMcpGateway(upstreamCommand, configName) {
|
|
|
80174
80420
|
humanDecision,
|
|
80175
80421
|
result.reason,
|
|
80176
80422
|
void 0,
|
|
80177
|
-
{
|
|
80423
|
+
{
|
|
80424
|
+
kind: result.blockKind,
|
|
80425
|
+
path: result.blockedPath,
|
|
80426
|
+
redirect: !!result.redirect,
|
|
80427
|
+
ruleDescription: result.ruleDescription
|
|
80428
|
+
}
|
|
80178
80429
|
);
|
|
80179
80430
|
const errorResponse = {
|
|
80180
80431
|
jsonrpc: "2.0",
|
|
@@ -80518,9 +80769,9 @@ init_cjs_shims();
|
|
|
80518
80769
|
init_cjs_shims();
|
|
80519
80770
|
var import_readline4 = __toESM(require("readline"));
|
|
80520
80771
|
init_write();
|
|
80521
|
-
var
|
|
80522
|
-
var
|
|
80523
|
-
var
|
|
80772
|
+
var import_fs91 = __toESM(require("fs"));
|
|
80773
|
+
var import_os76 = __toESM(require("os"));
|
|
80774
|
+
var import_path90 = __toESM(require("path"));
|
|
80524
80775
|
var import_child_process14 = require("child_process");
|
|
80525
80776
|
init_decision();
|
|
80526
80777
|
init_core();
|
|
@@ -81071,14 +81322,14 @@ function handleStatus() {
|
|
|
81071
81322
|
const state = !a.installed ? "not installed" : hooked ? "wired" : a.isProtected ? "protected through MCP" : "not wired";
|
|
81072
81323
|
lines.push(` ${a.label}: ${state}`);
|
|
81073
81324
|
}
|
|
81074
|
-
const projectConfig =
|
|
81075
|
-
const globalConfig =
|
|
81325
|
+
const projectConfig = import_path90.default.join(process.cwd(), "node9.config.json");
|
|
81326
|
+
const globalConfig = import_path90.default.join(import_os76.default.homedir(), ".node9", "config.json");
|
|
81076
81327
|
const presentLabel = wsGoverned ? "present \u2014 ignored (workspace config governs)" : "present";
|
|
81077
81328
|
lines.push(
|
|
81078
|
-
`Project config (node9.config.json): ${
|
|
81329
|
+
`Project config (node9.config.json): ${import_fs91.default.existsSync(projectConfig) ? presentLabel : "not found"}`
|
|
81079
81330
|
);
|
|
81080
81331
|
lines.push(
|
|
81081
|
-
`Global config (~/.node9/config.json): ${
|
|
81332
|
+
`Global config (~/.node9/config.json): ${import_fs91.default.existsSync(globalConfig) ? presentLabel : "not found"}`
|
|
81082
81333
|
);
|
|
81083
81334
|
return lines.join("\n");
|
|
81084
81335
|
}
|
|
@@ -81215,7 +81466,7 @@ function handleEgressDeny(args) {
|
|
|
81215
81466
|
addEgressHost("deny", host2);
|
|
81216
81467
|
return `Denied egress to ${host2} (deny always wins over allow).`;
|
|
81217
81468
|
}
|
|
81218
|
-
var GLOBAL_CONFIG_PATH2 =
|
|
81469
|
+
var GLOBAL_CONFIG_PATH2 = import_path90.default.join(import_os76.default.homedir(), ".node9", "config.json");
|
|
81219
81470
|
var APPROVER_CHANNELS2 = ["native", "browser", "cloud", "terminal"];
|
|
81220
81471
|
function handleApproverList() {
|
|
81221
81472
|
const config = getConfig();
|
|
@@ -81256,9 +81507,9 @@ function handleApproverSet(args) {
|
|
|
81256
81507
|
function handleAuditGet(args) {
|
|
81257
81508
|
const limit = Math.min(typeof args.limit === "number" ? args.limit : 20, 100);
|
|
81258
81509
|
const filter = typeof args.filter === "string" && args.filter !== "all" ? args.filter : null;
|
|
81259
|
-
const auditPath =
|
|
81260
|
-
if (!
|
|
81261
|
-
const rawLines =
|
|
81510
|
+
const auditPath = import_path90.default.join(import_os76.default.homedir(), ".node9", "audit.log");
|
|
81511
|
+
if (!import_fs91.default.existsSync(auditPath)) return "No audit log found.";
|
|
81512
|
+
const rawLines = import_fs91.default.readFileSync(auditPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
81262
81513
|
const wanted = filter === "block" ? "deny" : filter;
|
|
81263
81514
|
const parsed = [];
|
|
81264
81515
|
for (const line of rawLines) {
|
|
@@ -81618,7 +81869,7 @@ function registerTrustCommand(program2) {
|
|
|
81618
81869
|
init_cjs_shims();
|
|
81619
81870
|
var import_chalk32 = __toESM(require("chalk"));
|
|
81620
81871
|
init_mcp_pin();
|
|
81621
|
-
var
|
|
81872
|
+
var import_fs92 = __toESM(require("fs"));
|
|
81622
81873
|
|
|
81623
81874
|
// src/cli/commands/mcp-gateway-cmd.ts
|
|
81624
81875
|
init_cjs_shims();
|
|
@@ -81827,7 +82078,7 @@ function registerMcpPinCommand(program2) {
|
|
|
81827
82078
|
let repoCorrupt = false;
|
|
81828
82079
|
if (found.source === "repo") {
|
|
81829
82080
|
try {
|
|
81830
|
-
const raw =
|
|
82081
|
+
const raw = import_fs92.default.readFileSync(found.path, "utf-8");
|
|
81831
82082
|
const parsed = JSON.parse(raw);
|
|
81832
82083
|
repoEntries = parsed.servers ?? {};
|
|
81833
82084
|
} catch {
|
|
@@ -82279,8 +82530,8 @@ init_cjs_shims();
|
|
|
82279
82530
|
|
|
82280
82531
|
// src/ci-check/fetch.ts
|
|
82281
82532
|
init_cjs_shims();
|
|
82282
|
-
var
|
|
82283
|
-
var
|
|
82533
|
+
var import_fs93 = __toESM(require("fs"));
|
|
82534
|
+
var import_path91 = __toESM(require("path"));
|
|
82284
82535
|
var import_node_child_process = require("child_process");
|
|
82285
82536
|
var import_undici = __toESM(require_undici());
|
|
82286
82537
|
|
|
@@ -82480,8 +82731,8 @@ function isOfficialInstaller(u) {
|
|
|
82480
82731
|
if (u.username || u.password) return false;
|
|
82481
82732
|
const host2 = u.hostname.toLowerCase().replace(/^www\./, "");
|
|
82482
82733
|
if (OFFICIAL_HOSTS.has(host2)) return true;
|
|
82483
|
-
const
|
|
82484
|
-
return !!
|
|
82734
|
+
const path110 = OFFICIAL_PATHS[host2];
|
|
82735
|
+
return !!path110 && path110.test(u.pathname);
|
|
82485
82736
|
}
|
|
82486
82737
|
function onlyOfficialInstaller(s) {
|
|
82487
82738
|
const urls = s.match(URL_RE3);
|
|
@@ -82672,21 +82923,21 @@ function appSkillDirsOf(paths, skillDirs) {
|
|
|
82672
82923
|
}
|
|
82673
82924
|
return apps;
|
|
82674
82925
|
}
|
|
82675
|
-
function isSkillSupportFile(
|
|
82676
|
-
if (!
|
|
82677
|
-
for (let d =
|
|
82678
|
-
const dir2 =
|
|
82926
|
+
function isSkillSupportFile(path110, skillDirs, appDirs) {
|
|
82927
|
+
if (!path110.endsWith(".md") || /(^|\/)[Ss][Kk][Ii][Ll][Ll]\.md$/.test(path110)) return false;
|
|
82928
|
+
for (let d = path110.lastIndexOf("/"); d > 0; d = path110.lastIndexOf("/", d - 1)) {
|
|
82929
|
+
const dir2 = path110.slice(0, d);
|
|
82679
82930
|
if (!skillDirs.has(dir2)) continue;
|
|
82680
|
-
return !appDirs?.has(dir2) || SKILL_LAYOUT_RE.test(
|
|
82931
|
+
return !appDirs?.has(dir2) || SKILL_LAYOUT_RE.test(path110.slice(d + 1));
|
|
82681
82932
|
}
|
|
82682
82933
|
return false;
|
|
82683
82934
|
}
|
|
82684
|
-
function isAppDoc(
|
|
82685
|
-
if (!
|
|
82686
|
-
for (let d =
|
|
82687
|
-
const dir2 =
|
|
82935
|
+
function isAppDoc(path110, skillDirs, appDirs) {
|
|
82936
|
+
if (!path110.endsWith(".md") || INSTRUCTION_FILE_RE.test(path110)) return false;
|
|
82937
|
+
for (let d = path110.lastIndexOf("/"); d > 0; d = path110.lastIndexOf("/", d - 1)) {
|
|
82938
|
+
const dir2 = path110.slice(0, d);
|
|
82688
82939
|
if (!skillDirs.has(dir2)) continue;
|
|
82689
|
-
return appDirs.has(dir2) && !SKILL_LAYOUT_RE.test(
|
|
82940
|
+
return appDirs.has(dir2) && !SKILL_LAYOUT_RE.test(path110.slice(d + 1));
|
|
82690
82941
|
}
|
|
82691
82942
|
return false;
|
|
82692
82943
|
}
|
|
@@ -82709,20 +82960,20 @@ function namedDocs(dir2, skillMd) {
|
|
|
82709
82960
|
return out;
|
|
82710
82961
|
}
|
|
82711
82962
|
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 =
|
|
82963
|
+
function isHookScript(path110) {
|
|
82964
|
+
return /(^|\/)\.claude\/hooks\/.+/.test(path110) && SCRIPT_EXT_RE.test(path110);
|
|
82965
|
+
}
|
|
82966
|
+
function isSkillScript(path110, skillDirs) {
|
|
82967
|
+
if (!SCRIPT_EXT_RE.test(path110)) return false;
|
|
82968
|
+
for (let d = path110.lastIndexOf("/"); d > 0; d = path110.lastIndexOf("/", d - 1)) {
|
|
82969
|
+
if (!skillDirs.has(path110.slice(0, d))) continue;
|
|
82970
|
+
const rel = path110.slice(d + 1);
|
|
82720
82971
|
return !rel.includes("/") || /^(scripts|bin)\//.test(rel);
|
|
82721
82972
|
}
|
|
82722
82973
|
return false;
|
|
82723
82974
|
}
|
|
82724
|
-
function isInstructionFile(
|
|
82725
|
-
return INSTRUCTION_FILE_RE.test(
|
|
82975
|
+
function isInstructionFile(path110, skillDirs, appDirs) {
|
|
82976
|
+
return INSTRUCTION_FILE_RE.test(path110) || isSkillSupportFile(path110, skillDirs, appDirs);
|
|
82726
82977
|
}
|
|
82727
82978
|
var OVERRIDE_RE = /ignore\s+(all\s+)?(previous|prior|the\s+above)\s+(instructions|prompts?|rules)|disregard\s+(the\s+|your\s+)?(system\s+)?(prompt|instructions|rules)|forget\s+(everything|all\s+(previous|prior))|you\s+are\s+now\s+(a|an|the)\b|<\/?system>/i;
|
|
82728
82979
|
var FETCH_WORD_RE = /\b(curl|wget|iwr|invoke-webrequest)\b/gi;
|
|
@@ -82859,21 +83110,21 @@ function decodeSuspiciousBase64(text) {
|
|
|
82859
83110
|
}
|
|
82860
83111
|
return out;
|
|
82861
83112
|
}
|
|
82862
|
-
function mk2(rule, severity, title, signals, fix,
|
|
83113
|
+
function mk2(rule, severity, title, signals, fix, path110, line) {
|
|
82863
83114
|
return {
|
|
82864
83115
|
check: "CI-6",
|
|
82865
83116
|
rule,
|
|
82866
83117
|
dimension: "instructions",
|
|
82867
83118
|
severity,
|
|
82868
83119
|
title,
|
|
82869
|
-
file:
|
|
83120
|
+
file: path110,
|
|
82870
83121
|
...line ? { line } : {},
|
|
82871
83122
|
signals,
|
|
82872
83123
|
fix
|
|
82873
83124
|
};
|
|
82874
83125
|
}
|
|
82875
83126
|
var lineAt = (text, i) => i >= 0 ? lineAtIndex(text, i) : void 0;
|
|
82876
|
-
function analyzeInstructionFile(
|
|
83127
|
+
function analyzeInstructionFile(path110, content) {
|
|
82877
83128
|
const findings = [];
|
|
82878
83129
|
const decoded = decodeSuspiciousBase64(content);
|
|
82879
83130
|
const glyph = homoglyphWord(content);
|
|
@@ -82887,7 +83138,7 @@ function analyzeInstructionFile(path108, content) {
|
|
|
82887
83138
|
`\`${glyph.folded}\` is written with ${glyph.count} non-Latin look-alike letter(s): it reads the same to a reviewer, but a search, a replace or a policy check on the real word misses it`
|
|
82888
83139
|
],
|
|
82889
83140
|
"Spell the word with plain Latin letters, or explain on the same line why the look-alikes are there.",
|
|
82890
|
-
|
|
83141
|
+
path110,
|
|
82891
83142
|
glyph.line
|
|
82892
83143
|
)
|
|
82893
83144
|
);
|
|
@@ -82901,7 +83152,7 @@ function analyzeInstructionFile(path108, content) {
|
|
|
82901
83152
|
"contains Unicode tag characters (U+E0000\u2013E007F): an invisible instruction-smuggling channel with no legitimate use in text"
|
|
82902
83153
|
],
|
|
82903
83154
|
"Remove the tag characters. Instruction files must be plain, reviewable text.",
|
|
82904
|
-
|
|
83155
|
+
path110,
|
|
82905
83156
|
lineAt(content, content.search(TAG_CHARS))
|
|
82906
83157
|
)
|
|
82907
83158
|
);
|
|
@@ -82915,7 +83166,7 @@ function analyzeInstructionFile(path108, content) {
|
|
|
82915
83166
|
"contains a bidi override (U+202D/U+202E): a Trojan-Source technique that visually reorders text so a human reads something different from what the agent parses"
|
|
82916
83167
|
],
|
|
82917
83168
|
"Remove the bidi override characters.",
|
|
82918
|
-
|
|
83169
|
+
path110,
|
|
82919
83170
|
lineAt(content, content.search(BIDI_OVERRIDE))
|
|
82920
83171
|
)
|
|
82921
83172
|
);
|
|
@@ -82929,7 +83180,7 @@ function analyzeInstructionFile(path108, content) {
|
|
|
82929
83180
|
"contains bidi embed/isolate characters (U+202A\u2013202C / U+2066\u20132069): legitimate in right-to-left text, but confirm they are not being used to hide or reorder instructions"
|
|
82930
83181
|
],
|
|
82931
83182
|
"Confirm the bidi marks are legitimate RTL formatting; remove otherwise.",
|
|
82932
|
-
|
|
83183
|
+
path110,
|
|
82933
83184
|
lineAt(content, content.search(BIDI_EMBED_ISOLATE))
|
|
82934
83185
|
)
|
|
82935
83186
|
);
|
|
@@ -82945,7 +83196,7 @@ function analyzeInstructionFile(path108, content) {
|
|
|
82945
83196
|
revealed ? "a zero-width character conceals a prompt-override directive that only appears once the hidden characters are stripped" : "a zero-width character splits a visible Latin word: a concealment technique (hides text from human review while the agent reads it as contiguous)"
|
|
82946
83197
|
],
|
|
82947
83198
|
"Remove the zero-width characters. Instruction files must be plain, reviewable text.",
|
|
82948
|
-
|
|
83199
|
+
path110,
|
|
82949
83200
|
lineAt(content, zw.first)
|
|
82950
83201
|
)
|
|
82951
83202
|
);
|
|
@@ -82964,7 +83215,7 @@ function analyzeInstructionFile(path108, content) {
|
|
|
82964
83215
|
`contains a prompt-override / role-impersonation directive (\`${safeText(m[0].slice(0, 60).trim(), 60)}\`)${ovEnc ? ", concealed in a base64 blob" : ""}`
|
|
82965
83216
|
],
|
|
82966
83217
|
"Remove the override text. An instruction file should not tell the agent to ignore its own rules.",
|
|
82967
|
-
|
|
83218
|
+
path110,
|
|
82968
83219
|
ov ? lineAt(content, ov.index) : void 0
|
|
82969
83220
|
// concealed in base64: no line, never a wrong one
|
|
82970
83221
|
)
|
|
@@ -82981,7 +83232,7 @@ function analyzeInstructionFile(path108, content) {
|
|
|
82981
83232
|
`\`${safeText(fo[0].slice(0, 70).trim(), 70)}\`: fetch-and-obey, outside an install/setup section`
|
|
82982
83233
|
],
|
|
82983
83234
|
"Do not instruct the agent to pipe remote content into a shell; pin and vendor scripts instead.",
|
|
82984
|
-
|
|
83235
|
+
path110,
|
|
82985
83236
|
lineAt(content, fo.index)
|
|
82986
83237
|
)
|
|
82987
83238
|
);
|
|
@@ -82997,7 +83248,7 @@ function analyzeInstructionFile(path108, content) {
|
|
|
82997
83248
|
`references \`${safeText(sp[0].slice(0, 50).trim(), 50)}\`: directs the agent toward secrets`
|
|
82998
83249
|
],
|
|
82999
83250
|
"Do not reference credential files or paths in agent instructions.",
|
|
83000
|
-
|
|
83251
|
+
path110,
|
|
83001
83252
|
lineAt(content, sp.index)
|
|
83002
83253
|
)
|
|
83003
83254
|
);
|
|
@@ -83020,7 +83271,7 @@ function analyzeInstructionFile(path108, content) {
|
|
|
83020
83271
|
"Instruction directs the agent to send data to an external endpoint",
|
|
83021
83272
|
[`\`${safeText(ex[0].slice(0, 70).trim(), 70)}\`: possible exfiltration directive`],
|
|
83022
83273
|
"Remove external post/upload directives from agent instructions.",
|
|
83023
|
-
|
|
83274
|
+
path110,
|
|
83024
83275
|
lineAt(content, ex.index)
|
|
83025
83276
|
)
|
|
83026
83277
|
);
|
|
@@ -83031,18 +83282,18 @@ function analyzeInstructionFile(path108, content) {
|
|
|
83031
83282
|
// src/ci-check/route.ts
|
|
83032
83283
|
var MCP_CONFIG_RE = /\.mcp\.json$|\.cursor\/mcp\.json$|(^|\/)\.vscode\/mcp\.json$|(^|\/)\.kiro\/settings\/mcp\.json$|(^|\/)\.gemini\/settings\.json$|(^|\/)opencode\.json$|(^|\/)\.opencode\/config\.json$/;
|
|
83033
83284
|
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(
|
|
83285
|
+
function routeOf(path110, skillDirs, appDirs = /* @__PURE__ */ new Set()) {
|
|
83286
|
+
if (path110 === SUPPRESSIONS_FILE) return "suppressions";
|
|
83287
|
+
if (/\.github\/workflows\/.+\.ya?ml$/.test(path110)) return "workflow";
|
|
83288
|
+
if (ISSUE_FORM_RE.test(path110)) return "issue-form";
|
|
83289
|
+
if (path110 === "package.json" || path110 === "pyproject.toml") return "manifest";
|
|
83290
|
+
if (/\.claude\/settings(\.local)?\.json$/.test(path110)) return "agent-config";
|
|
83291
|
+
if (isHookScript(path110)) return "hook-script";
|
|
83292
|
+
if (isSkillScript(path110, skillDirs)) return "skill-script";
|
|
83293
|
+
if (MCP_CONFIG_RE.test(path110)) return "mcp";
|
|
83294
|
+
if (/(^|\/)\.codex\/config\.toml$/.test(path110)) return "codex";
|
|
83295
|
+
if (isInstructionFile(path110, skillDirs, appDirs)) return "instruction";
|
|
83296
|
+
if (isAppDoc(path110, skillDirs, appDirs)) return "app-doc";
|
|
83046
83297
|
return null;
|
|
83047
83298
|
}
|
|
83048
83299
|
|
|
@@ -83171,7 +83422,7 @@ function parseRepoUrl(input) {
|
|
|
83171
83422
|
function isLocalPath(input) {
|
|
83172
83423
|
if (input.startsWith(".") || input.startsWith("/") || input.startsWith("~")) return true;
|
|
83173
83424
|
try {
|
|
83174
|
-
return
|
|
83425
|
+
return import_fs93.default.existsSync(input) && import_fs93.default.statSync(input).isDirectory();
|
|
83175
83426
|
} catch {
|
|
83176
83427
|
return false;
|
|
83177
83428
|
}
|
|
@@ -83532,7 +83783,7 @@ function capNested(reads, cap, notes) {
|
|
|
83532
83783
|
}
|
|
83533
83784
|
var overLimit = (text) => Buffer.byteLength(text, "utf8") > MAX_FILE_BYTES3;
|
|
83534
83785
|
var RAW_LIMIT = 2 * MAX_FILE_BYTES3;
|
|
83535
|
-
var OPEN_READ =
|
|
83786
|
+
var OPEN_READ = import_fs93.default.constants.O_RDONLY | (import_fs93.default.constants.O_NOFOLLOW ?? 0) | (import_fs93.default.constants.O_NONBLOCK ?? 0);
|
|
83536
83787
|
var MAX_WALK_ENTRIES = 1e6;
|
|
83537
83788
|
var direntKind = (e) => e.isSymbolicLink() ? "link" : e.isDirectory() ? "dir" : e.isFile() ? "file" : "other";
|
|
83538
83789
|
function walkDisk(root, notes) {
|
|
@@ -83547,7 +83798,7 @@ function walkDisk(root, notes) {
|
|
|
83547
83798
|
const relDir = stack.pop();
|
|
83548
83799
|
let dirents;
|
|
83549
83800
|
try {
|
|
83550
|
-
dirents =
|
|
83801
|
+
dirents = import_fs93.default.readdirSync(import_path91.default.join(root, relDir), { withFileTypes: true });
|
|
83551
83802
|
} catch (e) {
|
|
83552
83803
|
unlistable.push(`${relDir || "."} (${e?.code ?? "error"})`);
|
|
83553
83804
|
continue;
|
|
@@ -83561,7 +83812,7 @@ function walkDisk(root, notes) {
|
|
|
83561
83812
|
const k = direntKind(e);
|
|
83562
83813
|
kinds2.set(rel, k);
|
|
83563
83814
|
if (k !== "dir" || isUnwalked(`${rel}/`)) continue;
|
|
83564
|
-
if (
|
|
83815
|
+
if (import_fs93.default.existsSync(import_path91.default.join(root, rel, ".git"))) {
|
|
83565
83816
|
sealed.add(rel);
|
|
83566
83817
|
nestedRepos.push(rel);
|
|
83567
83818
|
} else stack.push(rel);
|
|
@@ -83584,7 +83835,7 @@ function walkDisk(root, notes) {
|
|
|
83584
83835
|
}
|
|
83585
83836
|
function gitmodulePaths(root) {
|
|
83586
83837
|
try {
|
|
83587
|
-
const text = readLocalFile(
|
|
83838
|
+
const text = readLocalFile(import_path91.default.join(root, ".gitmodules"), ".gitmodules");
|
|
83588
83839
|
return [...text.matchAll(/^\s*path\s*=\s*(.+?)\s*$/gm)].map((m) => m[1].replace(/\/+$/, ""));
|
|
83589
83840
|
} catch {
|
|
83590
83841
|
return [];
|
|
@@ -83592,9 +83843,9 @@ function gitmodulePaths(root) {
|
|
|
83592
83843
|
}
|
|
83593
83844
|
function localLinkText(root, rel) {
|
|
83594
83845
|
try {
|
|
83595
|
-
const t =
|
|
83846
|
+
const t = import_fs93.default.readlinkSync(import_path91.default.join(root, rel));
|
|
83596
83847
|
if (process.platform !== "win32") return t;
|
|
83597
|
-
return
|
|
83848
|
+
return import_path91.default.win32.isAbsolute(t) ? `/${t.replace(/\\/g, "/")}` : t.replace(/\\/g, "/");
|
|
83598
83849
|
} catch {
|
|
83599
83850
|
return null;
|
|
83600
83851
|
}
|
|
@@ -83602,11 +83853,11 @@ function localLinkText(root, rel) {
|
|
|
83602
83853
|
function readLocalFile(abs, rel) {
|
|
83603
83854
|
let fd;
|
|
83604
83855
|
try {
|
|
83605
|
-
fd =
|
|
83606
|
-
const st =
|
|
83856
|
+
fd = import_fs93.default.openSync(abs, OPEN_READ);
|
|
83857
|
+
const st = import_fs93.default.fstatSync(fd);
|
|
83607
83858
|
if (!st.isFile()) throw new Error(unreadNote(rel, "no longer a regular file"));
|
|
83608
83859
|
if (st.size > RAW_LIMIT) throw new Error(tooLargeNote(rel));
|
|
83609
|
-
const text = lf(
|
|
83860
|
+
const text = lf(import_fs93.default.readFileSync(fd, "utf8"));
|
|
83610
83861
|
if (overLimit(text)) throw new Error(tooLargeNote(rel));
|
|
83611
83862
|
return text;
|
|
83612
83863
|
} catch (e) {
|
|
@@ -83614,7 +83865,7 @@ function readLocalFile(abs, rel) {
|
|
|
83614
83865
|
if (msg.includes(INCOMPLETE)) throw e;
|
|
83615
83866
|
throw new Error(unreadNote(rel, e?.code ?? "error"));
|
|
83616
83867
|
} finally {
|
|
83617
|
-
if (fd !== void 0)
|
|
83868
|
+
if (fd !== void 0) import_fs93.default.closeSync(fd);
|
|
83618
83869
|
}
|
|
83619
83870
|
}
|
|
83620
83871
|
function localGitHubRepo(root) {
|
|
@@ -83635,10 +83886,10 @@ function readLocalTree(dir2) {
|
|
|
83635
83886
|
notes.push(...plan.notes);
|
|
83636
83887
|
const files = [];
|
|
83637
83888
|
for (const { rel, real, route } of plan.reads) {
|
|
83638
|
-
const abs =
|
|
83889
|
+
const abs = import_path91.default.join(root, real);
|
|
83639
83890
|
let size = 0;
|
|
83640
83891
|
try {
|
|
83641
|
-
size =
|
|
83892
|
+
size = import_fs93.default.lstatSync(abs).size;
|
|
83642
83893
|
} catch {
|
|
83643
83894
|
}
|
|
83644
83895
|
if (size > RAW_LIMIT) {
|
|
@@ -85146,17 +85397,17 @@ function localTarget(uses, self) {
|
|
|
85146
85397
|
if (!f) return null;
|
|
85147
85398
|
return f[1].toLowerCase() === self.owner.toLowerCase() && f[2].toLowerCase() === self.repo.toLowerCase() ? `.github/workflows/${f[3]}` : null;
|
|
85148
85399
|
}
|
|
85149
|
-
function localCallsOf(
|
|
85400
|
+
function localCallsOf(path110, content, autoLabels, trustedRunSources, self) {
|
|
85150
85401
|
AUTO_LABELS = autoLabels ?? /* @__PURE__ */ new Set();
|
|
85151
85402
|
TRUSTED_RUN_SOURCES = trustedRunSources ?? /* @__PURE__ */ new Set();
|
|
85152
85403
|
try {
|
|
85153
|
-
return localCallsOfInner(
|
|
85404
|
+
return localCallsOfInner(path110, content, self);
|
|
85154
85405
|
} finally {
|
|
85155
85406
|
AUTO_LABELS = /* @__PURE__ */ new Set();
|
|
85156
85407
|
TRUSTED_RUN_SOURCES = /* @__PURE__ */ new Set();
|
|
85157
85408
|
}
|
|
85158
85409
|
}
|
|
85159
|
-
function localCallsOfInner(
|
|
85410
|
+
function localCallsOfInner(path110, content, self) {
|
|
85160
85411
|
let raw;
|
|
85161
85412
|
try {
|
|
85162
85413
|
raw = loadWorkflow(content).raw;
|
|
@@ -85174,7 +85425,7 @@ function localCallsOfInner(path108, content, self) {
|
|
|
85174
85425
|
out.push({
|
|
85175
85426
|
target,
|
|
85176
85427
|
caller: {
|
|
85177
|
-
file:
|
|
85428
|
+
file: path110,
|
|
85178
85429
|
keys: reach.keys,
|
|
85179
85430
|
untrusted: reach.untrusted,
|
|
85180
85431
|
secretExposed: reach.secretExposed,
|
|
@@ -85410,7 +85661,7 @@ function upstreamRunTrusted(wf, raw) {
|
|
|
85410
85661
|
const names = Array.isArray(run?.workflows) ? run.workflows.map(String) : [];
|
|
85411
85662
|
return names.length > 0 && names.every((n) => TRUSTED_RUN_SOURCES.has(n));
|
|
85412
85663
|
}
|
|
85413
|
-
function runSourceOf(
|
|
85664
|
+
function runSourceOf(path110, content, autoLabels) {
|
|
85414
85665
|
AUTO_LABELS = autoLabels ?? /* @__PURE__ */ new Set();
|
|
85415
85666
|
try {
|
|
85416
85667
|
let raw;
|
|
@@ -85423,7 +85674,7 @@ function runSourceOf(path108, content, autoLabels) {
|
|
|
85423
85674
|
const wf = raw;
|
|
85424
85675
|
CALLERS.delete(wf);
|
|
85425
85676
|
const reach = triggerReach(wf, raw);
|
|
85426
|
-
const name = typeof raw["name"] === "string" && raw["name"] ? raw["name"] :
|
|
85677
|
+
const name = typeof raw["name"] === "string" && raw["name"] ? raw["name"] : path110;
|
|
85427
85678
|
return { name, trusted: !reach.untrusted && !reach.reusable };
|
|
85428
85679
|
} finally {
|
|
85429
85680
|
AUTO_LABELS = /* @__PURE__ */ new Set();
|
|
@@ -85893,18 +86144,18 @@ function severityFromScore(score) {
|
|
|
85893
86144
|
if (score >= 1) return "advisory";
|
|
85894
86145
|
return null;
|
|
85895
86146
|
}
|
|
85896
|
-
function analyzeWorkflow(
|
|
86147
|
+
function analyzeWorkflow(path110, content, callers, autoLabels, trustedRunSources) {
|
|
85897
86148
|
AUTO_LABELS = autoLabels ?? /* @__PURE__ */ new Set();
|
|
85898
86149
|
TRUSTED_RUN_SOURCES = trustedRunSources ?? /* @__PURE__ */ new Set();
|
|
85899
86150
|
try {
|
|
85900
|
-
return analyzeWorkflowInner(
|
|
86151
|
+
return analyzeWorkflowInner(path110, content, callers);
|
|
85901
86152
|
} finally {
|
|
85902
86153
|
AUTO_LABELS = /* @__PURE__ */ new Set();
|
|
85903
86154
|
TRUSTED_RUN_SOURCES = /* @__PURE__ */ new Set();
|
|
85904
86155
|
UPSTREAM_TRUSTED = false;
|
|
85905
86156
|
}
|
|
85906
86157
|
}
|
|
85907
|
-
function analyzeWorkflowInner(
|
|
86158
|
+
function analyzeWorkflowInner(path110, content, callers) {
|
|
85908
86159
|
let raw;
|
|
85909
86160
|
try {
|
|
85910
86161
|
raw = loadWorkflow(content).raw;
|
|
@@ -86113,7 +86364,7 @@ function analyzeWorkflowInner(path108, content, callers) {
|
|
|
86113
86364
|
dimension: "workflows",
|
|
86114
86365
|
severity,
|
|
86115
86366
|
title,
|
|
86116
|
-
file:
|
|
86367
|
+
file: path110,
|
|
86117
86368
|
signals,
|
|
86118
86369
|
mitigations: mitigations.length ? mitigations : void 0,
|
|
86119
86370
|
fix: head === "root" && privileged ? "Do not check out the untrusted PR head into the workspace root under a privileged trigger (pull_request_target/workflow_run): check out the base ref, or isolate the head in a subdir (--add-dir). Add an actor gate and scope the agent tools." : head === "root" ? "This runs under `pull_request` (fork PRs get a read-only token), so the head checkout is low-risk today: keep it on `pull_request` (not `pull_request_target`) and keep the actor gate + scoped tools." : "Add/verify an actor gate, scope the agent tools to read-only, and env-deny secrets. See Anthropic\u2019s claude-code-action security doc."
|
|
@@ -86217,18 +86468,18 @@ function evalAgentJob(job, wf, raw, untrustedTrigger, reusable) {
|
|
|
86217
86468
|
if (reusable && !loadedGun && SEVERITY_RANK2[severity] > SEVERITY_RANK2.medium) severity = "medium";
|
|
86218
86469
|
return { severity, secrets, injectable, canReadEnv };
|
|
86219
86470
|
}
|
|
86220
|
-
function analyzeWorkflowSecrets(
|
|
86471
|
+
function analyzeWorkflowSecrets(path110, content, callers, autoLabels, trustedRunSources) {
|
|
86221
86472
|
AUTO_LABELS = autoLabels ?? /* @__PURE__ */ new Set();
|
|
86222
86473
|
TRUSTED_RUN_SOURCES = trustedRunSources ?? /* @__PURE__ */ new Set();
|
|
86223
86474
|
try {
|
|
86224
|
-
return analyzeWorkflowSecretsInner(
|
|
86475
|
+
return analyzeWorkflowSecretsInner(path110, content, callers);
|
|
86225
86476
|
} finally {
|
|
86226
86477
|
AUTO_LABELS = /* @__PURE__ */ new Set();
|
|
86227
86478
|
TRUSTED_RUN_SOURCES = /* @__PURE__ */ new Set();
|
|
86228
86479
|
UPSTREAM_TRUSTED = false;
|
|
86229
86480
|
}
|
|
86230
86481
|
}
|
|
86231
|
-
function analyzeWorkflowSecretsInner(
|
|
86482
|
+
function analyzeWorkflowSecretsInner(path110, content, callers) {
|
|
86232
86483
|
let raw;
|
|
86233
86484
|
try {
|
|
86234
86485
|
raw = loadWorkflow(content).raw;
|
|
@@ -86255,7 +86506,7 @@ function analyzeWorkflowSecretsInner(path108, content, callers) {
|
|
|
86255
86506
|
dimension: "data",
|
|
86256
86507
|
severity: worst.severity,
|
|
86257
86508
|
title: worst.severity === "advisory" ? "Secrets reachable by the agent: hardening" : "Exfiltratable secrets reachable by an injectable agent",
|
|
86258
|
-
file:
|
|
86509
|
+
file: path110,
|
|
86259
86510
|
signals: [
|
|
86260
86511
|
`agent can reach: ${worst.secrets.map((s) => s.name).join(", ")}`,
|
|
86261
86512
|
worst.injectable ? "the agent is externally triggerable (untrusted trigger, no gate)" : "gated / not externally triggerable: latent risk only",
|
|
@@ -86277,7 +86528,7 @@ function marketplaceOwner(market) {
|
|
|
86277
86528
|
market
|
|
86278
86529
|
)?.[1] ?? /^([\w.-]{1,100})\/[\w.-]{1,100}(?:[#@].*)?$/.exec(market)?.[1];
|
|
86279
86530
|
}
|
|
86280
|
-
function analyzeWorkflowPlugins(
|
|
86531
|
+
function analyzeWorkflowPlugins(path110, content, owner) {
|
|
86281
86532
|
let raw;
|
|
86282
86533
|
try {
|
|
86283
86534
|
raw = loadWorkflow(content).raw;
|
|
@@ -86307,7 +86558,7 @@ function analyzeWorkflowPlugins(path108, content, owner) {
|
|
|
86307
86558
|
dimension: "mcp",
|
|
86308
86559
|
severity: "medium",
|
|
86309
86560
|
title: "Agent installs plugins from a third-party marketplace on every run",
|
|
86310
|
-
file:
|
|
86561
|
+
file: path110,
|
|
86311
86562
|
signals: [
|
|
86312
86563
|
`\`plugin_marketplaces: ${safeText(market, 120)}\` is not pinned to a commit: whoever controls it changes the code and prompts the agent runs`
|
|
86313
86564
|
],
|
|
@@ -86323,11 +86574,11 @@ function readsItemList(text) {
|
|
|
86323
86574
|
if (text.length > 2e5) return ITEM_LIST_RE.test(text);
|
|
86324
86575
|
return text.replace(/\\\r?\n/g, " ").split("\n").some((l) => ITEM_LIST_RE.test(l) && !sanitizedListing(l));
|
|
86325
86576
|
}
|
|
86326
|
-
function analyzeTrustedReaders(
|
|
86577
|
+
function analyzeTrustedReaders(path110, content, autoLabels, callers, trustedRunSources) {
|
|
86327
86578
|
AUTO_LABELS = autoLabels ?? /* @__PURE__ */ new Set();
|
|
86328
86579
|
TRUSTED_RUN_SOURCES = trustedRunSources ?? /* @__PURE__ */ new Set();
|
|
86329
86580
|
try {
|
|
86330
|
-
return analyzeTrustedReadersInner(
|
|
86581
|
+
return analyzeTrustedReadersInner(path110, content, callers);
|
|
86331
86582
|
} finally {
|
|
86332
86583
|
AUTO_LABELS = /* @__PURE__ */ new Set();
|
|
86333
86584
|
TRUSTED_RUN_SOURCES = /* @__PURE__ */ new Set();
|
|
@@ -86336,7 +86587,7 @@ function analyzeTrustedReaders(path108, content, autoLabels, callers, trustedRun
|
|
|
86336
86587
|
function keysWithCallers(keys, callers) {
|
|
86337
86588
|
return [.../* @__PURE__ */ new Set([...keys, ...(callers ?? []).flatMap((c) => c.keys)])];
|
|
86338
86589
|
}
|
|
86339
|
-
function analyzeTrustedReadersInner(
|
|
86590
|
+
function analyzeTrustedReadersInner(path110, content, callers) {
|
|
86340
86591
|
let raw;
|
|
86341
86592
|
try {
|
|
86342
86593
|
raw = loadWorkflow(content).raw;
|
|
@@ -86397,7 +86648,7 @@ function analyzeTrustedReadersInner(path108, content, callers) {
|
|
|
86397
86648
|
dimension: "workflows",
|
|
86398
86649
|
severity: "advisory",
|
|
86399
86650
|
title: "Agent on a trusted trigger reads content strangers write, with a write token",
|
|
86400
|
-
file:
|
|
86651
|
+
file: path110,
|
|
86401
86652
|
signals: [
|
|
86402
86653
|
`runs on ${keys.map((k) => safeText(k, 40)).join(", ")}: no stranger starts it`,
|
|
86403
86654
|
...reads.map((r) => `the agent ${r}`),
|
|
@@ -86485,17 +86736,17 @@ function requiresTrustedAuthor(src) {
|
|
|
86485
86736
|
};
|
|
86486
86737
|
return req(x);
|
|
86487
86738
|
}
|
|
86488
|
-
function analyzeForkCodeOnTrust(
|
|
86739
|
+
function analyzeForkCodeOnTrust(path110, content, callers, autoLabels, trustedRunSources) {
|
|
86489
86740
|
AUTO_LABELS = autoLabels ?? /* @__PURE__ */ new Set();
|
|
86490
86741
|
TRUSTED_RUN_SOURCES = trustedRunSources ?? /* @__PURE__ */ new Set();
|
|
86491
86742
|
try {
|
|
86492
|
-
return analyzeForkCodeOnTrustInner(
|
|
86743
|
+
return analyzeForkCodeOnTrustInner(path110, content, callers);
|
|
86493
86744
|
} finally {
|
|
86494
86745
|
AUTO_LABELS = /* @__PURE__ */ new Set();
|
|
86495
86746
|
TRUSTED_RUN_SOURCES = /* @__PURE__ */ new Set();
|
|
86496
86747
|
}
|
|
86497
86748
|
}
|
|
86498
|
-
function analyzeForkCodeOnTrustInner(
|
|
86749
|
+
function analyzeForkCodeOnTrustInner(path110, content, callers) {
|
|
86499
86750
|
let raw;
|
|
86500
86751
|
try {
|
|
86501
86752
|
raw = loadWorkflow(content).raw;
|
|
@@ -86534,7 +86785,7 @@ function analyzeForkCodeOnTrustInner(path108, content, callers) {
|
|
|
86534
86785
|
dimension: "workflows",
|
|
86535
86786
|
severity: "advisory",
|
|
86536
86787
|
title: "A maintainer's action runs the agent inside the fork's code",
|
|
86537
|
-
file:
|
|
86788
|
+
file: path110,
|
|
86538
86789
|
signals: [
|
|
86539
86790
|
`triggered by ${forkKeys.map((k) => safeText(k, 40)).join(", ")}, behind a gate a maintainer passes (a comment, a label, a push to the PR branch, a reopen)`,
|
|
86540
86791
|
"checks out the untrusted PR head into the workspace root",
|
|
@@ -86566,18 +86817,18 @@ function laterSecrets(wf, job, from) {
|
|
|
86566
86817
|
if (!/^GITHUB_TOKEN$/i.test(m[1])) out.add(m[1]);
|
|
86567
86818
|
return [...out];
|
|
86568
86819
|
}
|
|
86569
|
-
function analyzeAgentOutputToEnv(
|
|
86820
|
+
function analyzeAgentOutputToEnv(path110, content, callers, autoLabels, trustedRunSources) {
|
|
86570
86821
|
AUTO_LABELS = autoLabels ?? /* @__PURE__ */ new Set();
|
|
86571
86822
|
TRUSTED_RUN_SOURCES = trustedRunSources ?? /* @__PURE__ */ new Set();
|
|
86572
86823
|
try {
|
|
86573
|
-
return analyzeAgentOutputToEnvInner(
|
|
86824
|
+
return analyzeAgentOutputToEnvInner(path110, content, callers);
|
|
86574
86825
|
} finally {
|
|
86575
86826
|
AUTO_LABELS = /* @__PURE__ */ new Set();
|
|
86576
86827
|
TRUSTED_RUN_SOURCES = /* @__PURE__ */ new Set();
|
|
86577
86828
|
UPSTREAM_TRUSTED = false;
|
|
86578
86829
|
}
|
|
86579
86830
|
}
|
|
86580
|
-
function analyzeAgentOutputToEnvInner(
|
|
86831
|
+
function analyzeAgentOutputToEnvInner(path110, content, callers) {
|
|
86581
86832
|
let raw;
|
|
86582
86833
|
try {
|
|
86583
86834
|
raw = loadWorkflow(content).raw;
|
|
@@ -86673,7 +86924,7 @@ function analyzeAgentOutputToEnvInner(path108, content, callers) {
|
|
|
86673
86924
|
dimension: "workflows",
|
|
86674
86925
|
severity,
|
|
86675
86926
|
title: sink.target === "GITHUB_PATH" ? "The agent's output is added to the job's PATH" : "The agent's output is written into the job's environment",
|
|
86676
|
-
file:
|
|
86927
|
+
file: path110,
|
|
86677
86928
|
signals,
|
|
86678
86929
|
fix: `Write the agent's result to a file and read it with a strict parser in the next step (a fixed set of values, or a number); never append free text from the agent to \`${target}\`. If a value must go there, strip newlines (\`tr -d '\\n'\`) and write it under a fixed name, or use a delimiter generated at run time.`,
|
|
86679
86930
|
explain: explainAgentOutputEnv({
|
|
@@ -86701,7 +86952,7 @@ function analyzeAgentOutputToEnvInner(path108, content, callers) {
|
|
|
86701
86952
|
|
|
86702
86953
|
// src/ci-check/agent-config.ts
|
|
86703
86954
|
init_cjs_shims();
|
|
86704
|
-
var
|
|
86955
|
+
var import_path92 = __toESM(require("path"));
|
|
86705
86956
|
function asStrings(v) {
|
|
86706
86957
|
return Array.isArray(v) ? v.filter((x) => typeof x === "string") : [];
|
|
86707
86958
|
}
|
|
@@ -86809,7 +87060,7 @@ function hookScriptPath(cmd) {
|
|
|
86809
87060
|
if (/^(https?:|\$|-)/.test(t)) continue;
|
|
86810
87061
|
t = t.replace(/^\.\//, "");
|
|
86811
87062
|
if (!SCRIPT_EXT_RE.test(t) && !/(^|\/)\.claude\/hooks\//.test(t)) continue;
|
|
86812
|
-
const norm =
|
|
87063
|
+
const norm = import_path92.default.posix.normalize(t);
|
|
86813
87064
|
if (norm.startsWith("..") || norm.startsWith("/") || norm.includes("/../")) return null;
|
|
86814
87065
|
return norm;
|
|
86815
87066
|
}
|
|
@@ -86819,7 +87070,7 @@ function cmdLine(content, cmd) {
|
|
|
86819
87070
|
const i = jsonValueIndex(content, cmd);
|
|
86820
87071
|
return i >= 0 ? lineAtIndex(content, i) : void 0;
|
|
86821
87072
|
}
|
|
86822
|
-
function analyzeAgentConfig(
|
|
87073
|
+
function analyzeAgentConfig(path110, content, tree) {
|
|
86823
87074
|
let cfg;
|
|
86824
87075
|
try {
|
|
86825
87076
|
cfg = JSON.parse(content);
|
|
@@ -86842,7 +87093,7 @@ function analyzeAgentConfig(path108, content, tree) {
|
|
|
86842
87093
|
dimension: "toolRules",
|
|
86843
87094
|
severity: high ? "high" : "medium",
|
|
86844
87095
|
title: high ? "Agent hook runs UNPINNED/remote third-party code on every action" : "Agent hook runs third-party code in the agent hot path",
|
|
86845
|
-
file:
|
|
87096
|
+
file: path110,
|
|
86846
87097
|
...cmdLine(content, cmd) ? { line: cmdLine(content, cmd) } : {},
|
|
86847
87098
|
signals: [
|
|
86848
87099
|
`hook command: \`${safeText(cmd, 120)}\``,
|
|
@@ -86863,7 +87114,7 @@ function analyzeAgentConfig(path108, content, tree) {
|
|
|
86863
87114
|
dimension: "toolRules",
|
|
86864
87115
|
severity: "medium",
|
|
86865
87116
|
title: "Agent hook runs a script that is not committed",
|
|
86866
|
-
file:
|
|
87117
|
+
file: path110,
|
|
86867
87118
|
...cmdLine(content, cmd) ? { line: cmdLine(content, cmd) } : {},
|
|
86868
87119
|
signals: [
|
|
86869
87120
|
`hook command: \`${safeText(cmd, 120)}\``,
|
|
@@ -86879,7 +87130,7 @@ function analyzeAgentConfig(path108, content, tree) {
|
|
|
86879
87130
|
dimension: "toolRules",
|
|
86880
87131
|
severity: "advisory",
|
|
86881
87132
|
title: "Agent hook runs a committed script this scan did not read",
|
|
86882
|
-
file:
|
|
87133
|
+
file: path110,
|
|
86883
87134
|
...cmdLine(content, cmd) ? { line: cmdLine(content, cmd) } : {},
|
|
86884
87135
|
signals: [
|
|
86885
87136
|
`hook command: \`${safeText(cmd, 120)}\``,
|
|
@@ -86908,12 +87159,12 @@ function analyzeAgentConfig(path108, content, tree) {
|
|
|
86908
87159
|
dimension: "toolRules",
|
|
86909
87160
|
severity: high ? "high" : "medium",
|
|
86910
87161
|
title: high ? "Committed agent config pre-authorizes broad tools with no deny backstop" : "Committed agent config pre-authorizes broad tools",
|
|
86911
|
-
file:
|
|
87162
|
+
file: path110,
|
|
86912
87163
|
signals,
|
|
86913
87164
|
fix: "Scope the allow-list to specific read-only subcommands (e.g. `Bash(gh pr view:*)`); avoid bare `Bash`/`git:`/`Write`, or add a `deny` backstop.",
|
|
86914
87165
|
explain: explainGrant({
|
|
86915
87166
|
high,
|
|
86916
|
-
file:
|
|
87167
|
+
file: path110,
|
|
86917
87168
|
broad: grade.broad,
|
|
86918
87169
|
bareShell: grade.bareShell,
|
|
86919
87170
|
hasBackstop: grade.bareShell ? deny.some((d) => /^Bash\b/.test(d)) : deny.some((d) => /Bash|Write|Edit/.test(d))
|
|
@@ -86930,7 +87181,7 @@ function analyzeAgentConfig(path108, content, tree) {
|
|
|
86930
87181
|
dimension: "toolRules",
|
|
86931
87182
|
severity: "medium",
|
|
86932
87183
|
title: "Committed agent config pre-approves a command that can run other programs",
|
|
86933
|
-
file:
|
|
87184
|
+
file: path110,
|
|
86934
87185
|
signals: [
|
|
86935
87186
|
`pre-approved: ${escapes.slice(0, 5).map((e) => `\`${safeText(e, 80)}\``).join(", ")}`,
|
|
86936
87187
|
"`find -exec` and `make -n --eval` run other programs without a prompt"
|
|
@@ -86945,8 +87196,8 @@ var ROOT_SURFACE_RE = /^\.(claude|agents|github|codex|cursor|gemini)\//;
|
|
|
86945
87196
|
var ITEM_TEXT_RE = /gh\s+(?:pr|issue)\s+(?:view|diff|list)\b|gh\s+pr\s+checkout\b|git\s+fetch\s+[^\n]{0,80}\bpull\/|gh\s+api\s+graphql\b|gh\s+api\s+[^\n]{0,120}\/(?:pulls|issues)\b|mcp__github__(?:get_issue|get_pull_request|list_issues|search_issues)|--json\s+[^\n]{0,120}\b(?:body|title)\b/;
|
|
86946
87197
|
var PR_TEXT_RE = /gh\s+pr\s+(?:view|diff)\b|gh\s+api\s+[^\n]{0,120}\/pulls\b/;
|
|
86947
87198
|
var WEB_TEXT_RE = /\bsearch the web\b|\bfetch (?:the )?(?:url|page)\b/i;
|
|
86948
|
-
function skillReadsUntrusted(
|
|
86949
|
-
if (!ROOT_SURFACE_RE.test(
|
|
87199
|
+
function skillReadsUntrusted(path110, content, allow, broad) {
|
|
87200
|
+
if (!ROOT_SURFACE_RE.test(path110)) return null;
|
|
86950
87201
|
const body = content.replace(/^---[\s\S]*?\n---/, "");
|
|
86951
87202
|
const runsCode = broad.map((a) => a.replace(/^PowerShell(?=$|\()/, "Bash")).some((a) => /^Bash$|^Bash\(\s*\*/.test(a) || openRunner(a) && !/^Bash\(\s*gh\b/.test(a));
|
|
86952
87203
|
const webGrant = allow.some((a) => /^(WebFetch|WebSearch)\b/.test(a));
|
|
@@ -86961,8 +87212,8 @@ function skillReadsUntrusted(path108, content, allow, broad) {
|
|
|
86961
87212
|
return "it reads pull request text that strangers write, and may edit files and run git/gh on it";
|
|
86962
87213
|
return null;
|
|
86963
87214
|
}
|
|
86964
|
-
function analyzeSkillGrants(
|
|
86965
|
-
if (!GRANT_CARRIER_RE.test(
|
|
87215
|
+
function analyzeSkillGrants(path110, content) {
|
|
87216
|
+
if (!GRANT_CARRIER_RE.test(path110)) return [];
|
|
86966
87217
|
const allow = allowedToolsOf(parseFrontmatter(content));
|
|
86967
87218
|
if (allow.length === 0) return [];
|
|
86968
87219
|
const grade = gradeBroadGrant(allow, [], {
|
|
@@ -86970,9 +87221,9 @@ function analyzeSkillGrants(path108, content) {
|
|
|
86970
87221
|
scope: "whenever this skill or command is active, for everyone who opens this repo with the agent"
|
|
86971
87222
|
});
|
|
86972
87223
|
if (!grade) return [];
|
|
86973
|
-
const kind = /commands\//.test(
|
|
87224
|
+
const kind = /commands\//.test(path110) ? "slash command" : "skill";
|
|
86974
87225
|
const at = content.search(/^allowed-tools\s*:/m);
|
|
86975
|
-
const untrusted = skillReadsUntrusted(
|
|
87226
|
+
const untrusted = skillReadsUntrusted(path110, content, allow, grade.broad);
|
|
86976
87227
|
if (untrusted)
|
|
86977
87228
|
return [
|
|
86978
87229
|
{
|
|
@@ -86982,7 +87233,7 @@ function analyzeSkillGrants(path108, content) {
|
|
|
86982
87233
|
dimension: "toolRules",
|
|
86983
87234
|
severity: "advisory",
|
|
86984
87235
|
title: `Committed ${kind} runs code or writes with text strangers control`,
|
|
86985
|
-
file:
|
|
87236
|
+
file: path110,
|
|
86986
87237
|
signals: [...grade.signals, untrusted],
|
|
86987
87238
|
fix: "Drop the shell or interpreter grant from a skill that reads PRs, issues or the web, or have it treat that text as data in a read-only step first."
|
|
86988
87239
|
}
|
|
@@ -86999,7 +87250,7 @@ function analyzeSkillGrants(path108, content) {
|
|
|
86999
87250
|
// shell — the cap is on reach, not on honesty.
|
|
87000
87251
|
severity: "medium",
|
|
87001
87252
|
title: grade.high ? `Committed ${kind} pre-authorizes an unrestricted shell while active` : `Committed ${kind} pre-authorizes broad tools while active`,
|
|
87002
|
-
file:
|
|
87253
|
+
file: path110,
|
|
87003
87254
|
signals: grade.signals,
|
|
87004
87255
|
fix: "Scope `allowed-tools` to the specific commands the skill needs (e.g. `Bash(git status:*)`); avoid a bare `Bash`, `Write` or `Edit`."
|
|
87005
87256
|
}
|
|
@@ -87131,7 +87382,7 @@ function ownPackageNames(manifests) {
|
|
|
87131
87382
|
}
|
|
87132
87383
|
return out;
|
|
87133
87384
|
}
|
|
87134
|
-
function analyzeMcp(
|
|
87385
|
+
function analyzeMcp(path110, content, own = /* @__PURE__ */ new Set()) {
|
|
87135
87386
|
let cfg;
|
|
87136
87387
|
try {
|
|
87137
87388
|
cfg = JSON.parse(content);
|
|
@@ -87167,9 +87418,9 @@ function analyzeMcp(path108, content, own = /* @__PURE__ */ new Set()) {
|
|
|
87167
87418
|
const key = (count.get(name) ?? 0) > 1 ? `${section}.${name}` : name;
|
|
87168
87419
|
servers[key] = { ...spec, anchor: name };
|
|
87169
87420
|
}
|
|
87170
|
-
return analyzeMcpServers(servers,
|
|
87421
|
+
return analyzeMcpServers(servers, path110, content, own);
|
|
87171
87422
|
}
|
|
87172
|
-
function analyzeMcpServers(servers,
|
|
87423
|
+
function analyzeMcpServers(servers, path110, content = "", own = /* @__PURE__ */ new Set()) {
|
|
87173
87424
|
const findings = [];
|
|
87174
87425
|
for (const [name, srv] of Object.entries(servers ?? {})) {
|
|
87175
87426
|
if (!srv || srv.disabled) continue;
|
|
@@ -87188,7 +87439,7 @@ function analyzeMcpServers(servers, path108, content = "", own = /* @__PURE__ */
|
|
|
87188
87439
|
dimension: "mcp",
|
|
87189
87440
|
severity: "medium",
|
|
87190
87441
|
title: `MCP server "${name}" runs an unpinned executable`,
|
|
87191
|
-
file:
|
|
87442
|
+
file: path110,
|
|
87192
87443
|
...line ? { line } : {},
|
|
87193
87444
|
signals: [
|
|
87194
87445
|
why.launcher === "npx" ? `\`${safeText(argv, 120)}\`: unversioned/@latest npx` : `\`${safeText(argv, 120)}\`: unversioned/latest ${why.launcher}`
|
|
@@ -87213,7 +87464,7 @@ function analyzeMcpServers(servers, path108, content = "", own = /* @__PURE__ */
|
|
|
87213
87464
|
dimension: "mcp",
|
|
87214
87465
|
severity: "high",
|
|
87215
87466
|
title: `MCP server "${name}" has an inline credential`,
|
|
87216
|
-
file:
|
|
87467
|
+
file: path110,
|
|
87217
87468
|
...line ? { line } : {},
|
|
87218
87469
|
signals: [
|
|
87219
87470
|
`env.${k} matches ${hit.patternName}: agent-reachable secret committed to the repo`
|
|
@@ -87229,7 +87480,7 @@ function analyzeMcpServers(servers, path108, content = "", own = /* @__PURE__ */
|
|
|
87229
87480
|
// src/ci-check/codex.ts
|
|
87230
87481
|
init_cjs_shims();
|
|
87231
87482
|
var import_smol_toml7 = require("smol-toml");
|
|
87232
|
-
function analyzeCodexConfig(
|
|
87483
|
+
function analyzeCodexConfig(path110, content, own = /* @__PURE__ */ new Set()) {
|
|
87233
87484
|
let cfg;
|
|
87234
87485
|
try {
|
|
87235
87486
|
cfg = (0, import_smol_toml7.parse)(content);
|
|
@@ -87237,7 +87488,7 @@ function analyzeCodexConfig(path108, content, own = /* @__PURE__ */ new Set()) {
|
|
|
87237
87488
|
return [];
|
|
87238
87489
|
}
|
|
87239
87490
|
const findings = [];
|
|
87240
|
-
findings.push(...analyzeMcpServers(cfg.mcp_servers ?? {},
|
|
87491
|
+
findings.push(...analyzeMcpServers(cfg.mcp_servers ?? {}, path110, content, own));
|
|
87241
87492
|
const sandbox = typeof cfg.sandbox_mode === "string" ? cfg.sandbox_mode : "";
|
|
87242
87493
|
const approval = typeof cfg.approval_policy === "string" ? cfg.approval_policy : "";
|
|
87243
87494
|
const fullAccess = /danger-full-access/i.test(sandbox);
|
|
@@ -87260,7 +87511,7 @@ function analyzeCodexConfig(path108, content, own = /* @__PURE__ */ new Set()) {
|
|
|
87260
87511
|
dimension: "toolRules",
|
|
87261
87512
|
severity: fullAccess ? "high" : "medium",
|
|
87262
87513
|
title: fullAccess ? "Codex config grants a full-access sandbox" : "Codex config never requires approval",
|
|
87263
|
-
file:
|
|
87514
|
+
file: path110,
|
|
87264
87515
|
signals,
|
|
87265
87516
|
fix: 'Commit a least-privilege Codex config: prefer `sandbox_mode = "read-only"` (or `"workspace-write"`) and `approval_policy = "on-request"`/`"on-failure"`. A repo-committed config applies to every contributor who runs Codex here.'
|
|
87266
87517
|
});
|
|
@@ -87314,7 +87565,7 @@ function reviewQuestion(rule) {
|
|
|
87314
87565
|
return "Is this an instruction the agent follows, or text for a person?";
|
|
87315
87566
|
}
|
|
87316
87567
|
var RANK2 = { critical: 4, high: 3, medium: 2, advisory: 1 };
|
|
87317
|
-
var worstRank = (
|
|
87568
|
+
var worstRank = (fs111) => Math.max(...fs111.map((f) => RANK2[f.severity] ?? 0));
|
|
87318
87569
|
var fileOrder = (a, b) => worstRank(b[1]) - worstRank(a[1]) || b[1].length - a[1].length;
|
|
87319
87570
|
function groupReview(findings) {
|
|
87320
87571
|
const byFile = /* @__PURE__ */ new Map();
|
|
@@ -87379,7 +87630,7 @@ function logicalLines2(content) {
|
|
|
87379
87630
|
}
|
|
87380
87631
|
return out;
|
|
87381
87632
|
}
|
|
87382
|
-
function analyzeScript(
|
|
87633
|
+
function analyzeScript(path110, content, rulePrefix) {
|
|
87383
87634
|
const check = rulePrefix.startsWith("CI-1") ? "CI-1" : "CI-6";
|
|
87384
87635
|
const dimension = check === "CI-1" ? "toolRules" : "instructions";
|
|
87385
87636
|
const mk3 = (suffix, severity, title, signal, fix, line) => ({
|
|
@@ -87388,7 +87639,7 @@ function analyzeScript(path108, content, rulePrefix) {
|
|
|
87388
87639
|
dimension,
|
|
87389
87640
|
severity,
|
|
87390
87641
|
title,
|
|
87391
|
-
file:
|
|
87642
|
+
file: path110,
|
|
87392
87643
|
...line ? { line } : {},
|
|
87393
87644
|
signals: [signal],
|
|
87394
87645
|
fix
|
|
@@ -87814,7 +88065,7 @@ async function scanRepo(input, onProgress) {
|
|
|
87814
88065
|
// src/ci-check/render.ts
|
|
87815
88066
|
init_cjs_shims();
|
|
87816
88067
|
var import_chalk36 = __toESM(require("chalk"));
|
|
87817
|
-
var listed = (
|
|
88068
|
+
var listed = (fs111) => fs111.filter((f) => f.tier !== "review");
|
|
87818
88069
|
function excerpt(f) {
|
|
87819
88070
|
const m = /`([^`]+)`/.exec(f.signals[0] ?? "");
|
|
87820
88071
|
return safeText(m ? m[1] : f.title, 120).replace(/`/g, "'");
|
|
@@ -87830,14 +88081,14 @@ function reviewMd(findings) {
|
|
|
87830
88081
|
L.push("");
|
|
87831
88082
|
const files = [...byFile.keys()];
|
|
87832
88083
|
for (const file2 of files.slice(0, REVIEW_FILES)) {
|
|
87833
|
-
const
|
|
88084
|
+
const fs111 = byFile.get(file2);
|
|
87834
88085
|
L.push(`- \`${safeText(file2, 300)}\``);
|
|
87835
|
-
for (const f of
|
|
88086
|
+
for (const f of fs111.slice(0, REVIEW_LINES_PER_FILE))
|
|
87836
88087
|
L.push(
|
|
87837
88088
|
` - ${f.line ? `line ${Number(f.line)}: ` : ""}\`${excerpt(f)}\`. Check: ${reviewQuestion(f.rule)}`
|
|
87838
88089
|
);
|
|
87839
|
-
if (
|
|
87840
|
-
L.push(` - and ${
|
|
88090
|
+
if (fs111.length > REVIEW_LINES_PER_FILE)
|
|
88091
|
+
L.push(` - and ${fs111.length - REVIEW_LINES_PER_FILE} similar lines in this file`);
|
|
87841
88092
|
}
|
|
87842
88093
|
const more = files.length - REVIEW_FILES;
|
|
87843
88094
|
if (more > 0) L.push(`- and ${more} more file${more === 1 ? "" : "s"}`);
|
|
@@ -87853,7 +88104,7 @@ function reviewMd(findings) {
|
|
|
87853
88104
|
}
|
|
87854
88105
|
function reviewTerminal(findings) {
|
|
87855
88106
|
const { byFile, grants } = groupReview(findings);
|
|
87856
|
-
const items = [...byFile.values()].reduce((a,
|
|
88107
|
+
const items = [...byFile.values()].reduce((a, fs111) => a + fs111.length, 0);
|
|
87857
88108
|
if (!items && !grants) return [];
|
|
87858
88109
|
const L = [];
|
|
87859
88110
|
if (items) {
|
|
@@ -87862,12 +88113,12 @@ function reviewTerminal(findings) {
|
|
|
87862
88113
|
);
|
|
87863
88114
|
const files = [...byFile.keys()];
|
|
87864
88115
|
for (const file2 of files.slice(0, REVIEW_FILES)) {
|
|
87865
|
-
const
|
|
88116
|
+
const fs111 = byFile.get(file2);
|
|
87866
88117
|
L.push(import_chalk36.default.gray(` ${file2}`));
|
|
87867
|
-
for (const f of
|
|
88118
|
+
for (const f of fs111.slice(0, REVIEW_LINES_PER_FILE))
|
|
87868
88119
|
L.push(` \u2022 ${f.line ? `line ${f.line}: ` : ""}${excerpt(f)}`);
|
|
87869
|
-
if (
|
|
87870
|
-
L.push(import_chalk36.default.gray(` and ${
|
|
88120
|
+
if (fs111.length > REVIEW_LINES_PER_FILE)
|
|
88121
|
+
L.push(import_chalk36.default.gray(` and ${fs111.length - REVIEW_LINES_PER_FILE} similar lines`));
|
|
87871
88122
|
}
|
|
87872
88123
|
const more = files.length - REVIEW_FILES;
|
|
87873
88124
|
if (more > 0) L.push(import_chalk36.default.gray(` and ${more} more file${more === 1 ? "" : "s"}`));
|
|
@@ -87881,7 +88132,7 @@ function reviewTerminal(findings) {
|
|
|
87881
88132
|
L.push("");
|
|
87882
88133
|
return L;
|
|
87883
88134
|
}
|
|
87884
|
-
var
|
|
88135
|
+
var ICON3 = {
|
|
87885
88136
|
critical: "\u{1F534}",
|
|
87886
88137
|
high: "\u{1F534}",
|
|
87887
88138
|
medium: "\u{1F7E1}",
|
|
@@ -87941,7 +88192,7 @@ function mdLine(v) {
|
|
|
87941
88192
|
function findingMd(f, L) {
|
|
87942
88193
|
const ex = f.explain;
|
|
87943
88194
|
L.push(
|
|
87944
|
-
`**${
|
|
88195
|
+
`**${ICON3[f.severity]} ${f.severity.toUpperCase()}: ${mdLine(ex ? ex.headline : f.title)}**` + (f.suppressed ? ` _(suppressed: \`${safeText(f.suppressed.reason, 200)}\`)_` : "")
|
|
87945
88196
|
);
|
|
87946
88197
|
L.push(`\`${safeText(f.file, 300)}${f.line ? ":" + Number(f.line) : ""}\` \xB7 ${f.rule}`);
|
|
87947
88198
|
L.push("");
|
|
@@ -87997,7 +88248,7 @@ function renderScan(res, diff) {
|
|
|
87997
88248
|
for (const f of shown) {
|
|
87998
88249
|
const ex = f.explain;
|
|
87999
88250
|
L.push(
|
|
88000
|
-
`${
|
|
88251
|
+
`${ICON3[f.severity]} ${COLOR[f.severity](f.severity.toUpperCase())} ${import_chalk36.default.bold(ex ? ex.headline : f.title)}`
|
|
88001
88252
|
);
|
|
88002
88253
|
L.push(import_chalk36.default.gray(` ${f.file}${f.line ? ":" + f.line : ""} \xB7 ${f.check}`));
|
|
88003
88254
|
if (ex) {
|
|
@@ -88519,16 +88770,16 @@ var import_chalk40 = __toESM(require("chalk"));
|
|
|
88519
88770
|
|
|
88520
88771
|
// src/canary/plant.ts
|
|
88521
88772
|
init_cjs_shims();
|
|
88522
|
-
var
|
|
88523
|
-
var
|
|
88524
|
-
var
|
|
88773
|
+
var import_fs95 = __toESM(require("fs"));
|
|
88774
|
+
var import_os77 = __toESM(require("os"));
|
|
88775
|
+
var import_path94 = __toESM(require("path"));
|
|
88525
88776
|
init_jail();
|
|
88526
88777
|
init_registry2();
|
|
88527
88778
|
|
|
88528
88779
|
// src/canary/sites.ts
|
|
88529
88780
|
init_cjs_shims();
|
|
88530
|
-
var
|
|
88531
|
-
var
|
|
88781
|
+
var import_fs94 = __toESM(require("fs"));
|
|
88782
|
+
var import_path93 = __toESM(require("path"));
|
|
88532
88783
|
|
|
88533
88784
|
// src/canary/generate.ts
|
|
88534
88785
|
init_cjs_shims();
|
|
@@ -88623,26 +88874,26 @@ function generateSshKey() {
|
|
|
88623
88874
|
var SITES = {
|
|
88624
88875
|
"aws-profile": {
|
|
88625
88876
|
kind: "aws-profile",
|
|
88626
|
-
primary: (h) =>
|
|
88627
|
-
fallback: (h) =>
|
|
88877
|
+
primary: (h) => import_path93.default.join(h, ".aws", "credentials"),
|
|
88878
|
+
fallback: (h) => import_path93.default.join(h, ".aws", "credentials.bak"),
|
|
88628
88879
|
// SSO / profile-only / credential_process setups have ~/.aws/config and no
|
|
88629
88880
|
// credentials file; the SDK and CLI then parse ~/.aws/credentials on every
|
|
88630
88881
|
// profile lookup. A planted primary would be a file real tools read.
|
|
88631
|
-
preferFallback: (h) =>
|
|
88882
|
+
preferFallback: (h) => import_fs94.default.existsSync(import_path93.default.join(h, ".aws", "config")),
|
|
88632
88883
|
dirMode: 448,
|
|
88633
88884
|
generate: generateAwsProfile
|
|
88634
88885
|
},
|
|
88635
88886
|
"env-file": {
|
|
88636
88887
|
kind: "env-file",
|
|
88637
|
-
primary: (h) =>
|
|
88638
|
-
fallback: (h) =>
|
|
88888
|
+
primary: (h) => import_path93.default.join(h, ".env.bak"),
|
|
88889
|
+
fallback: (h) => import_path93.default.join(h, ".env.local.bak"),
|
|
88639
88890
|
dirMode: 493,
|
|
88640
88891
|
generate: generateEnvFile
|
|
88641
88892
|
},
|
|
88642
88893
|
"ssh-key": {
|
|
88643
88894
|
kind: "ssh-key",
|
|
88644
|
-
primary: (h) =>
|
|
88645
|
-
fallback: (h) =>
|
|
88895
|
+
primary: (h) => import_path93.default.join(h, ".ssh", "id_rsa_backup"),
|
|
88896
|
+
fallback: (h) => import_path93.default.join(h, ".ssh", "id_rsa.old"),
|
|
88646
88897
|
// ssh refuses a group-writable ~/.ssh for config / known_hosts reads.
|
|
88647
88898
|
dirMode: 448,
|
|
88648
88899
|
generate: generateSshKey
|
|
@@ -88655,12 +88906,12 @@ var isKind = (s) => ALL_KINDS.includes(s);
|
|
|
88655
88906
|
var liveRecords = (kind) => loadCanaries().filter((r) => r.kind === kind && !r.retiredAt);
|
|
88656
88907
|
var fileHashOf = (p) => {
|
|
88657
88908
|
try {
|
|
88658
|
-
return sha256Hex(
|
|
88909
|
+
return sha256Hex(import_fs95.default.readFileSync(p));
|
|
88659
88910
|
} catch {
|
|
88660
88911
|
return null;
|
|
88661
88912
|
}
|
|
88662
88913
|
};
|
|
88663
|
-
function plantKind(kind, home =
|
|
88914
|
+
function plantKind(kind, home = import_os77.default.homedir()) {
|
|
88664
88915
|
const site = SITES[kind];
|
|
88665
88916
|
const live = liveRecords(kind);
|
|
88666
88917
|
if (live.length > 0) {
|
|
@@ -88679,8 +88930,8 @@ function plantKind(kind, home = import_os76.default.homedir()) {
|
|
|
88679
88930
|
const primary = site.primary(home);
|
|
88680
88931
|
const fallback = site.fallback(home);
|
|
88681
88932
|
let target;
|
|
88682
|
-
if (!
|
|
88683
|
-
else if (!
|
|
88933
|
+
if (!import_fs95.default.existsSync(primary) && !site.preferFallback?.(home)) target = primary;
|
|
88934
|
+
else if (!import_fs95.default.existsSync(fallback)) target = fallback;
|
|
88684
88935
|
else {
|
|
88685
88936
|
return {
|
|
88686
88937
|
kind,
|
|
@@ -88691,11 +88942,11 @@ function plantKind(kind, home = import_os76.default.homedir()) {
|
|
|
88691
88942
|
recordIds: []
|
|
88692
88943
|
};
|
|
88693
88944
|
}
|
|
88694
|
-
const dir2 =
|
|
88945
|
+
const dir2 = import_path94.default.dirname(target);
|
|
88695
88946
|
const gen = site.generate();
|
|
88696
|
-
const createdDir =
|
|
88697
|
-
|
|
88698
|
-
|
|
88947
|
+
const createdDir = import_fs95.default.mkdirSync(dir2, { recursive: true, mode: site.dirMode }) !== void 0;
|
|
88948
|
+
import_fs95.default.writeFileSync(target, gen.text, { mode: 384, flag: "wx" });
|
|
88949
|
+
import_fs95.default.chmodSync(target, 384);
|
|
88699
88950
|
const fileHash = sha256Hex(gen.text);
|
|
88700
88951
|
regenerateUserJail(addJailPath(target, "block"));
|
|
88701
88952
|
const recordIds = gen.values.map(
|
|
@@ -88713,14 +88964,14 @@ function plantKind(kind, home = import_os76.default.homedir()) {
|
|
|
88713
88964
|
}
|
|
88714
88965
|
function allowedPathsFor(kind, home) {
|
|
88715
88966
|
const site = SITES[kind];
|
|
88716
|
-
return [site.primary(home), site.fallback(home)].map((x) =>
|
|
88967
|
+
return [site.primary(home), site.fallback(home)].map((x) => import_path94.default.resolve(x));
|
|
88717
88968
|
}
|
|
88718
|
-
function removeKind(kind, home =
|
|
88969
|
+
function removeKind(kind, home = import_os77.default.homedir()) {
|
|
88719
88970
|
const live = liveRecords(kind);
|
|
88720
88971
|
if (live.length === 0) return { kind, action: "absent" };
|
|
88721
88972
|
const p = live[0].path;
|
|
88722
88973
|
const { fileHash, createdDir } = live[0];
|
|
88723
|
-
if (!allowedPathsFor(kind, home).includes(
|
|
88974
|
+
if (!allowedPathsFor(kind, home).includes(import_path94.default.resolve(p))) {
|
|
88724
88975
|
return {
|
|
88725
88976
|
kind,
|
|
88726
88977
|
action: "refused",
|
|
@@ -88728,7 +88979,7 @@ function removeKind(kind, home = import_os76.default.homedir()) {
|
|
|
88728
88979
|
reason: `${p} is not a path node9 plants a ${kind} decoy at; refusing to delete it. If you believe this is a decoy, remove it by hand.`
|
|
88729
88980
|
};
|
|
88730
88981
|
}
|
|
88731
|
-
if (!
|
|
88982
|
+
if (!import_fs95.default.existsSync(p)) {
|
|
88732
88983
|
for (const r of live) retireCanary(r.id);
|
|
88733
88984
|
unjail(p);
|
|
88734
88985
|
return { kind, action: "already-gone", path: p };
|
|
@@ -88741,13 +88992,13 @@ function removeKind(kind, home = import_os76.default.homedir()) {
|
|
|
88741
88992
|
reason: `${p} changed since node9 wrote it; inspect and remove it by hand`
|
|
88742
88993
|
};
|
|
88743
88994
|
}
|
|
88744
|
-
|
|
88995
|
+
import_fs95.default.unlinkSync(p);
|
|
88745
88996
|
let dirRemoved = false;
|
|
88746
88997
|
if (createdDir) {
|
|
88747
|
-
const dir2 =
|
|
88998
|
+
const dir2 = import_path94.default.dirname(p);
|
|
88748
88999
|
try {
|
|
88749
|
-
if (
|
|
88750
|
-
|
|
89000
|
+
if (import_fs95.default.readdirSync(dir2).length === 0) {
|
|
89001
|
+
import_fs95.default.rmdirSync(dir2);
|
|
88751
89002
|
dirRemoved = true;
|
|
88752
89003
|
}
|
|
88753
89004
|
} catch {
|
|
@@ -88771,14 +89022,14 @@ function statusAll() {
|
|
|
88771
89022
|
const p = live[0].path;
|
|
88772
89023
|
return {
|
|
88773
89024
|
kind,
|
|
88774
|
-
state:
|
|
89025
|
+
state: import_fs95.default.existsSync(p) ? "planted" : "missing",
|
|
88775
89026
|
path: p,
|
|
88776
89027
|
records: live.length,
|
|
88777
89028
|
plantedAt: live[0].plantedAt
|
|
88778
89029
|
};
|
|
88779
89030
|
});
|
|
88780
89031
|
}
|
|
88781
|
-
function rotateKind(kind, home =
|
|
89032
|
+
function rotateKind(kind, home = import_os77.default.homedir()) {
|
|
88782
89033
|
const removed = removeKind(kind);
|
|
88783
89034
|
if (removed.action === "refused") return { removed };
|
|
88784
89035
|
return { removed, planted: plantKind(kind, home) };
|
|
@@ -88867,15 +89118,15 @@ init_daemon3();
|
|
|
88867
89118
|
// src/cli/commands/sandbox.ts
|
|
88868
89119
|
init_cjs_shims();
|
|
88869
89120
|
var import_chalk41 = __toESM(require("chalk"));
|
|
88870
|
-
var
|
|
88871
|
-
var
|
|
89121
|
+
var import_fs98 = __toESM(require("fs"));
|
|
89122
|
+
var import_path97 = __toESM(require("path"));
|
|
88872
89123
|
var import_child_process16 = require("child_process");
|
|
88873
89124
|
init_config();
|
|
88874
89125
|
|
|
88875
89126
|
// src/sandbox/config.ts
|
|
88876
89127
|
init_cjs_shims();
|
|
88877
|
-
var
|
|
88878
|
-
var
|
|
89128
|
+
var import_fs96 = __toESM(require("fs"));
|
|
89129
|
+
var import_path95 = __toESM(require("path"));
|
|
88879
89130
|
var import_yaml2 = require("yaml");
|
|
88880
89131
|
var SANDBOX_CONFIG_FILE = "node9.sandbox.yaml";
|
|
88881
89132
|
var FORBIDDEN_ENV = /* @__PURE__ */ new Set(["NODE9_API_KEY", "NODE9_API_URL"]);
|
|
@@ -88948,16 +89199,16 @@ function scaffoldSandboxYaml(agent) {
|
|
|
88948
89199
|
return header + (0, import_yaml2.stringify)(defaultSandboxConfig(agent));
|
|
88949
89200
|
}
|
|
88950
89201
|
function sandboxConfigPath(cwd = process.cwd()) {
|
|
88951
|
-
return
|
|
89202
|
+
return import_path95.default.join(cwd, SANDBOX_CONFIG_FILE);
|
|
88952
89203
|
}
|
|
88953
89204
|
function loadSandboxConfig(cwd = process.cwd(), fallbackAgent = "claude") {
|
|
88954
89205
|
const p = sandboxConfigPath(cwd);
|
|
88955
|
-
if (!
|
|
89206
|
+
if (!import_fs96.default.existsSync(p)) {
|
|
88956
89207
|
throw new Error(`sandbox: ${SANDBOX_CONFIG_FILE} not found \u2014 run \`node9 sandbox new\` first.`);
|
|
88957
89208
|
}
|
|
88958
89209
|
let raw;
|
|
88959
89210
|
try {
|
|
88960
|
-
raw = (0, import_yaml2.parse)(
|
|
89211
|
+
raw = (0, import_yaml2.parse)(import_fs96.default.readFileSync(p, "utf-8"));
|
|
88961
89212
|
} catch (err2) {
|
|
88962
89213
|
throw new Error(
|
|
88963
89214
|
`sandbox: ${SANDBOX_CONFIG_FILE} is not valid YAML \u2014 ${err2.message}`
|
|
@@ -89018,14 +89269,14 @@ init_atomic_write();
|
|
|
89018
89269
|
|
|
89019
89270
|
// src/sandbox/runtime.ts
|
|
89020
89271
|
init_cjs_shims();
|
|
89021
|
-
var
|
|
89022
|
-
var
|
|
89023
|
-
var
|
|
89272
|
+
var import_fs97 = __toESM(require("fs"));
|
|
89273
|
+
var import_os78 = __toESM(require("os"));
|
|
89274
|
+
var import_path96 = __toESM(require("path"));
|
|
89024
89275
|
var import_crypto26 = __toESM(require("crypto"));
|
|
89025
89276
|
var import_child_process15 = require("child_process");
|
|
89026
89277
|
init_templates();
|
|
89027
89278
|
function sandboxDataDir(cwd = process.cwd()) {
|
|
89028
|
-
return
|
|
89279
|
+
return import_path96.default.join(cwd, ".node9", "sandbox", "data");
|
|
89029
89280
|
}
|
|
89030
89281
|
function detectEngine(engine) {
|
|
89031
89282
|
const r = (0, import_child_process15.spawnSync)(engine, ["--version"], { encoding: "utf-8" });
|
|
@@ -89036,7 +89287,7 @@ function detectEngine(engine) {
|
|
|
89036
89287
|
}
|
|
89037
89288
|
function agentCredentialsMount(agent) {
|
|
89038
89289
|
const rel = agent === "codex" ? ".codex/auth.json" : ".claude/.credentials.json";
|
|
89039
|
-
return { hostPath:
|
|
89290
|
+
return { hostPath: import_path96.default.join(import_os78.default.homedir(), rel), target: `/home/${RUN_AS_USER}/${rel}` };
|
|
89040
89291
|
}
|
|
89041
89292
|
function buildRunArgs(opts) {
|
|
89042
89293
|
const { config, workspaceHostPath, dataHostPath, allowlistHostPath, agentArgs } = opts;
|
|
@@ -89046,7 +89297,7 @@ function buildRunArgs(opts) {
|
|
|
89046
89297
|
args.push("-v", `${allowlistHostPath}:${ALLOWED_DOMAINS_PATH}:ro`);
|
|
89047
89298
|
if (config.node9.mountAgentCredentials) {
|
|
89048
89299
|
const creds = agentCredentialsMount(config.agent);
|
|
89049
|
-
if (
|
|
89300
|
+
if (import_fs97.default.existsSync(creds.hostPath)) {
|
|
89050
89301
|
args.push("-v", `${creds.hostPath}:${creds.target}`);
|
|
89051
89302
|
}
|
|
89052
89303
|
}
|
|
@@ -89064,30 +89315,30 @@ function imageContentHash(dockerfile, entrypoint) {
|
|
|
89064
89315
|
return import_crypto26.default.createHash("sha256").update(dockerfile).update("\0").update(entrypoint).digest("hex").slice(0, 16);
|
|
89065
89316
|
}
|
|
89066
89317
|
function sandboxBuildDir(cwd = process.cwd()) {
|
|
89067
|
-
return
|
|
89318
|
+
return import_path96.default.join(cwd, ".node9", "sandbox", "build");
|
|
89068
89319
|
}
|
|
89069
89320
|
function writeBuildContext(cwd, dockerfile, entrypoint) {
|
|
89070
89321
|
const dir2 = sandboxBuildDir(cwd);
|
|
89071
|
-
|
|
89072
|
-
|
|
89073
|
-
|
|
89322
|
+
import_fs97.default.mkdirSync(dir2, { recursive: true });
|
|
89323
|
+
import_fs97.default.writeFileSync(import_path96.default.join(dir2, "Dockerfile"), dockerfile);
|
|
89324
|
+
import_fs97.default.writeFileSync(import_path96.default.join(dir2, "entrypoint.sh"), entrypoint);
|
|
89074
89325
|
return dir2;
|
|
89075
89326
|
}
|
|
89076
89327
|
function writeAllowlist(cwd, hosts) {
|
|
89077
|
-
const dir2 =
|
|
89078
|
-
|
|
89079
|
-
const p =
|
|
89080
|
-
|
|
89328
|
+
const dir2 = import_path96.default.join(cwd, ".node9", "sandbox");
|
|
89329
|
+
import_fs97.default.mkdirSync(dir2, { recursive: true });
|
|
89330
|
+
const p = import_path96.default.join(dir2, "allowed-domains.txt");
|
|
89331
|
+
import_fs97.default.writeFileSync(p, hosts.join("\n") + "\n");
|
|
89081
89332
|
return p;
|
|
89082
89333
|
}
|
|
89083
89334
|
function resolveHomePath(p) {
|
|
89084
|
-
return p.startsWith("~") ?
|
|
89335
|
+
return p.startsWith("~") ? import_path96.default.join(import_os78.default.homedir(), p.slice(1)) : import_path96.default.resolve(p);
|
|
89085
89336
|
}
|
|
89086
89337
|
|
|
89087
89338
|
// src/cli/commands/sandbox.ts
|
|
89088
89339
|
function seedDataDirConfig(dataDir, sandbox) {
|
|
89089
|
-
|
|
89090
|
-
const configPath2 =
|
|
89340
|
+
import_fs98.default.mkdirSync(dataDir, { recursive: true });
|
|
89341
|
+
const configPath2 = import_path97.default.join(dataDir, "config.json");
|
|
89091
89342
|
const seed = {
|
|
89092
89343
|
settings: {
|
|
89093
89344
|
approvers: {
|
|
@@ -89098,7 +89349,7 @@ function seedDataDirConfig(dataDir, sandbox) {
|
|
|
89098
89349
|
}
|
|
89099
89350
|
}
|
|
89100
89351
|
};
|
|
89101
|
-
|
|
89352
|
+
import_fs98.default.writeFileSync(configPath2, JSON.stringify(seed, null, 2), { mode: 384 });
|
|
89102
89353
|
}
|
|
89103
89354
|
function registerSandboxCommand(program2, version2) {
|
|
89104
89355
|
const node9Version2 = pinnedNode9Version(version2);
|
|
@@ -89107,7 +89358,7 @@ function registerSandboxCommand(program2, version2) {
|
|
|
89107
89358
|
const agent = opts.agent === "codex" ? "codex" : "claude";
|
|
89108
89359
|
const p = sandboxConfigPath();
|
|
89109
89360
|
try {
|
|
89110
|
-
|
|
89361
|
+
import_fs98.default.writeFileSync(p, scaffoldSandboxYaml(agent), { flag: "wx" });
|
|
89111
89362
|
} catch (e) {
|
|
89112
89363
|
if (e.code !== "EEXIST") throw e;
|
|
89113
89364
|
console.log(
|
|
@@ -89154,8 +89405,8 @@ function registerSandboxCommand(program2, version2) {
|
|
|
89154
89405
|
const buildDir = writeBuildContext(cwd, dockerfile, entrypoint);
|
|
89155
89406
|
const hash2 = imageContentHash(dockerfile, entrypoint);
|
|
89156
89407
|
const image = sandbox.runtime.image;
|
|
89157
|
-
const hashFile =
|
|
89158
|
-
const lastHash =
|
|
89408
|
+
const hashFile = import_path97.default.join(sandboxBuildDir(cwd), ".image-hash");
|
|
89409
|
+
const lastHash = import_fs98.default.existsSync(hashFile) ? import_fs98.default.readFileSync(hashFile, "utf-8").trim() : "";
|
|
89159
89410
|
const imageExists = (0, import_child_process16.spawnSync)(sandbox.runtime.engine, ["image", "inspect", image], { stdio: "ignore" }).status === 0;
|
|
89160
89411
|
const needBuild = sandbox.runtime.rebuild === "always" || !imageExists || sandbox.runtime.rebuild !== "never" && lastHash !== hash2;
|
|
89161
89412
|
if (needBuild) {
|
|
@@ -89181,7 +89432,7 @@ function registerSandboxCommand(program2, version2) {
|
|
|
89181
89432
|
});
|
|
89182
89433
|
if (sandbox.node9.mountAgentCredentials) {
|
|
89183
89434
|
const creds = agentCredentialsMount(sandbox.agent);
|
|
89184
|
-
if (
|
|
89435
|
+
if (import_fs98.default.existsSync(creds.hostPath)) {
|
|
89185
89436
|
console.log(import_chalk41.default.dim(` mounting ${creds.hostPath} (agent credentials, rw)`));
|
|
89186
89437
|
} else {
|
|
89187
89438
|
console.log(
|
|
@@ -89197,20 +89448,20 @@ function registerSandboxCommand(program2, version2) {
|
|
|
89197
89448
|
process.exit(r.status ?? 0);
|
|
89198
89449
|
});
|
|
89199
89450
|
cmd.command("tail").description("Stream the sandbox's audit log (host-side)").action(() => {
|
|
89200
|
-
const auditPath =
|
|
89201
|
-
if (!
|
|
89451
|
+
const auditPath = import_path97.default.join(sandboxDataDir(), "audit.log");
|
|
89452
|
+
if (!import_fs98.default.existsSync(auditPath)) {
|
|
89202
89453
|
console.log(import_chalk41.default.dim(" no sandbox audit yet."));
|
|
89203
89454
|
return;
|
|
89204
89455
|
}
|
|
89205
89456
|
(0, import_child_process16.spawnSync)("tail", ["-f", auditPath], { stdio: "inherit" });
|
|
89206
89457
|
});
|
|
89207
89458
|
cmd.command("logs").description("Dump the sandbox's audit log").action(() => {
|
|
89208
|
-
const auditPath =
|
|
89209
|
-
if (!
|
|
89459
|
+
const auditPath = import_path97.default.join(sandboxDataDir(), "audit.log");
|
|
89460
|
+
if (!import_fs98.default.existsSync(auditPath)) {
|
|
89210
89461
|
console.log(import_chalk41.default.dim(" no sandbox audit yet."));
|
|
89211
89462
|
return;
|
|
89212
89463
|
}
|
|
89213
|
-
process.stdout.write(
|
|
89464
|
+
process.stdout.write(import_fs98.default.readFileSync(auditPath, "utf-8"));
|
|
89214
89465
|
});
|
|
89215
89466
|
cmd.command("clean").description("Remove the sandbox image, build context, and data").action(() => {
|
|
89216
89467
|
const cwd = process.cwd();
|
|
@@ -89224,7 +89475,7 @@ function registerSandboxCommand(program2, version2) {
|
|
|
89224
89475
|
stdio: "ignore"
|
|
89225
89476
|
});
|
|
89226
89477
|
}
|
|
89227
|
-
|
|
89478
|
+
import_fs98.default.rmSync(import_path97.default.join(cwd, ".node9", "sandbox"), { recursive: true, force: true });
|
|
89228
89479
|
console.log(import_chalk41.default.green(" \u2713 sandbox image + build + data removed."));
|
|
89229
89480
|
});
|
|
89230
89481
|
}
|
|
@@ -89453,12 +89704,12 @@ function registerPackageIndexCommand(program2) {
|
|
|
89453
89704
|
// src/cli/commands/skill-pin.ts
|
|
89454
89705
|
init_cjs_shims();
|
|
89455
89706
|
var import_chalk45 = __toESM(require("chalk"));
|
|
89456
|
-
var
|
|
89457
|
-
var
|
|
89458
|
-
var
|
|
89707
|
+
var import_fs99 = __toESM(require("fs"));
|
|
89708
|
+
var import_os79 = __toESM(require("os"));
|
|
89709
|
+
var import_path98 = __toESM(require("path"));
|
|
89459
89710
|
function wipeSkillSessions() {
|
|
89460
89711
|
try {
|
|
89461
|
-
|
|
89712
|
+
import_fs99.default.rmSync(import_path98.default.join(import_os79.default.homedir(), ".node9", "skill-sessions"), {
|
|
89462
89713
|
recursive: true,
|
|
89463
89714
|
force: true
|
|
89464
89715
|
});
|
|
@@ -89541,15 +89792,15 @@ function registerSkillPinCommand(program2) {
|
|
|
89541
89792
|
|
|
89542
89793
|
// src/cli/commands/decisions.ts
|
|
89543
89794
|
init_cjs_shims();
|
|
89544
|
-
var
|
|
89545
|
-
var
|
|
89546
|
-
var
|
|
89795
|
+
var import_fs100 = __toESM(require("fs"));
|
|
89796
|
+
var import_os80 = __toESM(require("os"));
|
|
89797
|
+
var import_path99 = __toESM(require("path"));
|
|
89547
89798
|
var import_chalk46 = __toESM(require("chalk"));
|
|
89548
|
-
var DECISIONS_FILE2 =
|
|
89799
|
+
var DECISIONS_FILE2 = import_path99.default.join(import_os80.default.homedir(), ".node9", "decisions.json");
|
|
89549
89800
|
function readDecisions() {
|
|
89550
89801
|
try {
|
|
89551
|
-
if (!
|
|
89552
|
-
const raw =
|
|
89802
|
+
if (!import_fs100.default.existsSync(DECISIONS_FILE2)) return {};
|
|
89803
|
+
const raw = import_fs100.default.readFileSync(DECISIONS_FILE2, "utf-8");
|
|
89553
89804
|
const parsed = JSON.parse(raw);
|
|
89554
89805
|
const out = {};
|
|
89555
89806
|
for (const [k, v] of Object.entries(parsed)) {
|
|
@@ -89561,11 +89812,11 @@ function readDecisions() {
|
|
|
89561
89812
|
}
|
|
89562
89813
|
}
|
|
89563
89814
|
function writeDecisions(d) {
|
|
89564
|
-
const dir2 =
|
|
89565
|
-
if (!
|
|
89815
|
+
const dir2 = import_path99.default.dirname(DECISIONS_FILE2);
|
|
89816
|
+
if (!import_fs100.default.existsSync(dir2)) import_fs100.default.mkdirSync(dir2, { recursive: true });
|
|
89566
89817
|
const tmp = `${DECISIONS_FILE2}.${process.pid}.tmp`;
|
|
89567
|
-
|
|
89568
|
-
|
|
89818
|
+
import_fs100.default.writeFileSync(tmp, JSON.stringify(d, null, 2));
|
|
89819
|
+
import_fs100.default.renameSync(tmp, DECISIONS_FILE2);
|
|
89569
89820
|
}
|
|
89570
89821
|
function registerDecisionsCommand(program2) {
|
|
89571
89822
|
const cmd = program2.command("decisions").description('Manage persistent "Always Allow" / "Always Deny" tool decisions');
|
|
@@ -89623,15 +89874,15 @@ Persistent decisions (${entries.length})
|
|
|
89623
89874
|
// src/cli/commands/dlp.ts
|
|
89624
89875
|
init_cjs_shims();
|
|
89625
89876
|
var import_chalk47 = __toESM(require("chalk"));
|
|
89626
|
-
var
|
|
89627
|
-
var
|
|
89628
|
-
var
|
|
89877
|
+
var import_fs101 = __toESM(require("fs"));
|
|
89878
|
+
var import_path100 = __toESM(require("path"));
|
|
89879
|
+
var import_os81 = __toESM(require("os"));
|
|
89629
89880
|
init_safe_text();
|
|
89630
|
-
var AUDIT_LOG =
|
|
89631
|
-
var RESOLVED_FILE =
|
|
89881
|
+
var AUDIT_LOG = import_path100.default.join(import_os81.default.homedir(), ".node9", "audit.log");
|
|
89882
|
+
var RESOLVED_FILE = import_path100.default.join(import_os81.default.homedir(), ".node9", "dlp-resolved.json");
|
|
89632
89883
|
function loadResolved() {
|
|
89633
89884
|
try {
|
|
89634
|
-
const raw = JSON.parse(
|
|
89885
|
+
const raw = JSON.parse(import_fs101.default.readFileSync(RESOLVED_FILE, "utf-8"));
|
|
89635
89886
|
return new Set(raw);
|
|
89636
89887
|
} catch {
|
|
89637
89888
|
return /* @__PURE__ */ new Set();
|
|
@@ -89639,13 +89890,13 @@ function loadResolved() {
|
|
|
89639
89890
|
}
|
|
89640
89891
|
function saveResolved(resolved) {
|
|
89641
89892
|
try {
|
|
89642
|
-
|
|
89893
|
+
import_fs101.default.writeFileSync(RESOLVED_FILE, JSON.stringify([...resolved], null, 2), { mode: 384 });
|
|
89643
89894
|
} catch {
|
|
89644
89895
|
}
|
|
89645
89896
|
}
|
|
89646
89897
|
function loadDlpFindings() {
|
|
89647
|
-
if (!
|
|
89648
|
-
return
|
|
89898
|
+
if (!import_fs101.default.existsSync(AUDIT_LOG)) return [];
|
|
89899
|
+
return import_fs101.default.readFileSync(AUDIT_LOG, "utf-8").split("\n").flatMap((line) => {
|
|
89649
89900
|
if (!line.trim()) return [];
|
|
89650
89901
|
try {
|
|
89651
89902
|
const e = JSON.parse(line);
|
|
@@ -89744,15 +89995,15 @@ function registerDlpCommand(program2) {
|
|
|
89744
89995
|
// src/cli/commands/mask.ts
|
|
89745
89996
|
init_cjs_shims();
|
|
89746
89997
|
var import_chalk48 = __toESM(require("chalk"));
|
|
89747
|
-
var
|
|
89748
|
-
var
|
|
89749
|
-
var
|
|
89998
|
+
var import_fs102 = __toESM(require("fs"));
|
|
89999
|
+
var import_path101 = __toESM(require("path"));
|
|
90000
|
+
var import_os82 = __toESM(require("os"));
|
|
89750
90001
|
init_dlp();
|
|
89751
90002
|
function findJsonlFiles(dir2) {
|
|
89752
90003
|
const results = [];
|
|
89753
|
-
if (!
|
|
89754
|
-
for (const entry of
|
|
89755
|
-
const full =
|
|
90004
|
+
if (!import_fs102.default.existsSync(dir2)) return results;
|
|
90005
|
+
for (const entry of import_fs102.default.readdirSync(dir2, { withFileTypes: true })) {
|
|
90006
|
+
const full = import_path101.default.join(dir2, entry.name);
|
|
89756
90007
|
if (entry.isDirectory()) results.push(...findJsonlFiles(full));
|
|
89757
90008
|
else if (entry.isFile() && entry.name.endsWith(".jsonl")) results.push(full);
|
|
89758
90009
|
}
|
|
@@ -89795,7 +90046,7 @@ function redactJson(obj) {
|
|
|
89795
90046
|
function processFile(filePath, dryRun) {
|
|
89796
90047
|
let raw;
|
|
89797
90048
|
try {
|
|
89798
|
-
raw =
|
|
90049
|
+
raw = import_fs102.default.readFileSync(filePath, "utf-8");
|
|
89799
90050
|
} catch {
|
|
89800
90051
|
return { redactedLines: 0, patterns: [] };
|
|
89801
90052
|
}
|
|
@@ -89827,14 +90078,14 @@ function processFile(filePath, dryRun) {
|
|
|
89827
90078
|
}
|
|
89828
90079
|
}
|
|
89829
90080
|
if (!dryRun && redactedLines > 0) {
|
|
89830
|
-
|
|
90081
|
+
import_fs102.default.writeFileSync(filePath, newLines.join("\n"), "utf-8");
|
|
89831
90082
|
}
|
|
89832
90083
|
return { redactedLines, patterns };
|
|
89833
90084
|
}
|
|
89834
90085
|
function processJsonFile(filePath, dryRun) {
|
|
89835
90086
|
let raw;
|
|
89836
90087
|
try {
|
|
89837
|
-
raw =
|
|
90088
|
+
raw = import_fs102.default.readFileSync(filePath, "utf-8");
|
|
89838
90089
|
} catch {
|
|
89839
90090
|
return { redactedLines: 0, patterns: [] };
|
|
89840
90091
|
}
|
|
@@ -89847,15 +90098,15 @@ function processJsonFile(filePath, dryRun) {
|
|
|
89847
90098
|
const { value, modified, found } = redactJson(parsed);
|
|
89848
90099
|
if (!modified) return { redactedLines: 0, patterns: [] };
|
|
89849
90100
|
if (!dryRun) {
|
|
89850
|
-
|
|
90101
|
+
import_fs102.default.writeFileSync(filePath, JSON.stringify(value, null, 2), "utf-8");
|
|
89851
90102
|
}
|
|
89852
90103
|
return { redactedLines: 1, patterns: found };
|
|
89853
90104
|
}
|
|
89854
90105
|
function findJsonFiles(dir2) {
|
|
89855
90106
|
const results = [];
|
|
89856
|
-
if (!
|
|
89857
|
-
for (const entry of
|
|
89858
|
-
const full =
|
|
90107
|
+
if (!import_fs102.default.existsSync(dir2)) return results;
|
|
90108
|
+
for (const entry of import_fs102.default.readdirSync(dir2, { withFileTypes: true })) {
|
|
90109
|
+
const full = import_path101.default.join(dir2, entry.name);
|
|
89859
90110
|
if (entry.isDirectory()) results.push(...findJsonFiles(full));
|
|
89860
90111
|
else if (entry.isFile() && entry.name.endsWith(".json")) results.push(full);
|
|
89861
90112
|
}
|
|
@@ -89864,9 +90115,9 @@ function findJsonFiles(dir2) {
|
|
|
89864
90115
|
function registerMaskCommand(program2) {
|
|
89865
90116
|
program2.command("mask").description("Redact plaintext secrets from local AI session history files").option("--dry-run", "show what would be redacted without making changes").option("--all", "scan all history (default: last 30 days)").action(async (options) => {
|
|
89866
90117
|
const dryRun = !!options.dryRun;
|
|
89867
|
-
const home =
|
|
89868
|
-
const claudeDir =
|
|
89869
|
-
const geminiDir =
|
|
90118
|
+
const home = import_os82.default.homedir();
|
|
90119
|
+
const claudeDir = import_path101.default.join(home, ".claude", "projects");
|
|
90120
|
+
const geminiDir = import_path101.default.join(home, ".gemini", "tmp");
|
|
89870
90121
|
const allFiles = [
|
|
89871
90122
|
...findJsonlFiles(claudeDir).map((p) => ({ path: p, type: "jsonl" })),
|
|
89872
90123
|
...findJsonFiles(geminiDir).map((p) => ({ path: p, type: "json" }))
|
|
@@ -89874,7 +90125,7 @@ function registerMaskCommand(program2) {
|
|
|
89874
90125
|
const cutoff = options.all ? null : new Date(Date.now() - 30 * 24 * 60 * 60 * 1e3);
|
|
89875
90126
|
const filtered = cutoff ? allFiles.filter((f) => {
|
|
89876
90127
|
try {
|
|
89877
|
-
return
|
|
90128
|
+
return import_fs102.default.statSync(f.path).mtime >= cutoff;
|
|
89878
90129
|
} catch {
|
|
89879
90130
|
return false;
|
|
89880
90131
|
}
|
|
@@ -89931,7 +90182,7 @@ function registerMaskCommand(program2) {
|
|
|
89931
90182
|
init_blast();
|
|
89932
90183
|
init_safe_text();
|
|
89933
90184
|
var { version } = JSON.parse(
|
|
89934
|
-
|
|
90185
|
+
import_fs106.default.readFileSync(import_path105.default.join(__dirname, "../package.json"), "utf-8")
|
|
89935
90186
|
);
|
|
89936
90187
|
var program = new import_commander.Command();
|
|
89937
90188
|
program.name("node9").description("The Sudo Command for AI Agents").version(version);
|
|
@@ -90089,8 +90340,8 @@ function undoLeftoverNote() {
|
|
|
90089
90340
|
program.command("uninstall").description("Remove all Node9 hooks and optionally delete config files").option("--purge", "Also delete ~/.node9/ directory (config, audit log, credentials)").action(async (options) => {
|
|
90090
90341
|
console.log(import_chalk50.default.cyan("\n\u{1F6E1}\uFE0F Node9 Uninstall\n"));
|
|
90091
90342
|
try {
|
|
90092
|
-
const credRaw =
|
|
90093
|
-
|
|
90343
|
+
const credRaw = import_fs106.default.readFileSync(
|
|
90344
|
+
import_path105.default.join(import_os86.default.homedir(), ".node9", "credentials.json"),
|
|
90094
90345
|
"utf-8"
|
|
90095
90346
|
);
|
|
90096
90347
|
const prof = JSON.parse(credRaw)[process.env.NODE9_PROFILE || "default"];
|
|
@@ -90165,7 +90416,7 @@ program.command("uninstall").description("Remove all Node9 hooks and optionally
|
|
|
90165
90416
|
if (removed.length > 0 || refused.length > 0) {
|
|
90166
90417
|
console.log(import_chalk50.default.bold("\nRemoving decoy credentials..."));
|
|
90167
90418
|
for (const r of removed) {
|
|
90168
|
-
if (r.path) console.log(import_chalk50.default.green(` \u2705 ${r.path.replace(
|
|
90419
|
+
if (r.path) console.log(import_chalk50.default.green(` \u2705 ${r.path.replace(import_os86.default.homedir(), "~")}`));
|
|
90169
90420
|
}
|
|
90170
90421
|
for (const r of refused) {
|
|
90171
90422
|
decoysLeft.push(r.path ?? "(unknown path)");
|
|
@@ -90182,8 +90433,8 @@ program.command("uninstall").description("Remove all Node9 hooks and optionally
|
|
|
90182
90433
|
decoysLeft = ["(the decoy registry could not be read)"];
|
|
90183
90434
|
}
|
|
90184
90435
|
if (options.purge) {
|
|
90185
|
-
const node9Dir =
|
|
90186
|
-
if (
|
|
90436
|
+
const node9Dir = import_path105.default.join(import_os86.default.homedir(), ".node9");
|
|
90437
|
+
if (import_fs106.default.existsSync(node9Dir)) {
|
|
90187
90438
|
const alsoSnapshots = undoLeftoverPaths().length > 0 ? ", old undo snapshots" : "";
|
|
90188
90439
|
if (decoysLeft.length > 0) {
|
|
90189
90440
|
console.error(import_chalk50.default.red("\n \u26A0\uFE0F Decoy credential files are still on disk:"));
|
|
@@ -90199,8 +90450,8 @@ program.command("uninstall").description("Remove all Node9 hooks and optionally
|
|
|
90199
90450
|
default: false
|
|
90200
90451
|
});
|
|
90201
90452
|
if (confirmed) {
|
|
90202
|
-
|
|
90203
|
-
if (
|
|
90453
|
+
import_fs106.default.rmSync(node9Dir, { recursive: true });
|
|
90454
|
+
if (import_fs106.default.existsSync(node9Dir)) {
|
|
90204
90455
|
console.error(
|
|
90205
90456
|
import_chalk50.default.red("\n \u26A0\uFE0F ~/.node9/ could not be fully deleted \u2014 remove it manually.")
|
|
90206
90457
|
);
|
|
@@ -90356,7 +90607,7 @@ program.command("tail").description("Stream live agent activity to the terminal"
|
|
|
90356
90607
|
});
|
|
90357
90608
|
program.command("monitor").description("Live interactive dashboard \u2014 activity feed, approvals, security signals").action(async () => {
|
|
90358
90609
|
try {
|
|
90359
|
-
const dashboardPath =
|
|
90610
|
+
const dashboardPath = import_path105.default.join(__dirname, "dashboard.mjs");
|
|
90360
90611
|
const dynamicImport = new Function("id", "return import(id)");
|
|
90361
90612
|
const mod = await dynamicImport(`file://${dashboardPath}`);
|
|
90362
90613
|
await mod.startMonitor();
|
|
@@ -90394,14 +90645,14 @@ Claude Code spawns this command every ~300ms and writes a JSON payload to stdin.
|
|
|
90394
90645
|
Run "node9 addto claude" to register it as the statusLine.`
|
|
90395
90646
|
).argument("[subcommand]", 'Optional: "debug on" / "debug off" to toggle stdin logging').argument("[state]", 'on|off \u2014 used with "debug" subcommand').action(async (subcommand, state) => {
|
|
90396
90647
|
if (subcommand === "debug") {
|
|
90397
|
-
const flagFile =
|
|
90648
|
+
const flagFile = import_path105.default.join(import_os86.default.homedir(), ".node9", "hud-debug");
|
|
90398
90649
|
if (state === "on") {
|
|
90399
|
-
|
|
90400
|
-
|
|
90650
|
+
import_fs106.default.mkdirSync(import_path105.default.dirname(flagFile), { recursive: true });
|
|
90651
|
+
import_fs106.default.writeFileSync(flagFile, "");
|
|
90401
90652
|
console.log("HUD debug logging enabled \u2192 ~/.node9/hud-debug.log");
|
|
90402
90653
|
console.log("Tail it with: tail -f ~/.node9/hud-debug.log");
|
|
90403
90654
|
} else if (state === "off") {
|
|
90404
|
-
if (
|
|
90655
|
+
if (import_fs106.default.existsSync(flagFile)) import_fs106.default.unlinkSync(flagFile);
|
|
90405
90656
|
console.log("HUD debug logging disabled.");
|
|
90406
90657
|
} else {
|
|
90407
90658
|
console.error("Usage: node9 hud debug on|off");
|
|
@@ -90535,9 +90786,9 @@ if (process.argv[2] !== "daemon") {
|
|
|
90535
90786
|
const isCheckHook = process.argv[2] === "check";
|
|
90536
90787
|
if (isCheckHook) {
|
|
90537
90788
|
if (process.env.NODE9_DEBUG === "1" || getConfig().settings.enableHookLogDebug) {
|
|
90538
|
-
const logPath =
|
|
90789
|
+
const logPath = import_path105.default.join(import_os86.default.homedir(), ".node9", "hook-debug.log");
|
|
90539
90790
|
const msg = reason instanceof Error ? reason.message : String(reason);
|
|
90540
|
-
|
|
90791
|
+
import_fs106.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] UNHANDLED: ${msg}
|
|
90541
90792
|
`);
|
|
90542
90793
|
}
|
|
90543
90794
|
process.exit(0);
|