@node9/proxy 1.64.0 → 1.65.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +1064 -792
- package/dist/cli.mjs +1044 -772
- package/dist/dashboard.mjs +2 -1
- package/dist/index.js +25 -10
- package/dist/index.mjs +25 -10
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -243,8 +243,8 @@ function sanitizeConfig(raw) {
|
|
|
243
243
|
}
|
|
244
244
|
}
|
|
245
245
|
const lines = result.error.issues.map((issue) => {
|
|
246
|
-
const
|
|
247
|
-
return ` \u2022 ${
|
|
246
|
+
const path72 = issue.path.length > 0 ? issue.path.join(".") : "root";
|
|
247
|
+
return ` \u2022 ${path72}: ${issue.message}`;
|
|
248
248
|
});
|
|
249
249
|
return {
|
|
250
250
|
sanitized,
|
|
@@ -1455,9 +1455,9 @@ function matchesPattern(text, patterns) {
|
|
|
1455
1455
|
const withoutDotSlash = text.replace(/^\.\//, "");
|
|
1456
1456
|
return isMatch(withoutDotSlash) || isMatch(`./${withoutDotSlash}`);
|
|
1457
1457
|
}
|
|
1458
|
-
function getNestedValue(obj,
|
|
1458
|
+
function getNestedValue(obj, path72) {
|
|
1459
1459
|
if (!obj || typeof obj !== "object") return null;
|
|
1460
|
-
const segments =
|
|
1460
|
+
const segments = path72.split(".");
|
|
1461
1461
|
for (const seg of segments) {
|
|
1462
1462
|
if (FORBIDDEN_PATH_SEGMENTS.has(seg)) return null;
|
|
1463
1463
|
}
|
|
@@ -4612,6 +4612,7 @@ function getActiveEnvironment(config) {
|
|
|
4612
4612
|
}
|
|
4613
4613
|
function readRulesCacheResilient(cacheFile) {
|
|
4614
4614
|
let existed = false;
|
|
4615
|
+
let sawReadError = false;
|
|
4615
4616
|
for (let attempt = 0; attempt < 3; attempt++) {
|
|
4616
4617
|
let content;
|
|
4617
4618
|
try {
|
|
@@ -4619,30 +4620,39 @@ function readRulesCacheResilient(cacheFile) {
|
|
|
4619
4620
|
existed = true;
|
|
4620
4621
|
} catch (err2) {
|
|
4621
4622
|
if (err2.code === "ENOENT") return {};
|
|
4623
|
+
sawReadError = true;
|
|
4622
4624
|
continue;
|
|
4623
4625
|
}
|
|
4624
4626
|
try {
|
|
4625
|
-
|
|
4627
|
+
const parsed = JSON.parse(content);
|
|
4628
|
+
lastParsedRulesCache = parsed;
|
|
4629
|
+
return parsed;
|
|
4626
4630
|
} catch {
|
|
4627
4631
|
}
|
|
4628
4632
|
}
|
|
4629
|
-
if (existed) {
|
|
4633
|
+
if (existed || sawReadError) {
|
|
4630
4634
|
const backup = import_path4.default.join(import_path4.default.dirname(cacheFile), "rules-cache.last-good.json");
|
|
4631
4635
|
if (backup !== cacheFile) {
|
|
4632
4636
|
try {
|
|
4633
4637
|
const raw = JSON.parse(import_fs4.default.readFileSync(backup, "utf-8"));
|
|
4634
4638
|
logCacheReadIssue(cacheFile, "RULES_CACHE_CORRUPT_USED_BACKUP");
|
|
4639
|
+
lastParsedRulesCache = raw;
|
|
4635
4640
|
return raw;
|
|
4636
4641
|
} catch {
|
|
4637
4642
|
}
|
|
4638
4643
|
}
|
|
4644
|
+
if (lastParsedRulesCache) {
|
|
4645
|
+
logCacheReadIssue(cacheFile, "RULES_CACHE_USED_MEMORY");
|
|
4646
|
+
return lastParsedRulesCache;
|
|
4647
|
+
}
|
|
4639
4648
|
logCacheReadIssue(cacheFile, "RULES_CACHE_UNREADABLE");
|
|
4640
4649
|
}
|
|
4641
4650
|
return {};
|
|
4642
4651
|
}
|
|
4643
4652
|
function logCacheReadIssue(cacheFile, kind) {
|
|
4644
|
-
|
|
4645
|
-
|
|
4653
|
+
const now = Date.now();
|
|
4654
|
+
if (now - cacheReadLastLoggedAt < CACHE_LOG_REARM_MS) return;
|
|
4655
|
+
cacheReadLastLoggedAt = now;
|
|
4646
4656
|
try {
|
|
4647
4657
|
import_fs4.default.appendFileSync(
|
|
4648
4658
|
import_path4.default.join(import_os4.default.homedir(), ".node9", "hook-debug.log"),
|
|
@@ -4893,10 +4903,10 @@ function getConfig(cwd) {
|
|
|
4893
4903
|
}
|
|
4894
4904
|
if (Array.isArray(mc.jailPaths)) {
|
|
4895
4905
|
for (const jp of mc.jailPaths) {
|
|
4896
|
-
const
|
|
4897
|
-
if (!
|
|
4906
|
+
const path72 = typeof jp?.path === "string" ? jp.path.trim() : "";
|
|
4907
|
+
if (!path72) continue;
|
|
4898
4908
|
const verdict = jp?.verdict === "review" ? "review" : "block";
|
|
4899
|
-
for (const r of pathRules(
|
|
4909
|
+
for (const r of pathRules(path72, verdict, "org-managed jail")) {
|
|
4900
4910
|
mergedPolicy.smartRules.push({ ...r, name: `org:${r.name}` });
|
|
4901
4911
|
}
|
|
4902
4912
|
}
|
|
@@ -5049,7 +5059,7 @@ ${error.replace("Invalid config:\n", "")}
|
|
|
5049
5059
|
}
|
|
5050
5060
|
return sanitized;
|
|
5051
5061
|
}
|
|
5052
|
-
var import_fs4, import_path4, import_os4, DANGEROUS_WORDS, DEFAULT_CONFIG, ADVISORY_SMART_RULES, cachedConfig,
|
|
5062
|
+
var import_fs4, import_path4, import_os4, DANGEROUS_WORDS, DEFAULT_CONFIG, ADVISORY_SMART_RULES, cachedConfig, lastParsedRulesCache, CACHE_LOG_REARM_MS, cacheReadLastLoggedAt;
|
|
5053
5063
|
var init_config = __esm({
|
|
5054
5064
|
"src/config/index.ts"() {
|
|
5055
5065
|
"use strict";
|
|
@@ -5339,7 +5349,9 @@ var init_config = __esm({
|
|
|
5339
5349
|
}
|
|
5340
5350
|
];
|
|
5341
5351
|
cachedConfig = null;
|
|
5342
|
-
|
|
5352
|
+
lastParsedRulesCache = null;
|
|
5353
|
+
CACHE_LOG_REARM_MS = 5 * 60 * 1e3;
|
|
5354
|
+
cacheReadLastLoggedAt = 0;
|
|
5343
5355
|
}
|
|
5344
5356
|
});
|
|
5345
5357
|
|
|
@@ -6057,6 +6069,18 @@ async function isDaemonReachable(timeoutMs = 500) {
|
|
|
6057
6069
|
return false;
|
|
6058
6070
|
}
|
|
6059
6071
|
}
|
|
6072
|
+
async function probeDaemonHealth(timeoutMs = 800) {
|
|
6073
|
+
try {
|
|
6074
|
+
const res = await fetch(`http://${DAEMON_HOST}:${DAEMON_PORT}/health`, {
|
|
6075
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
6076
|
+
});
|
|
6077
|
+
if (!res.ok) return { kind: "no-health" };
|
|
6078
|
+
const j = await res.json().catch(() => null);
|
|
6079
|
+
return j && typeof j === "object" ? { kind: "health", health: j } : { kind: "no-health" };
|
|
6080
|
+
} catch {
|
|
6081
|
+
return { kind: "unreachable" };
|
|
6082
|
+
}
|
|
6083
|
+
}
|
|
6060
6084
|
async function daemonHasInteractiveApprover(timeoutMs = 400) {
|
|
6061
6085
|
try {
|
|
6062
6086
|
const res = await fetch(`http://${DAEMON_HOST}:${DAEMON_PORT}/approver`, {
|
|
@@ -7032,6 +7056,7 @@ async function _authorizeHeadlessCore(toolName, args, metaArg, options) {
|
|
|
7032
7056
|
let riskMetadata;
|
|
7033
7057
|
let statefulRecoveryCommand;
|
|
7034
7058
|
let localSmartRuleMatched = false;
|
|
7059
|
+
let hardBlockDowngraded = false;
|
|
7035
7060
|
let taintWarning = null;
|
|
7036
7061
|
if (isNetworkTool(toolName, args)) {
|
|
7037
7062
|
const filePaths = extractFilePaths(toolName, args);
|
|
@@ -7273,6 +7298,7 @@ async function _authorizeHeadlessCore(toolName, args, metaArg, options) {
|
|
|
7273
7298
|
return { approved: true, checkedBy: "local-policy" };
|
|
7274
7299
|
}
|
|
7275
7300
|
if (policyResult.decision === "block") {
|
|
7301
|
+
hardBlockDowngraded = true;
|
|
7276
7302
|
const daemonUp = isDaemonRunning();
|
|
7277
7303
|
let humanApproverReachable = false;
|
|
7278
7304
|
if (!policyResult.dependsOnStatePredicates?.length && daemonUp && !isTestEnv2) {
|
|
@@ -7346,7 +7372,8 @@ async function _authorizeHeadlessCore(toolName, args, metaArg, options) {
|
|
|
7346
7372
|
explainableLabel = policyResult.blockedByLabel || "Local Config";
|
|
7347
7373
|
policyMatchedField = policyResult.matchedField;
|
|
7348
7374
|
policyMatchedWord = policyResult.matchedWord;
|
|
7349
|
-
if (policyResult.ruleName || policyResult.tier === 7
|
|
7375
|
+
if (policyResult.ruleName || policyResult.tier === 7 || hardBlockDowngraded)
|
|
7376
|
+
localSmartRuleMatched = true;
|
|
7350
7377
|
if (policyResult.ruleDescription) policyRuleDescription = policyResult.ruleDescription;
|
|
7351
7378
|
else if (policyResult.reason) policyRuleDescription = policyResult.reason;
|
|
7352
7379
|
riskMetadata = computeRiskMetadata(
|
|
@@ -7358,7 +7385,7 @@ async function _authorizeHeadlessCore(toolName, args, metaArg, options) {
|
|
|
7358
7385
|
policyResult.ruleName
|
|
7359
7386
|
);
|
|
7360
7387
|
if (policyRuleDescription) riskMetadata.ruleDescription = policyRuleDescription.slice(0, 200);
|
|
7361
|
-
const persistent = policyResult.ruleName || policyResult.tier === 7 ? null : getPersistentDecision(toolName);
|
|
7388
|
+
const persistent = policyResult.ruleName || policyResult.tier === 7 || hardBlockDowngraded ? null : getPersistentDecision(toolName);
|
|
7362
7389
|
if (persistent === "allow" && !appPermReview) {
|
|
7363
7390
|
if (!isManual) appendLocalAudit(toolName, args, "allow", "persistent", meta, hashAuditArgs);
|
|
7364
7391
|
return { approved: true, checkedBy: "persistent" };
|
|
@@ -7391,7 +7418,7 @@ async function _authorizeHeadlessCore(toolName, args, metaArg, options) {
|
|
|
7391
7418
|
return { approved: true };
|
|
7392
7419
|
}
|
|
7393
7420
|
}
|
|
7394
|
-
if (!taintWarning && !appPermReview && getActiveTrustSession(toolName, args)) {
|
|
7421
|
+
if (!taintWarning && !appPermReview && !hardBlockDowngraded && getActiveTrustSession(toolName, args)) {
|
|
7395
7422
|
if (!isManual) appendLocalAudit(toolName, args, "allow", "trust", meta, hashAuditArgs);
|
|
7396
7423
|
return { approved: true, checkedBy: "trust" };
|
|
7397
7424
|
}
|
|
@@ -7431,7 +7458,7 @@ ${appPermReview}`
|
|
|
7431
7458
|
}
|
|
7432
7459
|
}
|
|
7433
7460
|
const cloudEnforcedForDefer = approvers.cloud && !!creds?.apiKey;
|
|
7434
|
-
if (options?.deferReview && !taintWarning && !appPermReview && !cloudEnforcedForDefer) {
|
|
7461
|
+
if (options?.deferReview && !hardBlockDowngraded && !taintWarning && !appPermReview && !cloudEnforcedForDefer) {
|
|
7435
7462
|
return {
|
|
7436
7463
|
approved: false,
|
|
7437
7464
|
review: true,
|
|
@@ -7455,7 +7482,7 @@ ${appPermReview}`
|
|
|
7455
7482
|
forceReview
|
|
7456
7483
|
);
|
|
7457
7484
|
if (!initResult.pending) {
|
|
7458
|
-
if (initResult.shadowMode && !appPermReview) {
|
|
7485
|
+
if (initResult.shadowMode && !localSmartRuleMatched && !options?.localSmartRuleMatched && !appPermReview) {
|
|
7459
7486
|
return { approved: true, checkedBy: "cloud" };
|
|
7460
7487
|
}
|
|
7461
7488
|
if (!localSmartRuleMatched && !options?.localSmartRuleMatched && !appPermReview) {
|
|
@@ -15482,6 +15509,73 @@ var init_scan = __esm({
|
|
|
15482
15509
|
}
|
|
15483
15510
|
});
|
|
15484
15511
|
|
|
15512
|
+
// src/daemon/build-id.ts
|
|
15513
|
+
function readOwnVersion() {
|
|
15514
|
+
for (const rel of ["../package.json", "../../package.json"]) {
|
|
15515
|
+
try {
|
|
15516
|
+
const raw = import_fs26.default.readFileSync(import_path28.default.join(__dirname, rel), "utf-8");
|
|
15517
|
+
const v = JSON.parse(raw).version;
|
|
15518
|
+
if (typeof v === "string" && v.length > 0) return v;
|
|
15519
|
+
} catch {
|
|
15520
|
+
}
|
|
15521
|
+
}
|
|
15522
|
+
return "0.0.0";
|
|
15523
|
+
}
|
|
15524
|
+
function computeBuildId(entry = process.argv[1] ?? "") {
|
|
15525
|
+
let mtimeMs = 0;
|
|
15526
|
+
try {
|
|
15527
|
+
if (entry) mtimeMs = import_fs26.default.statSync(entry).mtimeMs;
|
|
15528
|
+
} catch {
|
|
15529
|
+
}
|
|
15530
|
+
return { version: readOwnVersion(), mtimeMs };
|
|
15531
|
+
}
|
|
15532
|
+
function buildIdString(b) {
|
|
15533
|
+
return `${b.version}+${Math.round(b.mtimeMs)}`;
|
|
15534
|
+
}
|
|
15535
|
+
function parseBuildId(s) {
|
|
15536
|
+
if (typeof s !== "string") return null;
|
|
15537
|
+
const at = s.lastIndexOf("+");
|
|
15538
|
+
if (at <= 0) return null;
|
|
15539
|
+
const version2 = s.slice(0, at);
|
|
15540
|
+
const mtimeMs = Number(s.slice(at + 1));
|
|
15541
|
+
if (!/^\d+(\.\d+){2}/.test(version2) || !Number.isFinite(mtimeMs) || mtimeMs < 0) return null;
|
|
15542
|
+
return { version: version2, mtimeMs };
|
|
15543
|
+
}
|
|
15544
|
+
function compareVersion(a, b) {
|
|
15545
|
+
const pa = a.split(".").map((n) => parseInt(n, 10) || 0);
|
|
15546
|
+
const pb = b.split(".").map((n) => parseInt(n, 10) || 0);
|
|
15547
|
+
for (let i = 0; i < 3; i++) {
|
|
15548
|
+
const d = (pa[i] ?? 0) - (pb[i] ?? 0);
|
|
15549
|
+
if (d !== 0) return d;
|
|
15550
|
+
}
|
|
15551
|
+
return 0;
|
|
15552
|
+
}
|
|
15553
|
+
function compareBuild(a, b) {
|
|
15554
|
+
const v = compareVersion(a.version, b.version);
|
|
15555
|
+
if (v !== 0) return v;
|
|
15556
|
+
return a.mtimeMs - b.mtimeMs;
|
|
15557
|
+
}
|
|
15558
|
+
function describeBuildDrift(running, installed) {
|
|
15559
|
+
const mine = buildIdString(installed);
|
|
15560
|
+
if (running === null) return null;
|
|
15561
|
+
if (running === "no-health") {
|
|
15562
|
+
return `running daemon predates the installed build (no /health \u2014 older than v${installed.version}) \u2014 it is enforcing OLD code`;
|
|
15563
|
+
}
|
|
15564
|
+
const theirs = typeof running.buildId === "string" ? running.buildId : null;
|
|
15565
|
+
if (!theirs || theirs === mine) return null;
|
|
15566
|
+
const theirVersion = typeof running.version === "string" ? running.version : "unknown";
|
|
15567
|
+
return `running daemon is v${theirVersion} (build ${theirs}) but installed is v${installed.version} (build ${mine}) \u2014 it is enforcing a different build`;
|
|
15568
|
+
}
|
|
15569
|
+
var import_fs26, import_path28, CURRENT_BUILD;
|
|
15570
|
+
var init_build_id = __esm({
|
|
15571
|
+
"src/daemon/build-id.ts"() {
|
|
15572
|
+
"use strict";
|
|
15573
|
+
import_fs26 = __toESM(require("fs"));
|
|
15574
|
+
import_path28 = __toESM(require("path"));
|
|
15575
|
+
CURRENT_BUILD = parseBuildId(process.env.NODE9_BUILD_ID_OVERRIDE) ?? computeBuildId();
|
|
15576
|
+
}
|
|
15577
|
+
});
|
|
15578
|
+
|
|
15485
15579
|
// src/daemon/suggestion-tracker.ts
|
|
15486
15580
|
function extractPath(args) {
|
|
15487
15581
|
if (!args || typeof args !== "object") return null;
|
|
@@ -15573,12 +15667,12 @@ var init_suggestion_tracker = __esm({
|
|
|
15573
15667
|
});
|
|
15574
15668
|
|
|
15575
15669
|
// src/daemon/taint-store.ts
|
|
15576
|
-
var
|
|
15670
|
+
var import_fs27, import_path29, DEFAULT_TTL_MS, TaintStore, SESSION_TAINT_TTL_MS, SessionTaintStore;
|
|
15577
15671
|
var init_taint_store = __esm({
|
|
15578
15672
|
"src/daemon/taint-store.ts"() {
|
|
15579
15673
|
"use strict";
|
|
15580
|
-
|
|
15581
|
-
|
|
15674
|
+
import_fs27 = __toESM(require("fs"));
|
|
15675
|
+
import_path29 = __toESM(require("path"));
|
|
15582
15676
|
DEFAULT_TTL_MS = 60 * 60 * 1e3;
|
|
15583
15677
|
TaintStore = class {
|
|
15584
15678
|
records = /* @__PURE__ */ new Map();
|
|
@@ -15644,9 +15738,9 @@ var init_taint_store = __esm({
|
|
|
15644
15738
|
/** Resolve to absolute path, falling back to path.resolve if file doesn't exist yet. */
|
|
15645
15739
|
_resolve(filePath) {
|
|
15646
15740
|
try {
|
|
15647
|
-
return
|
|
15741
|
+
return import_fs27.default.realpathSync.native(import_path29.default.resolve(filePath));
|
|
15648
15742
|
} catch {
|
|
15649
|
-
return
|
|
15743
|
+
return import_path29.default.resolve(filePath);
|
|
15650
15744
|
}
|
|
15651
15745
|
}
|
|
15652
15746
|
};
|
|
@@ -15812,8 +15906,8 @@ var init_session_history = __esm({
|
|
|
15812
15906
|
// src/daemon/state.ts
|
|
15813
15907
|
function loadInsightCounts() {
|
|
15814
15908
|
try {
|
|
15815
|
-
if (!
|
|
15816
|
-
const data = JSON.parse(
|
|
15909
|
+
if (!import_fs28.default.existsSync(INSIGHT_COUNTS_FILE)) return;
|
|
15910
|
+
const data = JSON.parse(import_fs28.default.readFileSync(INSIGHT_COUNTS_FILE, "utf-8"));
|
|
15817
15911
|
for (const [tool, count] of Object.entries(data)) {
|
|
15818
15912
|
if (typeof count === "number" && count > 0) insightCounts.set(tool, count);
|
|
15819
15913
|
}
|
|
@@ -15852,23 +15946,23 @@ function markRejectionHandlerRegistered() {
|
|
|
15852
15946
|
daemonRejectionHandlerRegistered = true;
|
|
15853
15947
|
}
|
|
15854
15948
|
function atomicWriteSync2(filePath, data, options) {
|
|
15855
|
-
const dir =
|
|
15856
|
-
if (!
|
|
15949
|
+
const dir = import_path30.default.dirname(filePath);
|
|
15950
|
+
if (!import_fs28.default.existsSync(dir)) import_fs28.default.mkdirSync(dir, { recursive: true });
|
|
15857
15951
|
const tmpPath = `${filePath}.${(0, import_crypto8.randomUUID)()}.tmp`;
|
|
15858
15952
|
try {
|
|
15859
|
-
|
|
15953
|
+
import_fs28.default.writeFileSync(tmpPath, data, options);
|
|
15860
15954
|
} catch (err2) {
|
|
15861
15955
|
try {
|
|
15862
|
-
|
|
15956
|
+
import_fs28.default.unlinkSync(tmpPath);
|
|
15863
15957
|
} catch {
|
|
15864
15958
|
}
|
|
15865
15959
|
throw err2;
|
|
15866
15960
|
}
|
|
15867
15961
|
try {
|
|
15868
|
-
|
|
15962
|
+
import_fs28.default.renameSync(tmpPath, filePath);
|
|
15869
15963
|
} catch (err2) {
|
|
15870
15964
|
try {
|
|
15871
|
-
|
|
15965
|
+
import_fs28.default.unlinkSync(tmpPath);
|
|
15872
15966
|
} catch {
|
|
15873
15967
|
}
|
|
15874
15968
|
throw err2;
|
|
@@ -15892,16 +15986,16 @@ function appendAuditLog(data) {
|
|
|
15892
15986
|
decision: data.decision,
|
|
15893
15987
|
source: "daemon"
|
|
15894
15988
|
};
|
|
15895
|
-
const dir =
|
|
15896
|
-
if (!
|
|
15897
|
-
|
|
15989
|
+
const dir = import_path30.default.dirname(AUDIT_LOG_FILE);
|
|
15990
|
+
if (!import_fs28.default.existsSync(dir)) import_fs28.default.mkdirSync(dir, { recursive: true });
|
|
15991
|
+
import_fs28.default.appendFileSync(AUDIT_LOG_FILE, JSON.stringify(entry) + "\n");
|
|
15898
15992
|
} catch {
|
|
15899
15993
|
}
|
|
15900
15994
|
}
|
|
15901
15995
|
function getAuditHistory(limit = 20) {
|
|
15902
15996
|
try {
|
|
15903
|
-
if (!
|
|
15904
|
-
const lines =
|
|
15997
|
+
if (!import_fs28.default.existsSync(AUDIT_LOG_FILE)) return [];
|
|
15998
|
+
const lines = import_fs28.default.readFileSync(AUDIT_LOG_FILE, "utf-8").trim().split("\n");
|
|
15905
15999
|
if (lines.length === 1 && lines[0] === "") return [];
|
|
15906
16000
|
return lines.slice(-limit).map((l) => JSON.parse(l)).reverse();
|
|
15907
16001
|
} catch {
|
|
@@ -15910,7 +16004,7 @@ function getAuditHistory(limit = 20) {
|
|
|
15910
16004
|
}
|
|
15911
16005
|
function getOrgName() {
|
|
15912
16006
|
try {
|
|
15913
|
-
if (
|
|
16007
|
+
if (import_fs28.default.existsSync(CREDENTIALS_FILE)) return "Node9 Cloud";
|
|
15914
16008
|
} catch {
|
|
15915
16009
|
}
|
|
15916
16010
|
return null;
|
|
@@ -15918,8 +16012,8 @@ function getOrgName() {
|
|
|
15918
16012
|
function writeGlobalSetting(key, value) {
|
|
15919
16013
|
let config = {};
|
|
15920
16014
|
try {
|
|
15921
|
-
if (
|
|
15922
|
-
config = JSON.parse(
|
|
16015
|
+
if (import_fs28.default.existsSync(GLOBAL_CONFIG_FILE)) {
|
|
16016
|
+
config = JSON.parse(import_fs28.default.readFileSync(GLOBAL_CONFIG_FILE, "utf-8"));
|
|
15923
16017
|
}
|
|
15924
16018
|
} catch {
|
|
15925
16019
|
}
|
|
@@ -15931,8 +16025,8 @@ function writeTrustEntry(toolName, durationMs, commandPattern) {
|
|
|
15931
16025
|
try {
|
|
15932
16026
|
let trust = { entries: [] };
|
|
15933
16027
|
try {
|
|
15934
|
-
if (
|
|
15935
|
-
trust = JSON.parse(
|
|
16028
|
+
if (import_fs28.default.existsSync(TRUST_FILE2))
|
|
16029
|
+
trust = JSON.parse(import_fs28.default.readFileSync(TRUST_FILE2, "utf-8"));
|
|
15936
16030
|
} catch {
|
|
15937
16031
|
}
|
|
15938
16032
|
trust.entries = trust.entries.filter(
|
|
@@ -15949,8 +16043,8 @@ function writeTrustEntry(toolName, durationMs, commandPattern) {
|
|
|
15949
16043
|
}
|
|
15950
16044
|
function readPersistentDecisions() {
|
|
15951
16045
|
try {
|
|
15952
|
-
if (
|
|
15953
|
-
return JSON.parse(
|
|
16046
|
+
if (import_fs28.default.existsSync(DECISIONS_FILE)) {
|
|
16047
|
+
return JSON.parse(import_fs28.default.readFileSync(DECISIONS_FILE, "utf-8"));
|
|
15954
16048
|
}
|
|
15955
16049
|
} catch {
|
|
15956
16050
|
}
|
|
@@ -15978,7 +16072,7 @@ function estimateToolCost(tool, args) {
|
|
|
15978
16072
|
const filePath = a.file_path ?? a.path;
|
|
15979
16073
|
if (filePath) {
|
|
15980
16074
|
try {
|
|
15981
|
-
const bytes =
|
|
16075
|
+
const bytes = import_fs28.default.statSync(filePath).size;
|
|
15982
16076
|
return bytes / BYTES_PER_TOKEN / 1e6 * INPUT_PRICE_PER_1M;
|
|
15983
16077
|
} catch {
|
|
15984
16078
|
}
|
|
@@ -16052,7 +16146,7 @@ function abandonPending() {
|
|
|
16052
16146
|
});
|
|
16053
16147
|
if (autoStarted) {
|
|
16054
16148
|
try {
|
|
16055
|
-
|
|
16149
|
+
import_fs28.default.unlinkSync(DAEMON_PID_FILE);
|
|
16056
16150
|
} catch {
|
|
16057
16151
|
}
|
|
16058
16152
|
setTimeout(() => {
|
|
@@ -16063,8 +16157,8 @@ function abandonPending() {
|
|
|
16063
16157
|
}
|
|
16064
16158
|
function logActivitySocket(msg) {
|
|
16065
16159
|
try {
|
|
16066
|
-
|
|
16067
|
-
|
|
16160
|
+
import_fs28.default.appendFileSync(
|
|
16161
|
+
import_path30.default.join(homeDir, ".node9", "hook-debug.log"),
|
|
16068
16162
|
`[${(/* @__PURE__ */ new Date()).toISOString()}] [activity-socket] ${msg}
|
|
16069
16163
|
`
|
|
16070
16164
|
);
|
|
@@ -16086,13 +16180,13 @@ function shouldRebind(now = Date.now()) {
|
|
|
16086
16180
|
function startActivitySocket() {
|
|
16087
16181
|
bindActivitySocket();
|
|
16088
16182
|
activityHealthInterval = setInterval(() => {
|
|
16089
|
-
if (!
|
|
16183
|
+
if (!import_fs28.default.existsSync(ACTIVITY_SOCKET_PATH2)) attemptRebind("health-probe");
|
|
16090
16184
|
}, ACTIVITY_HEALTH_PROBE_MS);
|
|
16091
16185
|
activityHealthInterval.unref();
|
|
16092
16186
|
process.on("exit", () => {
|
|
16093
16187
|
if (activityHealthInterval) clearInterval(activityHealthInterval);
|
|
16094
16188
|
try {
|
|
16095
|
-
|
|
16189
|
+
import_fs28.default.unlinkSync(ACTIVITY_SOCKET_PATH2);
|
|
16096
16190
|
} catch {
|
|
16097
16191
|
}
|
|
16098
16192
|
});
|
|
@@ -16120,7 +16214,7 @@ function attemptRebind(reason) {
|
|
|
16120
16214
|
}
|
|
16121
16215
|
function bindActivitySocket() {
|
|
16122
16216
|
try {
|
|
16123
|
-
|
|
16217
|
+
import_fs28.default.unlinkSync(ACTIVITY_SOCKET_PATH2);
|
|
16124
16218
|
} catch {
|
|
16125
16219
|
}
|
|
16126
16220
|
const ACTIVITY_MAX_BYTES = 1024 * 1024;
|
|
@@ -16224,13 +16318,13 @@ function bindActivitySocket() {
|
|
|
16224
16318
|
});
|
|
16225
16319
|
activitySocketServer = unixServer;
|
|
16226
16320
|
}
|
|
16227
|
-
var import_net2,
|
|
16321
|
+
var import_net2, import_fs28, import_path30, import_os25, import_crypto8, homeDir, DAEMON_PID_FILE, DECISIONS_FILE, AUDIT_LOG_FILE, TRUST_FILE2, GLOBAL_CONFIG_FILE, CREDENTIALS_FILE, INSIGHT_COUNTS_FILE, pending, sseClients, suggestionTracker, taintStore, sessionTaintStore, insightCounts, _abandonTimer, _hadBrowserClient, _daemonServer, daemonRejectionHandlerRegistered, AUTO_DENY_MS, TRUST_DURATIONS, autoStarted, ACTIVITY_SOCKET_PATH2, ACTIVITY_RING_SIZE, activityRing, LARGE_RESPONSE_RING_SIZE, largeResponseRing, cachedScanResult, cachedScanTs, SCAN_CACHE_TTL_MS, SECRET_KEY_RE, INPUT_PRICE_PER_1M, OUTPUT_PRICE_PER_1M, BYTES_PER_TOKEN, CRITICAL_FORENSIC_CATEGORIES, WRITE_TOOL_NAMES, ACTIVITY_REBIND_MAX_ATTEMPTS, ACTIVITY_REBIND_WINDOW_MS, ACTIVITY_HEALTH_PROBE_MS, activitySocketServer, activityHealthInterval, activityRebindAttempts, activityCircuitTripped;
|
|
16228
16322
|
var init_state2 = __esm({
|
|
16229
16323
|
"src/daemon/state.ts"() {
|
|
16230
16324
|
"use strict";
|
|
16231
16325
|
import_net2 = __toESM(require("net"));
|
|
16232
|
-
|
|
16233
|
-
|
|
16326
|
+
import_fs28 = __toESM(require("fs"));
|
|
16327
|
+
import_path30 = __toESM(require("path"));
|
|
16234
16328
|
import_os25 = __toESM(require("os"));
|
|
16235
16329
|
import_crypto8 = require("crypto");
|
|
16236
16330
|
init_daemon();
|
|
@@ -16239,13 +16333,13 @@ var init_state2 = __esm({
|
|
|
16239
16333
|
init_session_counters();
|
|
16240
16334
|
init_session_history();
|
|
16241
16335
|
homeDir = import_os25.default.homedir();
|
|
16242
|
-
DAEMON_PID_FILE =
|
|
16243
|
-
DECISIONS_FILE =
|
|
16244
|
-
AUDIT_LOG_FILE =
|
|
16245
|
-
TRUST_FILE2 =
|
|
16246
|
-
GLOBAL_CONFIG_FILE =
|
|
16247
|
-
CREDENTIALS_FILE =
|
|
16248
|
-
INSIGHT_COUNTS_FILE =
|
|
16336
|
+
DAEMON_PID_FILE = import_path30.default.join(homeDir, ".node9", "daemon.pid");
|
|
16337
|
+
DECISIONS_FILE = import_path30.default.join(homeDir, ".node9", "decisions.json");
|
|
16338
|
+
AUDIT_LOG_FILE = import_path30.default.join(homeDir, ".node9", "audit.log");
|
|
16339
|
+
TRUST_FILE2 = import_path30.default.join(homeDir, ".node9", "trust.json");
|
|
16340
|
+
GLOBAL_CONFIG_FILE = import_path30.default.join(homeDir, ".node9", "config.json");
|
|
16341
|
+
CREDENTIALS_FILE = import_path30.default.join(homeDir, ".node9", "credentials.json");
|
|
16342
|
+
INSIGHT_COUNTS_FILE = import_path30.default.join(homeDir, ".node9", "insight-counts.json");
|
|
16249
16343
|
pending = /* @__PURE__ */ new Map();
|
|
16250
16344
|
sseClients = /* @__PURE__ */ new Set();
|
|
16251
16345
|
suggestionTracker = new SuggestionTracker(3);
|
|
@@ -16263,7 +16357,7 @@ var init_state2 = __esm({
|
|
|
16263
16357
|
"2h": 2 * 60 * 6e4
|
|
16264
16358
|
};
|
|
16265
16359
|
autoStarted = process.env.NODE9_AUTO_STARTED === "1";
|
|
16266
|
-
ACTIVITY_SOCKET_PATH2 = process.platform === "win32" ? "\\\\.\\pipe\\node9-activity" :
|
|
16360
|
+
ACTIVITY_SOCKET_PATH2 = process.platform === "win32" ? "\\\\.\\pipe\\node9-activity" : import_path30.default.join(import_os25.default.tmpdir(), "node9-activity.sock");
|
|
16267
16361
|
ACTIVITY_RING_SIZE = 100;
|
|
16268
16362
|
activityRing = [];
|
|
16269
16363
|
LARGE_RESPONSE_RING_SIZE = 20;
|
|
@@ -16304,15 +16398,15 @@ var init_state2 = __esm({
|
|
|
16304
16398
|
// src/posture/secrets.ts
|
|
16305
16399
|
function displayPath(p, home) {
|
|
16306
16400
|
if (p === home) return "~";
|
|
16307
|
-
const prefix = home.endsWith(
|
|
16308
|
-
if (p.startsWith(prefix)) return "~" +
|
|
16401
|
+
const prefix = home.endsWith(import_path31.default.sep) ? home : home + import_path31.default.sep;
|
|
16402
|
+
if (p.startsWith(prefix)) return "~" + import_path31.default.sep + p.slice(prefix.length);
|
|
16309
16403
|
return p;
|
|
16310
16404
|
}
|
|
16311
16405
|
function safeRead(file) {
|
|
16312
16406
|
try {
|
|
16313
|
-
const stat =
|
|
16407
|
+
const stat = import_fs29.default.statSync(file);
|
|
16314
16408
|
if (!stat.isFile() || stat.size === 0 || stat.size > MAX_FILE_BYTES) return null;
|
|
16315
|
-
return
|
|
16409
|
+
return import_fs29.default.readFileSync(file, "utf8");
|
|
16316
16410
|
} catch {
|
|
16317
16411
|
return null;
|
|
16318
16412
|
}
|
|
@@ -16320,8 +16414,8 @@ function safeRead(file) {
|
|
|
16320
16414
|
function candidateFiles(home, cwd) {
|
|
16321
16415
|
const files = /* @__PURE__ */ new Set();
|
|
16322
16416
|
try {
|
|
16323
|
-
for (const name of
|
|
16324
|
-
if (name === ".env" || name.startsWith(".env.")) files.add(
|
|
16417
|
+
for (const name of import_fs29.default.readdirSync(cwd)) {
|
|
16418
|
+
if (name === ".env" || name.startsWith(".env.")) files.add(import_path31.default.join(cwd, name));
|
|
16325
16419
|
}
|
|
16326
16420
|
} catch {
|
|
16327
16421
|
}
|
|
@@ -16329,17 +16423,17 @@ function candidateFiles(home, cwd) {
|
|
|
16329
16423
|
if (spec.hookFile) files.add(spec.hookFile(home));
|
|
16330
16424
|
if (spec.mcpFile) files.add(spec.mcpFile(home));
|
|
16331
16425
|
}
|
|
16332
|
-
files.add(
|
|
16426
|
+
files.add(import_path31.default.join(home, ".env"));
|
|
16333
16427
|
return [...files];
|
|
16334
16428
|
}
|
|
16335
16429
|
function credentialMaterial(home) {
|
|
16336
16430
|
return [
|
|
16337
|
-
|
|
16338
|
-
|
|
16339
|
-
|
|
16340
|
-
|
|
16341
|
-
|
|
16342
|
-
|
|
16431
|
+
import_path31.default.join(home, ".ssh", "id_rsa"),
|
|
16432
|
+
import_path31.default.join(home, ".ssh", "id_dsa"),
|
|
16433
|
+
import_path31.default.join(home, ".ssh", "id_ecdsa"),
|
|
16434
|
+
import_path31.default.join(home, ".ssh", "id_ed25519"),
|
|
16435
|
+
import_path31.default.join(home, ".aws", "credentials"),
|
|
16436
|
+
import_path31.default.join(home, ".config", "gcloud", "application_default_credentials.json")
|
|
16343
16437
|
];
|
|
16344
16438
|
}
|
|
16345
16439
|
function checkSecrets(ctx) {
|
|
@@ -16376,7 +16470,7 @@ function checkSecrets(ctx) {
|
|
|
16376
16470
|
const credPaths = [];
|
|
16377
16471
|
for (const file of credentialMaterial(home)) {
|
|
16378
16472
|
try {
|
|
16379
|
-
if (
|
|
16473
|
+
if (import_fs29.default.statSync(file).isFile()) {
|
|
16380
16474
|
creds.push(displayPath(file, home));
|
|
16381
16475
|
credPaths.push(file);
|
|
16382
16476
|
}
|
|
@@ -16399,12 +16493,12 @@ function checkSecrets(ctx) {
|
|
|
16399
16493
|
}
|
|
16400
16494
|
return findings;
|
|
16401
16495
|
}
|
|
16402
|
-
var
|
|
16496
|
+
var import_fs29, import_path31, import_os26, MAX_FILE_BYTES;
|
|
16403
16497
|
var init_secrets = __esm({
|
|
16404
16498
|
"src/posture/secrets.ts"() {
|
|
16405
16499
|
"use strict";
|
|
16406
|
-
|
|
16407
|
-
|
|
16500
|
+
import_fs29 = __toESM(require("fs"));
|
|
16501
|
+
import_path31 = __toESM(require("path"));
|
|
16408
16502
|
import_os26 = __toESM(require("os"));
|
|
16409
16503
|
init_dist();
|
|
16410
16504
|
init_agent_wiring();
|
|
@@ -16537,7 +16631,7 @@ var init_templates = __esm({
|
|
|
16537
16631
|
// src/posture/egress.ts
|
|
16538
16632
|
function sandboxEgressWallActive() {
|
|
16539
16633
|
try {
|
|
16540
|
-
return
|
|
16634
|
+
return import_fs30.default.existsSync(ALLOWED_DOMAINS_PATH);
|
|
16541
16635
|
} catch {
|
|
16542
16636
|
return false;
|
|
16543
16637
|
}
|
|
@@ -16610,11 +16704,11 @@ function checkEgress(ctx) {
|
|
|
16610
16704
|
const egress = config.policy.egress;
|
|
16611
16705
|
return [evaluateEgressConfig({ enabled: egress.enabled, mode: egress.mode })];
|
|
16612
16706
|
}
|
|
16613
|
-
var
|
|
16707
|
+
var import_fs30;
|
|
16614
16708
|
var init_egress = __esm({
|
|
16615
16709
|
"src/posture/egress.ts"() {
|
|
16616
16710
|
"use strict";
|
|
16617
|
-
|
|
16711
|
+
import_fs30 = __toESM(require("fs"));
|
|
16618
16712
|
init_config();
|
|
16619
16713
|
init_templates();
|
|
16620
16714
|
}
|
|
@@ -16663,17 +16757,17 @@ var init_gate = __esm({
|
|
|
16663
16757
|
// src/posture/supply-chain.ts
|
|
16664
16758
|
function isNode9Managed(command, args = []) {
|
|
16665
16759
|
if (!command) return false;
|
|
16666
|
-
if (
|
|
16667
|
-
if (PACKAGE_RUNNERS.has(
|
|
16668
|
-
return args.some((a) => a === "node9" ||
|
|
16760
|
+
if (import_path32.default.basename(command).toLowerCase() === "node9") return true;
|
|
16761
|
+
if (PACKAGE_RUNNERS.has(import_path32.default.basename(command).toLowerCase())) {
|
|
16762
|
+
return args.some((a) => a === "node9" || import_path32.default.basename(a).toLowerCase() === "node9");
|
|
16669
16763
|
}
|
|
16670
16764
|
return false;
|
|
16671
16765
|
}
|
|
16672
16766
|
function readServers(file, format, agent) {
|
|
16673
16767
|
try {
|
|
16674
|
-
const stat =
|
|
16768
|
+
const stat = import_fs31.default.statSync(file);
|
|
16675
16769
|
if (!stat.isFile() || stat.size > MAX_CONFIG_BYTES) return [];
|
|
16676
|
-
const text =
|
|
16770
|
+
const text = import_fs31.default.readFileSync(file, "utf8");
|
|
16677
16771
|
const map = format === "toml" ? (0, import_smol_toml3.parse)(text)?.mcp_servers : JSON.parse(text)?.mcpServers;
|
|
16678
16772
|
if (!map || typeof map !== "object") return [];
|
|
16679
16773
|
return Object.entries(map).map(([name, v]) => ({
|
|
@@ -16727,13 +16821,13 @@ function checkSupplyChain(ctx) {
|
|
|
16727
16821
|
}
|
|
16728
16822
|
return findings;
|
|
16729
16823
|
}
|
|
16730
|
-
var
|
|
16824
|
+
var import_fs31, import_os27, import_path32, import_smol_toml3, PACKAGE_RUNNERS, MAX_CONFIG_BYTES;
|
|
16731
16825
|
var init_supply_chain = __esm({
|
|
16732
16826
|
"src/posture/supply-chain.ts"() {
|
|
16733
16827
|
"use strict";
|
|
16734
|
-
|
|
16828
|
+
import_fs31 = __toESM(require("fs"));
|
|
16735
16829
|
import_os27 = __toESM(require("os"));
|
|
16736
|
-
|
|
16830
|
+
import_path32 = __toESM(require("path"));
|
|
16737
16831
|
import_smol_toml3 = require("smol-toml");
|
|
16738
16832
|
init_provenance();
|
|
16739
16833
|
init_agent_wiring();
|
|
@@ -16790,9 +16884,9 @@ var init_privilege = __esm({
|
|
|
16790
16884
|
|
|
16791
16885
|
// src/posture/containment.ts
|
|
16792
16886
|
function inContainer() {
|
|
16793
|
-
if (
|
|
16887
|
+
if (import_fs32.default.existsSync("/.dockerenv") || import_fs32.default.existsSync("/run/.containerenv")) return true;
|
|
16794
16888
|
try {
|
|
16795
|
-
const cgroup =
|
|
16889
|
+
const cgroup = import_fs32.default.readFileSync("/proc/1/cgroup", "utf8");
|
|
16796
16890
|
if (/docker|kubepods|containerd|lxc|libpod/.test(cgroup)) return true;
|
|
16797
16891
|
} catch {
|
|
16798
16892
|
}
|
|
@@ -16829,11 +16923,11 @@ Lighter \u2014 harden in place, keep full host access (about +${Math.round(
|
|
|
16829
16923
|
}
|
|
16830
16924
|
];
|
|
16831
16925
|
}
|
|
16832
|
-
var
|
|
16926
|
+
var import_fs32, ISOLATION_WEIGHT;
|
|
16833
16927
|
var init_containment = __esm({
|
|
16834
16928
|
"src/posture/containment.ts"() {
|
|
16835
16929
|
"use strict";
|
|
16836
|
-
|
|
16930
|
+
import_fs32 = __toESM(require("fs"));
|
|
16837
16931
|
ISOLATION_WEIGHT = 12;
|
|
16838
16932
|
}
|
|
16839
16933
|
});
|
|
@@ -16896,7 +16990,7 @@ function collectListeners() {
|
|
|
16896
16990
|
const byPort = /* @__PURE__ */ new Map();
|
|
16897
16991
|
for (const file of ["/proc/net/tcp", "/proc/net/tcp6"]) {
|
|
16898
16992
|
try {
|
|
16899
|
-
for (const l of parseListeners(
|
|
16993
|
+
for (const l of parseListeners(import_fs33.default.readFileSync(file, "utf8"))) {
|
|
16900
16994
|
if (!byPort.has(l.port)) byPort.set(l.port, l);
|
|
16901
16995
|
}
|
|
16902
16996
|
} catch {
|
|
@@ -16908,11 +17002,11 @@ function readProc(pid) {
|
|
|
16908
17002
|
let comm = "unknown";
|
|
16909
17003
|
let cmdline = "";
|
|
16910
17004
|
try {
|
|
16911
|
-
comm =
|
|
17005
|
+
comm = import_fs33.default.readFileSync(`/proc/${pid}/comm`, "utf8").trim().replace(/-MainThread$/, "") || "unknown";
|
|
16912
17006
|
} catch {
|
|
16913
17007
|
}
|
|
16914
17008
|
try {
|
|
16915
|
-
cmdline =
|
|
17009
|
+
cmdline = import_fs33.default.readFileSync(`/proc/${pid}/cmdline`).toString().replace(/\0/g, " ").trim();
|
|
16916
17010
|
} catch {
|
|
16917
17011
|
}
|
|
16918
17012
|
return { comm, cmdline };
|
|
@@ -16922,21 +17016,21 @@ function resolveProcesses(inodes) {
|
|
|
16922
17016
|
if (inodes.size === 0) return map;
|
|
16923
17017
|
let pids;
|
|
16924
17018
|
try {
|
|
16925
|
-
pids =
|
|
17019
|
+
pids = import_fs33.default.readdirSync("/proc").filter((d) => /^\d+$/.test(d));
|
|
16926
17020
|
} catch {
|
|
16927
17021
|
return map;
|
|
16928
17022
|
}
|
|
16929
17023
|
for (const pid of pids) {
|
|
16930
17024
|
let fds;
|
|
16931
17025
|
try {
|
|
16932
|
-
fds =
|
|
17026
|
+
fds = import_fs33.default.readdirSync(`/proc/${pid}/fd`);
|
|
16933
17027
|
} catch {
|
|
16934
17028
|
continue;
|
|
16935
17029
|
}
|
|
16936
17030
|
for (const fd of fds) {
|
|
16937
17031
|
let link;
|
|
16938
17032
|
try {
|
|
16939
|
-
link =
|
|
17033
|
+
link = import_fs33.default.readlinkSync(`/proc/${pid}/fd/${fd}`);
|
|
16940
17034
|
} catch {
|
|
16941
17035
|
continue;
|
|
16942
17036
|
}
|
|
@@ -17004,11 +17098,11 @@ function checkInbound(ctx) {
|
|
|
17004
17098
|
}
|
|
17005
17099
|
return findings;
|
|
17006
17100
|
}
|
|
17007
|
-
var
|
|
17101
|
+
var import_fs33, DB_EXPOSURE_WEIGHT, KNOWN_SERVICE_PORTS, KNOWN_SERVICE_COMMS, DB_LABEL, SHIELD_FOR_SERVICE;
|
|
17008
17102
|
var init_inbound = __esm({
|
|
17009
17103
|
"src/posture/inbound.ts"() {
|
|
17010
17104
|
"use strict";
|
|
17011
|
-
|
|
17105
|
+
import_fs33 = __toESM(require("fs"));
|
|
17012
17106
|
DB_EXPOSURE_WEIGHT = 4;
|
|
17013
17107
|
KNOWN_SERVICE_PORTS = {
|
|
17014
17108
|
5432: "PostgreSQL",
|
|
@@ -17226,13 +17320,13 @@ function checkCost(_ctx) {
|
|
|
17226
17320
|
}
|
|
17227
17321
|
];
|
|
17228
17322
|
}
|
|
17229
|
-
var
|
|
17323
|
+
var import_path33, jailProbePath;
|
|
17230
17324
|
var init_governance = __esm({
|
|
17231
17325
|
"src/posture/governance.ts"() {
|
|
17232
17326
|
"use strict";
|
|
17233
|
-
|
|
17327
|
+
import_path33 = __toESM(require("path"));
|
|
17234
17328
|
init_config();
|
|
17235
|
-
jailProbePath = (home) =>
|
|
17329
|
+
jailProbePath = (home) => import_path33.default.join(home, ".aws", "credentials");
|
|
17236
17330
|
}
|
|
17237
17331
|
});
|
|
17238
17332
|
|
|
@@ -17725,13 +17819,13 @@ function deriveServerName(cmd) {
|
|
|
17725
17819
|
return strip(base) || "MCP Server";
|
|
17726
17820
|
}
|
|
17727
17821
|
function getMcpToolsFile() {
|
|
17728
|
-
return
|
|
17822
|
+
return import_path34.default.join(import_os30.default.homedir(), ".node9", "mcp-tools.json");
|
|
17729
17823
|
}
|
|
17730
17824
|
function readMcpToolsConfig() {
|
|
17731
17825
|
try {
|
|
17732
17826
|
const file = getMcpToolsFile();
|
|
17733
|
-
if (!
|
|
17734
|
-
const raw =
|
|
17827
|
+
if (!import_fs34.default.existsSync(file)) return {};
|
|
17828
|
+
const raw = import_fs34.default.readFileSync(file, "utf-8");
|
|
17735
17829
|
return JSON.parse(raw);
|
|
17736
17830
|
} catch {
|
|
17737
17831
|
return {};
|
|
@@ -17740,11 +17834,11 @@ function readMcpToolsConfig() {
|
|
|
17740
17834
|
function writeMcpToolsConfig(config) {
|
|
17741
17835
|
try {
|
|
17742
17836
|
const file = getMcpToolsFile();
|
|
17743
|
-
const dir =
|
|
17744
|
-
if (!
|
|
17837
|
+
const dir = import_path34.default.dirname(file);
|
|
17838
|
+
if (!import_fs34.default.existsSync(dir)) import_fs34.default.mkdirSync(dir, { recursive: true });
|
|
17745
17839
|
const tmpPath = `${file}.${import_os30.default.hostname()}.${process.pid}.tmp`;
|
|
17746
|
-
|
|
17747
|
-
|
|
17840
|
+
import_fs34.default.writeFileSync(tmpPath, JSON.stringify(config, null, 2));
|
|
17841
|
+
import_fs34.default.renameSync(tmpPath, file);
|
|
17748
17842
|
} catch (e) {
|
|
17749
17843
|
console.error("Failed to write mcp-tools.json", e);
|
|
17750
17844
|
}
|
|
@@ -17791,12 +17885,12 @@ function approveServer(serverKey, disabledTools) {
|
|
|
17791
17885
|
writeMcpToolsConfig(config);
|
|
17792
17886
|
}
|
|
17793
17887
|
}
|
|
17794
|
-
var
|
|
17888
|
+
var import_fs34, import_path34, import_os30;
|
|
17795
17889
|
var init_mcp_tools = __esm({
|
|
17796
17890
|
"src/daemon/mcp-tools.ts"() {
|
|
17797
17891
|
"use strict";
|
|
17798
|
-
|
|
17799
|
-
|
|
17892
|
+
import_fs34 = __toESM(require("fs"));
|
|
17893
|
+
import_path34 = __toESM(require("path"));
|
|
17800
17894
|
import_os30 = __toESM(require("os"));
|
|
17801
17895
|
init_mcp_cmd();
|
|
17802
17896
|
}
|
|
@@ -17873,11 +17967,11 @@ function inventoryServerKeys(inv) {
|
|
|
17873
17967
|
function writeMcpEntry(mcpFile, format, name, entry) {
|
|
17874
17968
|
const key = format === "toml" ? "mcp_servers" : "mcpServers";
|
|
17875
17969
|
let root = {};
|
|
17876
|
-
if (
|
|
17877
|
-
const raw =
|
|
17970
|
+
if (import_fs35.default.existsSync(mcpFile)) {
|
|
17971
|
+
const raw = import_fs35.default.readFileSync(mcpFile, "utf-8");
|
|
17878
17972
|
root = format === "toml" ? (0, import_smol_toml4.parse)(raw) : JSON.parse(raw);
|
|
17879
17973
|
const bak = `${mcpFile}.node9-bak`;
|
|
17880
|
-
if (!
|
|
17974
|
+
if (!import_fs35.default.existsSync(bak)) import_fs35.default.writeFileSync(bak, raw, { mode: 384 });
|
|
17881
17975
|
}
|
|
17882
17976
|
const existing = root[key];
|
|
17883
17977
|
const servers = existing && typeof existing === "object" && !Array.isArray(existing) ? existing : {};
|
|
@@ -17885,14 +17979,14 @@ function writeMcpEntry(mcpFile, format, name, entry) {
|
|
|
17885
17979
|
root[key] = servers;
|
|
17886
17980
|
const serialized = format === "toml" ? (0, import_smol_toml4.stringify)(root) : JSON.stringify(root, null, 2);
|
|
17887
17981
|
const tmp = `${mcpFile}.${process.pid}.tmp`;
|
|
17888
|
-
|
|
17889
|
-
|
|
17982
|
+
import_fs35.default.writeFileSync(tmp, serialized, { mode: 384 });
|
|
17983
|
+
import_fs35.default.renameSync(tmp, mcpFile);
|
|
17890
17984
|
}
|
|
17891
|
-
var
|
|
17985
|
+
var import_fs35, import_os31, import_smol_toml4;
|
|
17892
17986
|
var init_mcp_wrap = __esm({
|
|
17893
17987
|
"src/mcp-wrap.ts"() {
|
|
17894
17988
|
"use strict";
|
|
17895
|
-
|
|
17989
|
+
import_fs35 = __toESM(require("fs"));
|
|
17896
17990
|
import_os31 = __toESM(require("os"));
|
|
17897
17991
|
import_smol_toml4 = require("smol-toml");
|
|
17898
17992
|
init_agent_wiring();
|
|
@@ -18062,8 +18156,8 @@ function readCredentials() {
|
|
|
18062
18156
|
};
|
|
18063
18157
|
}
|
|
18064
18158
|
try {
|
|
18065
|
-
const credPath =
|
|
18066
|
-
const creds = JSON.parse(
|
|
18159
|
+
const credPath = import_path35.default.join(import_os32.default.homedir(), ".node9", "credentials.json");
|
|
18160
|
+
const creds = JSON.parse(import_fs36.default.readFileSync(credPath, "utf-8"));
|
|
18067
18161
|
const profileName = process.env.NODE9_PROFILE ?? "default";
|
|
18068
18162
|
const profile = creds[profileName];
|
|
18069
18163
|
if (typeof profile?.apiKey === "string" && profile.apiKey.length > 0) {
|
|
@@ -18089,7 +18183,7 @@ function readCredentials() {
|
|
|
18089
18183
|
}
|
|
18090
18184
|
function readCachedEtag() {
|
|
18091
18185
|
try {
|
|
18092
|
-
const raw = JSON.parse(
|
|
18186
|
+
const raw = JSON.parse(import_fs36.default.readFileSync(rulesCacheFile(), "utf-8"));
|
|
18093
18187
|
return typeof raw.etag === "string" ? raw.etag : void 0;
|
|
18094
18188
|
} catch {
|
|
18095
18189
|
return void 0;
|
|
@@ -18097,7 +18191,7 @@ function readCachedEtag() {
|
|
|
18097
18191
|
}
|
|
18098
18192
|
function readCachedSyncIntervalHours() {
|
|
18099
18193
|
try {
|
|
18100
|
-
const raw = JSON.parse(
|
|
18194
|
+
const raw = JSON.parse(import_fs36.default.readFileSync(rulesCacheFile(), "utf-8"));
|
|
18101
18195
|
return typeof raw.syncIntervalHours === "number" ? raw.syncIntervalHours : void 0;
|
|
18102
18196
|
} catch {
|
|
18103
18197
|
return void 0;
|
|
@@ -18114,7 +18208,7 @@ function effectiveSyncIntervalMs() {
|
|
|
18114
18208
|
}
|
|
18115
18209
|
function readSyncHealth() {
|
|
18116
18210
|
try {
|
|
18117
|
-
const raw = JSON.parse(
|
|
18211
|
+
const raw = JSON.parse(import_fs36.default.readFileSync(syncHealthFile(), "utf-8"));
|
|
18118
18212
|
return {
|
|
18119
18213
|
lastCheckedAt: typeof raw.lastCheckedAt === "string" ? raw.lastCheckedAt : void 0,
|
|
18120
18214
|
lastChangedAt: typeof raw.lastChangedAt === "string" ? raw.lastChangedAt : void 0,
|
|
@@ -18129,17 +18223,17 @@ function readSyncHealth() {
|
|
|
18129
18223
|
function writeSyncHealth(h) {
|
|
18130
18224
|
try {
|
|
18131
18225
|
const file = syncHealthFile();
|
|
18132
|
-
const dir =
|
|
18133
|
-
if (!
|
|
18226
|
+
const dir = import_path35.default.dirname(file);
|
|
18227
|
+
if (!import_fs36.default.existsSync(dir)) import_fs36.default.mkdirSync(dir, { recursive: true });
|
|
18134
18228
|
const tmp = `${file}.${process.pid}.tmp`;
|
|
18135
|
-
|
|
18136
|
-
|
|
18229
|
+
import_fs36.default.writeFileSync(tmp, JSON.stringify(h, null, 2) + "\n", "utf-8");
|
|
18230
|
+
import_fs36.default.renameSync(tmp, file);
|
|
18137
18231
|
} catch {
|
|
18138
18232
|
}
|
|
18139
18233
|
}
|
|
18140
18234
|
function readCacheFetchedAt() {
|
|
18141
18235
|
try {
|
|
18142
|
-
const raw = JSON.parse(
|
|
18236
|
+
const raw = JSON.parse(import_fs36.default.readFileSync(rulesCacheFile(), "utf-8"));
|
|
18143
18237
|
return typeof raw.fetchedAt === "string" ? raw.fetchedAt : void 0;
|
|
18144
18238
|
} catch {
|
|
18145
18239
|
return void 0;
|
|
@@ -18325,8 +18419,24 @@ function extractManagedConfig(body) {
|
|
|
18325
18419
|
}
|
|
18326
18420
|
return out.mode !== void 0 || out.egress !== void 0 || out.dlp !== void 0 || out.approvers !== void 0 || out.reviewChannel !== void 0 || out.approvalTimeoutMs !== void 0 || out.injectionScan !== void 0 || out.loopDetection !== void 0 || out.skillPinning !== void 0 || out.jailPaths !== void 0 || out.trustedHosts !== void 0 || out.appPermissions !== void 0 ? out : void 0;
|
|
18327
18421
|
}
|
|
18422
|
+
function sweepStaleTmp(target) {
|
|
18423
|
+
try {
|
|
18424
|
+
const dir = import_path35.default.dirname(target);
|
|
18425
|
+
const prefix = `${import_path35.default.basename(target)}.`;
|
|
18426
|
+
for (const name of import_fs36.default.readdirSync(dir)) {
|
|
18427
|
+
if (!name.startsWith(prefix) || !name.endsWith(".tmp")) continue;
|
|
18428
|
+
const full = import_path35.default.join(dir, name);
|
|
18429
|
+
try {
|
|
18430
|
+
if (Date.now() - import_fs36.default.statSync(full).mtimeMs > 5 * 60 * 1e3) import_fs36.default.unlinkSync(full);
|
|
18431
|
+
} catch {
|
|
18432
|
+
}
|
|
18433
|
+
}
|
|
18434
|
+
} catch {
|
|
18435
|
+
}
|
|
18436
|
+
}
|
|
18328
18437
|
function writeCache2(cache) {
|
|
18329
18438
|
const data = JSON.stringify(cache, null, 2) + "\n";
|
|
18439
|
+
sweepStaleTmp(rulesCacheFile());
|
|
18330
18440
|
atomicWriteSync2(rulesCacheFile(), data, "utf-8");
|
|
18331
18441
|
try {
|
|
18332
18442
|
atomicWriteSync2(rulesCacheBackupFile(), data, "utf-8");
|
|
@@ -18573,7 +18683,7 @@ async function runCloudSync() {
|
|
|
18573
18683
|
}
|
|
18574
18684
|
function getCloudSyncStatus() {
|
|
18575
18685
|
try {
|
|
18576
|
-
const raw = JSON.parse(
|
|
18686
|
+
const raw = JSON.parse(import_fs36.default.readFileSync(rulesCacheFile(), "utf-8"));
|
|
18577
18687
|
if (!Array.isArray(raw.rules) || typeof raw.fetchedAt !== "string") return { cached: false };
|
|
18578
18688
|
return {
|
|
18579
18689
|
cached: true,
|
|
@@ -18590,7 +18700,7 @@ function getCloudSyncStatus() {
|
|
|
18590
18700
|
}
|
|
18591
18701
|
function getCloudRules() {
|
|
18592
18702
|
try {
|
|
18593
|
-
const raw = JSON.parse(
|
|
18703
|
+
const raw = JSON.parse(import_fs36.default.readFileSync(rulesCacheFile(), "utf-8"));
|
|
18594
18704
|
return Array.isArray(raw.rules) ? raw.rules : null;
|
|
18595
18705
|
} catch {
|
|
18596
18706
|
return null;
|
|
@@ -18625,14 +18735,14 @@ function startForensicBroadcast() {
|
|
|
18625
18735
|
const recurring = setInterval(() => void tick(), FORENSIC_BROADCAST_INTERVAL_MS);
|
|
18626
18736
|
recurring.unref();
|
|
18627
18737
|
}
|
|
18628
|
-
var
|
|
18738
|
+
var import_fs36, import_https4, import_os32, import_path35, FINDING_TO_SIGNAL3, rulesCacheFile, rulesCacheBackupFile, DEFAULT_API_URL2, DEFAULT_INTERVAL_HOURS, MIN_INTERVAL_SECONDS, MAX_INTERVAL_SECONDS, syncHealthFile, STALE_MIN_MS, STALE_MAX_MS, STALE_FACTOR, FORENSIC_BROADCAST_INTERVAL_MS, FORENSIC_INITIAL_DELAY_MS, forensicBroadcastOffsets;
|
|
18629
18739
|
var init_sync = __esm({
|
|
18630
18740
|
"src/daemon/sync.ts"() {
|
|
18631
18741
|
"use strict";
|
|
18632
|
-
|
|
18742
|
+
import_fs36 = __toESM(require("fs"));
|
|
18633
18743
|
import_https4 = __toESM(require("https"));
|
|
18634
18744
|
import_os32 = __toESM(require("os"));
|
|
18635
|
-
|
|
18745
|
+
import_path35 = __toESM(require("path"));
|
|
18636
18746
|
init_config();
|
|
18637
18747
|
init_blast();
|
|
18638
18748
|
init_posture();
|
|
@@ -18659,13 +18769,13 @@ var init_sync = __esm({
|
|
|
18659
18769
|
loop: "loops",
|
|
18660
18770
|
"long-output-redacted": "longOutputRedactions"
|
|
18661
18771
|
};
|
|
18662
|
-
rulesCacheFile = () =>
|
|
18663
|
-
rulesCacheBackupFile = () =>
|
|
18772
|
+
rulesCacheFile = () => import_path35.default.join(import_os32.default.homedir(), ".node9", "rules-cache.json");
|
|
18773
|
+
rulesCacheBackupFile = () => import_path35.default.join(import_os32.default.homedir(), ".node9", "rules-cache.last-good.json");
|
|
18664
18774
|
DEFAULT_API_URL2 = "https://api.node9.ai/api/v1/intercept/policies/sync";
|
|
18665
18775
|
DEFAULT_INTERVAL_HOURS = 5;
|
|
18666
18776
|
MIN_INTERVAL_SECONDS = 15;
|
|
18667
18777
|
MAX_INTERVAL_SECONDS = 24 * 60 * 60;
|
|
18668
|
-
syncHealthFile = () =>
|
|
18778
|
+
syncHealthFile = () => import_path35.default.join(import_os32.default.homedir(), ".node9", "sync-health.json");
|
|
18669
18779
|
STALE_MIN_MS = 3 * 60 * 60 * 1e3;
|
|
18670
18780
|
STALE_MAX_MS = 24 * 60 * 60 * 1e3;
|
|
18671
18781
|
STALE_FACTOR = 3;
|
|
@@ -18689,21 +18799,21 @@ __export(audit_shipper_exports, {
|
|
|
18689
18799
|
writeWatermark: () => writeWatermark
|
|
18690
18800
|
});
|
|
18691
18801
|
function fileSignature(filePath) {
|
|
18692
|
-
const fd =
|
|
18802
|
+
const fd = import_fs37.default.openSync(filePath, "r");
|
|
18693
18803
|
try {
|
|
18694
18804
|
const buf = Buffer.alloc(512);
|
|
18695
|
-
const read2 =
|
|
18805
|
+
const read2 = import_fs37.default.readSync(fd, buf, 0, 512, 0);
|
|
18696
18806
|
const slice = buf.subarray(0, read2);
|
|
18697
18807
|
const nl = slice.indexOf(10);
|
|
18698
18808
|
const firstLine = nl === -1 ? slice : slice.subarray(0, nl);
|
|
18699
18809
|
return import_crypto9.default.createHash("sha256").update(firstLine).digest("hex").slice(0, 16);
|
|
18700
18810
|
} finally {
|
|
18701
|
-
|
|
18811
|
+
import_fs37.default.closeSync(fd);
|
|
18702
18812
|
}
|
|
18703
18813
|
}
|
|
18704
18814
|
function readWatermark(watermarkPath) {
|
|
18705
18815
|
try {
|
|
18706
|
-
const raw = JSON.parse(
|
|
18816
|
+
const raw = JSON.parse(import_fs37.default.readFileSync(watermarkPath, "utf-8"));
|
|
18707
18817
|
if (typeof raw.fileSig === "string" && typeof raw.offset === "number" && raw.offset >= 0)
|
|
18708
18818
|
return raw;
|
|
18709
18819
|
} catch {
|
|
@@ -18712,8 +18822,8 @@ function readWatermark(watermarkPath) {
|
|
|
18712
18822
|
}
|
|
18713
18823
|
function writeWatermark(watermarkPath, wm) {
|
|
18714
18824
|
const tmp = `${watermarkPath}.tmp`;
|
|
18715
|
-
|
|
18716
|
-
|
|
18825
|
+
import_fs37.default.writeFileSync(tmp, JSON.stringify(wm));
|
|
18826
|
+
import_fs37.default.renameSync(tmp, watermarkPath);
|
|
18717
18827
|
}
|
|
18718
18828
|
function buildWireRows(chunk2) {
|
|
18719
18829
|
const lastNl = chunk2.lastIndexOf(10);
|
|
@@ -18791,11 +18901,11 @@ async function shipOnce(deps = {}) {
|
|
|
18791
18901
|
if (!creds?.apiKey) return { status: "no-creds", shipped: 0 };
|
|
18792
18902
|
const endpoint = buildBatchEndpoint(creds.apiUrl);
|
|
18793
18903
|
if (!endpoint) return { status: "no-creds", shipped: 0 };
|
|
18794
|
-
if (!
|
|
18904
|
+
if (!import_fs37.default.existsSync(auditLogPath)) return { status: "idle", shipped: 0 };
|
|
18795
18905
|
let shipped = 0;
|
|
18796
18906
|
try {
|
|
18797
18907
|
for (let chunkN = 0; chunkN < MAX_CHUNKS_PER_TICK; chunkN++) {
|
|
18798
|
-
const size =
|
|
18908
|
+
const size = import_fs37.default.statSync(auditLogPath).size;
|
|
18799
18909
|
if (size === 0) break;
|
|
18800
18910
|
const sig = fileSignature(auditLogPath);
|
|
18801
18911
|
const wm = readWatermark(watermarkPath);
|
|
@@ -18803,12 +18913,12 @@ async function shipOnce(deps = {}) {
|
|
|
18803
18913
|
if (offset >= size) break;
|
|
18804
18914
|
const toRead = Math.min(size - offset, MAX_CHUNK_BYTES);
|
|
18805
18915
|
const buf = Buffer.alloc(toRead);
|
|
18806
|
-
const fd =
|
|
18916
|
+
const fd = import_fs37.default.openSync(auditLogPath, "r");
|
|
18807
18917
|
let read2;
|
|
18808
18918
|
try {
|
|
18809
|
-
read2 =
|
|
18919
|
+
read2 = import_fs37.default.readSync(fd, buf, 0, toRead, offset);
|
|
18810
18920
|
} finally {
|
|
18811
|
-
|
|
18921
|
+
import_fs37.default.closeSync(fd);
|
|
18812
18922
|
}
|
|
18813
18923
|
const { rows, consumed } = buildWireRows(buf.subarray(0, read2));
|
|
18814
18924
|
if (consumed === 0) break;
|
|
@@ -18855,8 +18965,8 @@ async function shipOnce(deps = {}) {
|
|
|
18855
18965
|
}
|
|
18856
18966
|
function shipLagBytes(auditLogPath = LOCAL_AUDIT_LOG, watermarkPath = AUDIT_SHIP_WATERMARK) {
|
|
18857
18967
|
try {
|
|
18858
|
-
if (!
|
|
18859
|
-
const size =
|
|
18968
|
+
if (!import_fs37.default.existsSync(auditLogPath)) return 0;
|
|
18969
|
+
const size = import_fs37.default.statSync(auditLogPath).size;
|
|
18860
18970
|
const wm = readWatermark(watermarkPath);
|
|
18861
18971
|
if (!wm) return size;
|
|
18862
18972
|
if (wm.fileSig !== fileSignature(auditLogPath)) return size;
|
|
@@ -18879,19 +18989,19 @@ function startAuditShipper() {
|
|
|
18879
18989
|
setTimeout(() => void shipOnce(), 3e3);
|
|
18880
18990
|
setInterval(() => void shipOnce(), intervalMs);
|
|
18881
18991
|
}
|
|
18882
|
-
var
|
|
18992
|
+
var import_fs37, import_path36, import_os33, import_crypto9, AUDIT_SHIP_WATERMARK, DEFAULT_INTERVAL_MS, MAX_BATCH, MAX_CHUNK_BYTES, MAX_CHUNKS_PER_TICK, FETCH_TIMEOUT_MS, SKIP_CHECKED_BY, shipperStarted;
|
|
18883
18993
|
var init_audit_shipper = __esm({
|
|
18884
18994
|
"src/daemon/audit-shipper.ts"() {
|
|
18885
18995
|
"use strict";
|
|
18886
|
-
|
|
18887
|
-
|
|
18996
|
+
import_fs37 = __toESM(require("fs"));
|
|
18997
|
+
import_path36 = __toESM(require("path"));
|
|
18888
18998
|
import_os33 = __toESM(require("os"));
|
|
18889
18999
|
import_crypto9 = __toESM(require("crypto"));
|
|
18890
19000
|
init_audit();
|
|
18891
19001
|
init_config();
|
|
18892
19002
|
init_sync();
|
|
18893
19003
|
init_cloud();
|
|
18894
|
-
AUDIT_SHIP_WATERMARK =
|
|
19004
|
+
AUDIT_SHIP_WATERMARK = import_path36.default.join(import_os33.default.homedir(), ".node9", "audit-ship.json");
|
|
18895
19005
|
DEFAULT_INTERVAL_MS = 2e4;
|
|
18896
19006
|
MAX_BATCH = 500;
|
|
18897
19007
|
MAX_CHUNK_BYTES = 4 * 1024 * 1024;
|
|
@@ -18952,7 +19062,7 @@ var init_decision = __esm({
|
|
|
18952
19062
|
// src/daemon/dlp-scanner.ts
|
|
18953
19063
|
function loadIndex() {
|
|
18954
19064
|
try {
|
|
18955
|
-
const raw = JSON.parse(
|
|
19065
|
+
const raw = JSON.parse(import_fs38.default.readFileSync(INDEX_FILE, "utf-8"));
|
|
18956
19066
|
if (raw && typeof raw === "object" && !Array.isArray(raw)) {
|
|
18957
19067
|
const r = raw;
|
|
18958
19068
|
if (r.offsets && typeof r.offsets === "object") return r.offsets;
|
|
@@ -18964,63 +19074,63 @@ function loadIndex() {
|
|
|
18964
19074
|
}
|
|
18965
19075
|
function saveIndex(index) {
|
|
18966
19076
|
try {
|
|
18967
|
-
|
|
19077
|
+
import_fs38.default.writeFileSync(INDEX_FILE, JSON.stringify(index), { encoding: "utf-8", mode: 384 });
|
|
18968
19078
|
} catch {
|
|
18969
19079
|
}
|
|
18970
19080
|
}
|
|
18971
19081
|
function appendAuditEntry(entry) {
|
|
18972
19082
|
try {
|
|
18973
|
-
|
|
19083
|
+
import_fs38.default.appendFileSync(AUDIT_LOG_FILE, JSON.stringify(entry) + "\n");
|
|
18974
19084
|
} catch {
|
|
18975
19085
|
}
|
|
18976
19086
|
}
|
|
18977
19087
|
function runDlpScan() {
|
|
18978
|
-
if (!
|
|
19088
|
+
if (!import_fs38.default.existsSync(PROJECTS_DIR2)) return;
|
|
18979
19089
|
const index = loadIndex();
|
|
18980
19090
|
const seenThisPass = /* @__PURE__ */ new Set();
|
|
18981
19091
|
const newFindings = [];
|
|
18982
19092
|
let updated = false;
|
|
18983
19093
|
let projDirs;
|
|
18984
19094
|
try {
|
|
18985
|
-
projDirs =
|
|
19095
|
+
projDirs = import_fs38.default.readdirSync(PROJECTS_DIR2);
|
|
18986
19096
|
} catch {
|
|
18987
19097
|
return;
|
|
18988
19098
|
}
|
|
18989
19099
|
for (const proj of projDirs) {
|
|
18990
|
-
const projPath =
|
|
19100
|
+
const projPath = import_path37.default.join(PROJECTS_DIR2, proj);
|
|
18991
19101
|
try {
|
|
18992
|
-
if (!
|
|
18993
|
-
const real =
|
|
18994
|
-
if (!real.startsWith(PROJECTS_DIR2 +
|
|
19102
|
+
if (!import_fs38.default.lstatSync(projPath).isDirectory()) continue;
|
|
19103
|
+
const real = import_fs38.default.realpathSync(projPath);
|
|
19104
|
+
if (!real.startsWith(PROJECTS_DIR2 + import_path37.default.sep) && real !== PROJECTS_DIR2) continue;
|
|
18995
19105
|
} catch {
|
|
18996
19106
|
continue;
|
|
18997
19107
|
}
|
|
18998
19108
|
let files;
|
|
18999
19109
|
try {
|
|
19000
|
-
files =
|
|
19110
|
+
files = import_fs38.default.readdirSync(projPath).filter((f) => f.endsWith(".jsonl") && !f.startsWith("agent-"));
|
|
19001
19111
|
} catch {
|
|
19002
19112
|
continue;
|
|
19003
19113
|
}
|
|
19004
19114
|
for (const file of files) {
|
|
19005
|
-
const filePath =
|
|
19115
|
+
const filePath = import_path37.default.join(projPath, file);
|
|
19006
19116
|
const lastOffset = index[filePath] ?? 0;
|
|
19007
19117
|
let size;
|
|
19008
19118
|
try {
|
|
19009
|
-
size =
|
|
19119
|
+
size = import_fs38.default.statSync(filePath).size;
|
|
19010
19120
|
} catch {
|
|
19011
19121
|
continue;
|
|
19012
19122
|
}
|
|
19013
19123
|
if (size <= lastOffset) continue;
|
|
19014
19124
|
let fd;
|
|
19015
19125
|
try {
|
|
19016
|
-
fd =
|
|
19126
|
+
fd = import_fs38.default.openSync(filePath, "r");
|
|
19017
19127
|
} catch {
|
|
19018
19128
|
continue;
|
|
19019
19129
|
}
|
|
19020
19130
|
try {
|
|
19021
19131
|
const chunkSize = size - lastOffset;
|
|
19022
19132
|
const buf = Buffer.alloc(chunkSize);
|
|
19023
|
-
|
|
19133
|
+
import_fs38.default.readSync(fd, buf, 0, chunkSize, lastOffset);
|
|
19024
19134
|
const chunk2 = buf.toString("utf-8");
|
|
19025
19135
|
for (const line of chunk2.split("\n")) {
|
|
19026
19136
|
if (!line.trim()) continue;
|
|
@@ -19067,7 +19177,7 @@ function runDlpScan() {
|
|
|
19067
19177
|
updated = true;
|
|
19068
19178
|
} finally {
|
|
19069
19179
|
try {
|
|
19070
|
-
|
|
19180
|
+
import_fs38.default.closeSync(fd);
|
|
19071
19181
|
} catch {
|
|
19072
19182
|
}
|
|
19073
19183
|
}
|
|
@@ -19108,18 +19218,18 @@ function startDlpScanner() {
|
|
|
19108
19218
|
);
|
|
19109
19219
|
timer.unref();
|
|
19110
19220
|
}
|
|
19111
|
-
var
|
|
19221
|
+
var import_fs38, import_path37, import_os34, INDEX_FILE, PROJECTS_DIR2;
|
|
19112
19222
|
var init_dlp_scanner = __esm({
|
|
19113
19223
|
"src/daemon/dlp-scanner.ts"() {
|
|
19114
19224
|
"use strict";
|
|
19115
|
-
|
|
19116
|
-
|
|
19225
|
+
import_fs38 = __toESM(require("fs"));
|
|
19226
|
+
import_path37 = __toESM(require("path"));
|
|
19117
19227
|
import_os34 = __toESM(require("os"));
|
|
19118
19228
|
init_dlp();
|
|
19119
19229
|
init_native();
|
|
19120
19230
|
init_state2();
|
|
19121
|
-
INDEX_FILE =
|
|
19122
|
-
PROJECTS_DIR2 =
|
|
19231
|
+
INDEX_FILE = import_path37.default.join(import_os34.default.homedir(), ".node9", "dlp-index.json");
|
|
19232
|
+
PROJECTS_DIR2 = import_path37.default.join(import_os34.default.homedir(), ".claude", "projects");
|
|
19123
19233
|
}
|
|
19124
19234
|
});
|
|
19125
19235
|
|
|
@@ -19130,7 +19240,7 @@ function idKey(e) {
|
|
|
19130
19240
|
}
|
|
19131
19241
|
function loadBaseline() {
|
|
19132
19242
|
try {
|
|
19133
|
-
const raw = JSON.parse(
|
|
19243
|
+
const raw = JSON.parse(import_fs39.default.readFileSync(BASELINE_FILE2, "utf-8"));
|
|
19134
19244
|
return new Set(Array.isArray(raw) ? raw : []);
|
|
19135
19245
|
} catch {
|
|
19136
19246
|
return /* @__PURE__ */ new Set();
|
|
@@ -19138,7 +19248,7 @@ function loadBaseline() {
|
|
|
19138
19248
|
}
|
|
19139
19249
|
function saveBaseline(keys) {
|
|
19140
19250
|
try {
|
|
19141
|
-
|
|
19251
|
+
import_fs39.default.writeFileSync(BASELINE_FILE2, JSON.stringify([...keys].slice(-BASELINE_CAP)), {
|
|
19142
19252
|
mode: 384
|
|
19143
19253
|
});
|
|
19144
19254
|
} catch {
|
|
@@ -19316,12 +19426,12 @@ function startMcpReconciler() {
|
|
|
19316
19426
|
};
|
|
19317
19427
|
schedule();
|
|
19318
19428
|
}
|
|
19319
|
-
var
|
|
19429
|
+
var import_fs39, import_path38, import_os35, import_crypto10, BASELINE_FILE2, BASELINE_CAP, DEFAULT_INTERVAL_MIN, DEFAULT_STALE_DAYS;
|
|
19320
19430
|
var init_mcp_reconciler = __esm({
|
|
19321
19431
|
"src/daemon/mcp-reconciler.ts"() {
|
|
19322
19432
|
"use strict";
|
|
19323
|
-
|
|
19324
|
-
|
|
19433
|
+
import_fs39 = __toESM(require("fs"));
|
|
19434
|
+
import_path38 = __toESM(require("path"));
|
|
19325
19435
|
import_os35 = __toESM(require("os"));
|
|
19326
19436
|
import_crypto10 = __toESM(require("crypto"));
|
|
19327
19437
|
init_mcp_wrap();
|
|
@@ -19330,7 +19440,7 @@ var init_mcp_reconciler = __esm({
|
|
|
19330
19440
|
init_cloud();
|
|
19331
19441
|
init_audit();
|
|
19332
19442
|
init_mcp_pin();
|
|
19333
|
-
BASELINE_FILE2 =
|
|
19443
|
+
BASELINE_FILE2 = import_path38.default.join(import_os35.default.homedir(), ".node9", "mcp-baseline.json");
|
|
19334
19444
|
BASELINE_CAP = 500;
|
|
19335
19445
|
DEFAULT_INTERVAL_MIN = 60;
|
|
19336
19446
|
DEFAULT_STALE_DAYS = 7;
|
|
@@ -19407,17 +19517,17 @@ var init_hook_heal = __esm({
|
|
|
19407
19517
|
// src/daemon/startup-log.ts
|
|
19408
19518
|
function capStartupLog(file) {
|
|
19409
19519
|
try {
|
|
19410
|
-
if (
|
|
19520
|
+
if (import_fs40.default.statSync(file).size > MAX_STARTUP_LOG_BYTES) import_fs40.default.truncateSync(file);
|
|
19411
19521
|
} catch {
|
|
19412
19522
|
}
|
|
19413
19523
|
}
|
|
19414
19524
|
function openStartupLogFd() {
|
|
19415
19525
|
try {
|
|
19416
19526
|
const file = DAEMON_STARTUP_LOG();
|
|
19417
|
-
const dir =
|
|
19418
|
-
if (!
|
|
19527
|
+
const dir = import_path39.default.dirname(file);
|
|
19528
|
+
if (!import_fs40.default.existsSync(dir)) import_fs40.default.mkdirSync(dir, { recursive: true });
|
|
19419
19529
|
capStartupLog(file);
|
|
19420
|
-
return
|
|
19530
|
+
return import_fs40.default.openSync(file, "a");
|
|
19421
19531
|
} catch {
|
|
19422
19532
|
return void 0;
|
|
19423
19533
|
}
|
|
@@ -19433,18 +19543,18 @@ function recordStartupState(outcome, kind, detail) {
|
|
|
19433
19543
|
}
|
|
19434
19544
|
}
|
|
19435
19545
|
const file = DAEMON_STARTUP_STATE();
|
|
19436
|
-
const dir =
|
|
19437
|
-
if (!
|
|
19546
|
+
const dir = import_path39.default.dirname(file);
|
|
19547
|
+
if (!import_fs40.default.existsSync(dir)) import_fs40.default.mkdirSync(dir, { recursive: true });
|
|
19438
19548
|
const state = { outcome, at: (/* @__PURE__ */ new Date()).toISOString() };
|
|
19439
19549
|
if (kind) state.kind = kind;
|
|
19440
19550
|
if (detail) state.detail = detail.slice(0, MAX_DETAIL);
|
|
19441
19551
|
const tmp = `${file}.${process.pid}.tmp`;
|
|
19442
19552
|
try {
|
|
19443
|
-
|
|
19444
|
-
|
|
19553
|
+
import_fs40.default.writeFileSync(tmp, JSON.stringify(state), "utf-8");
|
|
19554
|
+
import_fs40.default.renameSync(tmp, file);
|
|
19445
19555
|
} catch (err2) {
|
|
19446
19556
|
try {
|
|
19447
|
-
|
|
19557
|
+
import_fs40.default.unlinkSync(tmp);
|
|
19448
19558
|
} catch {
|
|
19449
19559
|
}
|
|
19450
19560
|
throw err2;
|
|
@@ -19454,7 +19564,7 @@ function recordStartupState(outcome, kind, detail) {
|
|
|
19454
19564
|
}
|
|
19455
19565
|
function readStartupState() {
|
|
19456
19566
|
try {
|
|
19457
|
-
const raw =
|
|
19567
|
+
const raw = import_fs40.default.readFileSync(DAEMON_STARTUP_STATE(), "utf-8");
|
|
19458
19568
|
const s = JSON.parse(raw);
|
|
19459
19569
|
if (!s || typeof s.outcome !== "string" || typeof s.at !== "string") return null;
|
|
19460
19570
|
return s;
|
|
@@ -19489,24 +19599,24 @@ function readStartupCause(maxAgeMs = 24 * 60 * 60 * 1e3) {
|
|
|
19489
19599
|
function logDaemonStartup(kind, detail) {
|
|
19490
19600
|
try {
|
|
19491
19601
|
const file = DAEMON_STARTUP_LOG();
|
|
19492
|
-
const dir =
|
|
19493
|
-
if (!
|
|
19602
|
+
const dir = import_path39.default.dirname(file);
|
|
19603
|
+
if (!import_fs40.default.existsSync(dir)) import_fs40.default.mkdirSync(dir, { recursive: true });
|
|
19494
19604
|
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] daemon-startup:${kind}${detail ? ` ${detail}` : ""}
|
|
19495
19605
|
`;
|
|
19496
|
-
|
|
19606
|
+
import_fs40.default.appendFileSync(file, line, "utf-8");
|
|
19497
19607
|
} catch {
|
|
19498
19608
|
}
|
|
19499
19609
|
}
|
|
19500
|
-
var
|
|
19610
|
+
var import_fs40, import_path39, import_os36, DAEMON_STARTUP_LOG, MAX_STARTUP_LOG_BYTES, DAEMON_STARTUP_STATE, MAX_DETAIL, STARTING_GRACE_MS;
|
|
19501
19611
|
var init_startup_log = __esm({
|
|
19502
19612
|
"src/daemon/startup-log.ts"() {
|
|
19503
19613
|
"use strict";
|
|
19504
|
-
|
|
19505
|
-
|
|
19614
|
+
import_fs40 = __toESM(require("fs"));
|
|
19615
|
+
import_path39 = __toESM(require("path"));
|
|
19506
19616
|
import_os36 = __toESM(require("os"));
|
|
19507
|
-
DAEMON_STARTUP_LOG = () =>
|
|
19617
|
+
DAEMON_STARTUP_LOG = () => import_path39.default.join(import_os36.default.homedir(), ".node9", "daemon-startup.log");
|
|
19508
19618
|
MAX_STARTUP_LOG_BYTES = 256 * 1024;
|
|
19509
|
-
DAEMON_STARTUP_STATE = () =>
|
|
19619
|
+
DAEMON_STARTUP_STATE = () => import_path39.default.join(import_os36.default.homedir(), ".node9", "daemon-startup-state.json");
|
|
19510
19620
|
MAX_DETAIL = 200;
|
|
19511
19621
|
STARTING_GRACE_MS = 90 * 1e3;
|
|
19512
19622
|
}
|
|
@@ -19602,6 +19712,7 @@ function startDaemon() {
|
|
|
19602
19712
|
}
|
|
19603
19713
|
const internalToken = (0, import_crypto11.randomUUID)();
|
|
19604
19714
|
const validToken = (req) => req.headers["x-node9-internal"] === internalToken || req.headers["x-node9-token"] === internalToken;
|
|
19715
|
+
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
19605
19716
|
const IDLE_TIMEOUT_MS = 12 * 60 * 60 * 1e3;
|
|
19606
19717
|
const watchMode = process.env.NODE9_WATCH_MODE === "1";
|
|
19607
19718
|
let idleTimer;
|
|
@@ -19611,7 +19722,7 @@ function startDaemon() {
|
|
|
19611
19722
|
idleTimer = setTimeout(() => {
|
|
19612
19723
|
if (autoStarted) {
|
|
19613
19724
|
try {
|
|
19614
|
-
|
|
19725
|
+
import_fs41.default.unlinkSync(DAEMON_PID_FILE);
|
|
19615
19726
|
} catch {
|
|
19616
19727
|
}
|
|
19617
19728
|
}
|
|
@@ -19756,7 +19867,7 @@ data: ${JSON.stringify(item.data)}
|
|
|
19756
19867
|
mcpServer: entry.mcpServer
|
|
19757
19868
|
});
|
|
19758
19869
|
}
|
|
19759
|
-
const projectCwd = typeof cwd === "string" &&
|
|
19870
|
+
const projectCwd = typeof cwd === "string" && import_path40.default.isAbsolute(cwd) ? cwd : void 0;
|
|
19760
19871
|
const projectConfig = getConfig(projectCwd);
|
|
19761
19872
|
const browserEnabled = projectConfig.settings.approvers?.browser !== false;
|
|
19762
19873
|
const terminalEnabled = projectConfig.settings.approvers?.terminal !== false;
|
|
@@ -19974,6 +20085,35 @@ data: ${JSON.stringify(item.data)}
|
|
|
19974
20085
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
19975
20086
|
return res.end(JSON.stringify({ interactive: hasInteractiveClient() }));
|
|
19976
20087
|
}
|
|
20088
|
+
if (req.method === "POST" && pathname === "/shutdown") {
|
|
20089
|
+
if (!validToken(req)) {
|
|
20090
|
+
res.writeHead(401, { "Content-Type": "application/json" });
|
|
20091
|
+
return res.end(JSON.stringify({ error: "unauthorized" }));
|
|
20092
|
+
}
|
|
20093
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
20094
|
+
res.end(JSON.stringify({ ok: true }));
|
|
20095
|
+
logDaemonStartup("shutdown", "yielding on authenticated /shutdown (takeover or restart)");
|
|
20096
|
+
setImmediate(() => {
|
|
20097
|
+
try {
|
|
20098
|
+
server.close();
|
|
20099
|
+
} catch {
|
|
20100
|
+
}
|
|
20101
|
+
process.exit(0);
|
|
20102
|
+
});
|
|
20103
|
+
return;
|
|
20104
|
+
}
|
|
20105
|
+
if (req.method === "GET" && pathname === "/health") {
|
|
20106
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
20107
|
+
return res.end(
|
|
20108
|
+
JSON.stringify({
|
|
20109
|
+
version: CURRENT_BUILD.version,
|
|
20110
|
+
buildId: buildIdString(CURRENT_BUILD),
|
|
20111
|
+
pid: process.pid,
|
|
20112
|
+
startedAt,
|
|
20113
|
+
autoStarted
|
|
20114
|
+
})
|
|
20115
|
+
);
|
|
20116
|
+
}
|
|
19977
20117
|
if (req.method === "GET" && pathname === "/state/check") {
|
|
19978
20118
|
const predicatesParam = reqUrl.searchParams.get("predicates") ?? "";
|
|
19979
20119
|
const predicates = predicatesParam.split(",").filter(Boolean);
|
|
@@ -20052,8 +20192,8 @@ data: ${JSON.stringify(item.data)}
|
|
|
20052
20192
|
if (!validToken(req)) return res.writeHead(403).end();
|
|
20053
20193
|
const periodParam = reqUrl.searchParams.get("period") || "7d";
|
|
20054
20194
|
const period = ["today", "7d", "30d", "month"].includes(periodParam) ? periodParam : "7d";
|
|
20055
|
-
const logPath =
|
|
20056
|
-
if (!
|
|
20195
|
+
const logPath = import_path40.default.join(import_os37.default.homedir(), ".node9", "audit.log");
|
|
20196
|
+
if (!import_fs41.default.existsSync(logPath)) {
|
|
20057
20197
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
20058
20198
|
return res.end(
|
|
20059
20199
|
JSON.stringify({
|
|
@@ -20066,7 +20206,7 @@ data: ${JSON.stringify(item.data)}
|
|
|
20066
20206
|
);
|
|
20067
20207
|
}
|
|
20068
20208
|
try {
|
|
20069
|
-
const raw =
|
|
20209
|
+
const raw = import_fs41.default.readFileSync(logPath, "utf-8");
|
|
20070
20210
|
const allEntries = raw.split("\n").flatMap((line) => {
|
|
20071
20211
|
if (!line.trim()) return [];
|
|
20072
20212
|
try {
|
|
@@ -20381,34 +20521,114 @@ data: ${JSON.stringify(item.data)}
|
|
|
20381
20521
|
setDaemonServer(server);
|
|
20382
20522
|
let bindAttempts = 0;
|
|
20383
20523
|
const MAX_BIND_ATTEMPTS = 3;
|
|
20524
|
+
let tookDownHolder = false;
|
|
20384
20525
|
function retryListen() {
|
|
20385
20526
|
if (++bindAttempts >= MAX_BIND_ATTEMPTS) {
|
|
20527
|
+
if (tookDownHolder) {
|
|
20528
|
+
logDaemonStartup(
|
|
20529
|
+
"takeover-bind-failed",
|
|
20530
|
+
`shut down the previous daemon but could not bind :${DAEMON_PORT} \u2014 the port was taken during handover`
|
|
20531
|
+
);
|
|
20532
|
+
recordStartupState(
|
|
20533
|
+
"failed",
|
|
20534
|
+
"takeover-bind-failed",
|
|
20535
|
+
`took over :${DAEMON_PORT} but could not rebind (the port was claimed during handover) \u2014 no daemon is serving; run: node9 daemon restart`
|
|
20536
|
+
);
|
|
20537
|
+
} else {
|
|
20538
|
+
logDaemonStartup(
|
|
20539
|
+
"port-unavailable",
|
|
20540
|
+
`:${DAEMON_PORT} is held by something that is not a node9 daemon`
|
|
20541
|
+
);
|
|
20542
|
+
recordStartupState(
|
|
20543
|
+
"failed",
|
|
20544
|
+
"port-unavailable",
|
|
20545
|
+
`:${DAEMON_PORT} is held by another process that is not a node9 daemon \u2014 free the port, then: node9 daemon --background`
|
|
20546
|
+
);
|
|
20547
|
+
}
|
|
20548
|
+
return process.exit(0);
|
|
20549
|
+
}
|
|
20550
|
+
server.listen(DAEMON_PORT, DAEMON_HOST);
|
|
20551
|
+
}
|
|
20552
|
+
async function decideAgainstHolder(holderPid, holderToken) {
|
|
20553
|
+
let holderBuildId = null;
|
|
20554
|
+
try {
|
|
20555
|
+
const res = await fetch(`http://${DAEMON_HOST}:${DAEMON_PORT}/health`, {
|
|
20556
|
+
signal: AbortSignal.timeout(800)
|
|
20557
|
+
});
|
|
20558
|
+
if (res.ok) {
|
|
20559
|
+
const j = await res.json().catch(() => null);
|
|
20560
|
+
if (j && typeof j.buildId === "string") holderBuildId = j.buildId;
|
|
20561
|
+
}
|
|
20562
|
+
} catch {
|
|
20563
|
+
}
|
|
20564
|
+
const holderBuild = holderBuildId ? parseBuildId(holderBuildId) : null;
|
|
20565
|
+
if (holderBuild && compareBuild(CURRENT_BUILD, holderBuild) > 0 && holderToken) {
|
|
20566
|
+
try {
|
|
20567
|
+
const r = await fetch(`http://${DAEMON_HOST}:${DAEMON_PORT}/shutdown`, {
|
|
20568
|
+
method: "POST",
|
|
20569
|
+
headers: { "x-node9-internal": holderToken },
|
|
20570
|
+
signal: AbortSignal.timeout(2e3)
|
|
20571
|
+
});
|
|
20572
|
+
if (r.ok) {
|
|
20573
|
+
for (let i = 0; i < 10; i++) {
|
|
20574
|
+
await new Promise((resolve2) => setTimeout(resolve2, 200));
|
|
20575
|
+
const stillUp = await fetch(`http://${DAEMON_HOST}:${DAEMON_PORT}/health`, {
|
|
20576
|
+
signal: AbortSignal.timeout(300)
|
|
20577
|
+
}).then(
|
|
20578
|
+
() => true,
|
|
20579
|
+
() => false
|
|
20580
|
+
);
|
|
20581
|
+
if (!stillUp) break;
|
|
20582
|
+
}
|
|
20583
|
+
logDaemonStartup(
|
|
20584
|
+
"takeover",
|
|
20585
|
+
`took over :${DAEMON_PORT} from older build ${holderBuildId} (pid ${holderPid})`
|
|
20586
|
+
);
|
|
20587
|
+
tookDownHolder = true;
|
|
20588
|
+
retryListen();
|
|
20589
|
+
return;
|
|
20590
|
+
}
|
|
20591
|
+
recordStartupState(
|
|
20592
|
+
"failed",
|
|
20593
|
+
"version-skew-unauthenticated",
|
|
20594
|
+
`an older-build daemon (${holderBuildId}) holds :${DAEMON_PORT} but could not be authenticated for takeover \u2014 run: node9 daemon restart`
|
|
20595
|
+
);
|
|
20596
|
+
logDaemonStartup("port-in-use", `older build on :${DAEMON_PORT}, /shutdown refused`);
|
|
20597
|
+
return process.exit(0);
|
|
20598
|
+
} catch {
|
|
20599
|
+
}
|
|
20600
|
+
}
|
|
20601
|
+
if (holderBuild && compareBuild(holderBuild, CURRENT_BUILD) > 0) {
|
|
20386
20602
|
logDaemonStartup(
|
|
20387
|
-
"port-
|
|
20388
|
-
|
|
20389
|
-
);
|
|
20390
|
-
recordStartupState(
|
|
20391
|
-
"failed",
|
|
20392
|
-
"port-unavailable",
|
|
20393
|
-
`:${DAEMON_PORT} is held by another process that is not a node9 daemon \u2014 free the port, then: node9 daemon --background`
|
|
20603
|
+
"port-in-use",
|
|
20604
|
+
`a NEWER daemon (${holderBuildId}, pid ${holderPid}) owns :${DAEMON_PORT} \u2014 yielding`
|
|
20394
20605
|
);
|
|
20606
|
+
recordStartupState("ok-elsewhere", "newer-daemon-running");
|
|
20395
20607
|
return process.exit(0);
|
|
20396
20608
|
}
|
|
20397
|
-
|
|
20609
|
+
logDaemonStartup("port-in-use", `another daemon (pid ${holderPid}) owns :${DAEMON_PORT}`);
|
|
20610
|
+
recordStartupState("ok-elsewhere");
|
|
20611
|
+
return process.exit(0);
|
|
20398
20612
|
}
|
|
20399
20613
|
server.on("error", (e) => {
|
|
20400
20614
|
if (e.code === "EADDRINUSE") {
|
|
20401
20615
|
try {
|
|
20402
|
-
if (
|
|
20403
|
-
const
|
|
20616
|
+
if (import_fs41.default.existsSync(DAEMON_PID_FILE)) {
|
|
20617
|
+
const parsed = JSON.parse(import_fs41.default.readFileSync(DAEMON_PID_FILE, "utf-8"));
|
|
20618
|
+
const pid = parsed.pid;
|
|
20619
|
+
if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0 || pid > 4194304) {
|
|
20620
|
+
throw new Error("invalid pid in daemon.pid");
|
|
20621
|
+
}
|
|
20404
20622
|
process.kill(pid, 0);
|
|
20405
|
-
|
|
20406
|
-
|
|
20407
|
-
|
|
20623
|
+
void decideAgainstHolder(
|
|
20624
|
+
pid,
|
|
20625
|
+
typeof parsed.internalToken === "string" ? parsed.internalToken : null
|
|
20626
|
+
);
|
|
20627
|
+
return;
|
|
20408
20628
|
}
|
|
20409
20629
|
} catch {
|
|
20410
20630
|
try {
|
|
20411
|
-
|
|
20631
|
+
import_fs41.default.unlinkSync(DAEMON_PID_FILE);
|
|
20412
20632
|
} catch {
|
|
20413
20633
|
}
|
|
20414
20634
|
retryListen();
|
|
@@ -20443,7 +20663,12 @@ data: ${JSON.stringify(item.data)}
|
|
|
20443
20663
|
process.kill(orphanPid, 0);
|
|
20444
20664
|
atomicWriteSync2(
|
|
20445
20665
|
DAEMON_PID_FILE,
|
|
20446
|
-
JSON.stringify({
|
|
20666
|
+
JSON.stringify({
|
|
20667
|
+
pid: orphanPid,
|
|
20668
|
+
port: DAEMON_PORT,
|
|
20669
|
+
internalToken: null,
|
|
20670
|
+
autoStarted
|
|
20671
|
+
}),
|
|
20447
20672
|
{ mode: 384 }
|
|
20448
20673
|
);
|
|
20449
20674
|
adopted = true;
|
|
@@ -20491,7 +20716,15 @@ data: ${JSON.stringify(item.data)}
|
|
|
20491
20716
|
server.listen(DAEMON_PORT, DAEMON_HOST, () => {
|
|
20492
20717
|
atomicWriteSync2(
|
|
20493
20718
|
DAEMON_PID_FILE,
|
|
20494
|
-
JSON.stringify({
|
|
20719
|
+
JSON.stringify({
|
|
20720
|
+
pid: process.pid,
|
|
20721
|
+
port: DAEMON_PORT,
|
|
20722
|
+
internalToken,
|
|
20723
|
+
autoStarted,
|
|
20724
|
+
version: CURRENT_BUILD.version,
|
|
20725
|
+
buildId: buildIdString(CURRENT_BUILD),
|
|
20726
|
+
startedAt
|
|
20727
|
+
}),
|
|
20495
20728
|
{ mode: 384 }
|
|
20496
20729
|
);
|
|
20497
20730
|
console.error(import_chalk6.default.green(`\u{1F6E1}\uFE0F Node9 Guard LIVE on 127.0.0.1:${DAEMON_PORT}`));
|
|
@@ -20503,13 +20736,13 @@ data: ${JSON.stringify(item.data)}
|
|
|
20503
20736
|
}
|
|
20504
20737
|
startActivitySocket();
|
|
20505
20738
|
}
|
|
20506
|
-
var import_http3,
|
|
20739
|
+
var import_http3, import_fs41, import_path40, import_os37, import_crypto11, import_child_process2, import_chalk6;
|
|
20507
20740
|
var init_server = __esm({
|
|
20508
20741
|
"src/daemon/server.ts"() {
|
|
20509
20742
|
"use strict";
|
|
20510
20743
|
import_http3 = __toESM(require("http"));
|
|
20511
|
-
|
|
20512
|
-
|
|
20744
|
+
import_fs41 = __toESM(require("fs"));
|
|
20745
|
+
import_path40 = __toESM(require("path"));
|
|
20513
20746
|
import_os37 = __toESM(require("os"));
|
|
20514
20747
|
import_crypto11 = require("crypto");
|
|
20515
20748
|
import_child_process2 = require("child_process");
|
|
@@ -20517,6 +20750,7 @@ var init_server = __esm({
|
|
|
20517
20750
|
init_core();
|
|
20518
20751
|
init_scan();
|
|
20519
20752
|
init_scan_summary();
|
|
20753
|
+
init_build_id();
|
|
20520
20754
|
init_state2();
|
|
20521
20755
|
init_state();
|
|
20522
20756
|
init_costSync();
|
|
@@ -20535,8 +20769,8 @@ var init_server = __esm({
|
|
|
20535
20769
|
function resolveNode9Binary() {
|
|
20536
20770
|
try {
|
|
20537
20771
|
const script = process.argv[1];
|
|
20538
|
-
if (typeof script === "string" &&
|
|
20539
|
-
return
|
|
20772
|
+
if (typeof script === "string" && import_path41.default.isAbsolute(script) && import_fs42.default.existsSync(script)) {
|
|
20773
|
+
return import_fs42.default.realpathSync(script);
|
|
20540
20774
|
}
|
|
20541
20775
|
} catch {
|
|
20542
20776
|
}
|
|
@@ -20554,11 +20788,11 @@ function xmlEscape(s) {
|
|
|
20554
20788
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
20555
20789
|
}
|
|
20556
20790
|
function launchdPlist(binaryPath) {
|
|
20557
|
-
const logDir =
|
|
20791
|
+
const logDir = import_path41.default.join(import_os38.default.homedir(), ".node9");
|
|
20558
20792
|
const nodePath = xmlEscape(process.execPath);
|
|
20559
20793
|
const scriptPath = xmlEscape(binaryPath);
|
|
20560
|
-
const outLog = xmlEscape(
|
|
20561
|
-
const errLog = xmlEscape(
|
|
20794
|
+
const outLog = xmlEscape(import_path41.default.join(logDir, "daemon.log"));
|
|
20795
|
+
const errLog = xmlEscape(import_path41.default.join(logDir, "daemon-error.log"));
|
|
20562
20796
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
20563
20797
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
20564
20798
|
<plist version="1.0">
|
|
@@ -20591,9 +20825,9 @@ function launchdPlist(binaryPath) {
|
|
|
20591
20825
|
`;
|
|
20592
20826
|
}
|
|
20593
20827
|
function installLaunchd(binaryPath) {
|
|
20594
|
-
const dir =
|
|
20595
|
-
if (!
|
|
20596
|
-
|
|
20828
|
+
const dir = import_path41.default.dirname(LAUNCHD_PLIST);
|
|
20829
|
+
if (!import_fs42.default.existsSync(dir)) import_fs42.default.mkdirSync(dir, { recursive: true });
|
|
20830
|
+
import_fs42.default.writeFileSync(LAUNCHD_PLIST, launchdPlist(binaryPath), "utf-8");
|
|
20597
20831
|
(0, import_child_process3.spawnSync)("launchctl", ["unload", LAUNCHD_PLIST], { encoding: "utf8" });
|
|
20598
20832
|
const r = (0, import_child_process3.spawnSync)("launchctl", ["load", "-w", LAUNCHD_PLIST], {
|
|
20599
20833
|
encoding: "utf8",
|
|
@@ -20604,13 +20838,13 @@ function installLaunchd(binaryPath) {
|
|
|
20604
20838
|
}
|
|
20605
20839
|
}
|
|
20606
20840
|
function uninstallLaunchd() {
|
|
20607
|
-
if (
|
|
20841
|
+
if (import_fs42.default.existsSync(LAUNCHD_PLIST)) {
|
|
20608
20842
|
(0, import_child_process3.spawnSync)("launchctl", ["unload", "-w", LAUNCHD_PLIST], { encoding: "utf8", timeout: 5e3 });
|
|
20609
|
-
|
|
20843
|
+
import_fs42.default.unlinkSync(LAUNCHD_PLIST);
|
|
20610
20844
|
}
|
|
20611
20845
|
}
|
|
20612
20846
|
function isLaunchdInstalled() {
|
|
20613
|
-
return
|
|
20847
|
+
return import_fs42.default.existsSync(LAUNCHD_PLIST);
|
|
20614
20848
|
}
|
|
20615
20849
|
function systemdUnit(binaryPath) {
|
|
20616
20850
|
return `[Unit]
|
|
@@ -20629,10 +20863,10 @@ WantedBy=default.target
|
|
|
20629
20863
|
`;
|
|
20630
20864
|
}
|
|
20631
20865
|
function installSystemd(binaryPath) {
|
|
20632
|
-
if (!
|
|
20633
|
-
|
|
20866
|
+
if (!import_fs42.default.existsSync(SYSTEMD_UNIT_DIR)) {
|
|
20867
|
+
import_fs42.default.mkdirSync(SYSTEMD_UNIT_DIR, { recursive: true });
|
|
20634
20868
|
}
|
|
20635
|
-
|
|
20869
|
+
import_fs42.default.writeFileSync(SYSTEMD_UNIT, systemdUnit(binaryPath), "utf-8");
|
|
20636
20870
|
try {
|
|
20637
20871
|
(0, import_child_process3.execFileSync)("loginctl", ["enable-linger", import_os38.default.userInfo().username], { timeout: 3e3 });
|
|
20638
20872
|
} catch {
|
|
@@ -20654,23 +20888,23 @@ function installSystemd(binaryPath) {
|
|
|
20654
20888
|
}
|
|
20655
20889
|
}
|
|
20656
20890
|
function uninstallSystemd() {
|
|
20657
|
-
if (
|
|
20891
|
+
if (import_fs42.default.existsSync(SYSTEMD_UNIT)) {
|
|
20658
20892
|
(0, import_child_process3.spawnSync)("systemctl", ["--user", "disable", "--now", "node9-daemon"], {
|
|
20659
20893
|
encoding: "utf8",
|
|
20660
20894
|
timeout: 5e3
|
|
20661
20895
|
});
|
|
20662
20896
|
(0, import_child_process3.spawnSync)("systemctl", ["--user", "daemon-reload"], { encoding: "utf8", timeout: 5e3 });
|
|
20663
|
-
|
|
20897
|
+
import_fs42.default.unlinkSync(SYSTEMD_UNIT);
|
|
20664
20898
|
}
|
|
20665
20899
|
}
|
|
20666
20900
|
function isSystemdInstalled() {
|
|
20667
|
-
return
|
|
20901
|
+
return import_fs42.default.existsSync(SYSTEMD_UNIT);
|
|
20668
20902
|
}
|
|
20669
20903
|
function stopRunningDaemon() {
|
|
20670
|
-
const pidFile =
|
|
20671
|
-
if (!
|
|
20904
|
+
const pidFile = import_path41.default.join(import_os38.default.homedir(), ".node9", "daemon.pid");
|
|
20905
|
+
if (!import_fs42.default.existsSync(pidFile)) return;
|
|
20672
20906
|
try {
|
|
20673
|
-
const data = JSON.parse(
|
|
20907
|
+
const data = JSON.parse(import_fs42.default.readFileSync(pidFile, "utf-8"));
|
|
20674
20908
|
const pid = data.pid;
|
|
20675
20909
|
const MAX_PID2 = 4194304;
|
|
20676
20910
|
if (typeof pid === "number" && Number.isInteger(pid) && pid > 0 && pid <= MAX_PID2) {
|
|
@@ -20690,7 +20924,7 @@ function stopRunningDaemon() {
|
|
|
20690
20924
|
}
|
|
20691
20925
|
}
|
|
20692
20926
|
try {
|
|
20693
|
-
|
|
20927
|
+
import_fs42.default.unlinkSync(pidFile);
|
|
20694
20928
|
} catch {
|
|
20695
20929
|
}
|
|
20696
20930
|
} catch {
|
|
@@ -20829,26 +21063,26 @@ function isDaemonServiceEnabled() {
|
|
|
20829
21063
|
}
|
|
20830
21064
|
return false;
|
|
20831
21065
|
}
|
|
20832
|
-
var
|
|
21066
|
+
var import_fs42, import_path41, import_os38, import_child_process3, LAUNCHD_LABEL, LAUNCHD_PLIST, SYSTEMD_UNIT_DIR, SYSTEMD_UNIT;
|
|
20833
21067
|
var init_service = __esm({
|
|
20834
21068
|
"src/daemon/service.ts"() {
|
|
20835
21069
|
"use strict";
|
|
20836
|
-
|
|
20837
|
-
|
|
21070
|
+
import_fs42 = __toESM(require("fs"));
|
|
21071
|
+
import_path41 = __toESM(require("path"));
|
|
20838
21072
|
import_os38 = __toESM(require("os"));
|
|
20839
21073
|
import_child_process3 = require("child_process");
|
|
20840
21074
|
LAUNCHD_LABEL = "ai.node9.daemon";
|
|
20841
|
-
LAUNCHD_PLIST =
|
|
20842
|
-
SYSTEMD_UNIT_DIR =
|
|
20843
|
-
SYSTEMD_UNIT =
|
|
21075
|
+
LAUNCHD_PLIST = import_path41.default.join(import_os38.default.homedir(), "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`);
|
|
21076
|
+
SYSTEMD_UNIT_DIR = import_path41.default.join(import_os38.default.homedir(), ".config", "systemd", "user");
|
|
21077
|
+
SYSTEMD_UNIT = import_path41.default.join(SYSTEMD_UNIT_DIR, "node9-daemon.service");
|
|
20844
21078
|
}
|
|
20845
21079
|
});
|
|
20846
21080
|
|
|
20847
21081
|
// src/daemon/index.ts
|
|
20848
21082
|
function stopDaemon() {
|
|
20849
|
-
if (!
|
|
21083
|
+
if (!import_fs43.default.existsSync(DAEMON_PID_FILE)) return console.log(import_chalk7.default.yellow("Not running."));
|
|
20850
21084
|
try {
|
|
20851
|
-
const data = JSON.parse(
|
|
21085
|
+
const data = JSON.parse(import_fs43.default.readFileSync(DAEMON_PID_FILE, "utf-8"));
|
|
20852
21086
|
const pid = data.pid;
|
|
20853
21087
|
if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0 || pid > MAX_PID) {
|
|
20854
21088
|
console.log(import_chalk7.default.gray("Cleaned up invalid PID file."));
|
|
@@ -20860,7 +21094,7 @@ function stopDaemon() {
|
|
|
20860
21094
|
console.log(import_chalk7.default.gray("Cleaned up stale PID file."));
|
|
20861
21095
|
} finally {
|
|
20862
21096
|
try {
|
|
20863
|
-
|
|
21097
|
+
import_fs43.default.unlinkSync(DAEMON_PID_FILE);
|
|
20864
21098
|
} catch {
|
|
20865
21099
|
}
|
|
20866
21100
|
}
|
|
@@ -20869,9 +21103,9 @@ function daemonStatus() {
|
|
|
20869
21103
|
const serviceInstalled = isDaemonServiceInstalled();
|
|
20870
21104
|
const serviceLabel = serviceInstalled ? import_chalk7.default.green("installed (starts on login)") : import_chalk7.default.yellow("not installed \u2014 run: node9 daemon install");
|
|
20871
21105
|
let processStatus;
|
|
20872
|
-
if (
|
|
21106
|
+
if (import_fs43.default.existsSync(DAEMON_PID_FILE)) {
|
|
20873
21107
|
try {
|
|
20874
|
-
const data = JSON.parse(
|
|
21108
|
+
const data = JSON.parse(import_fs43.default.readFileSync(DAEMON_PID_FILE, "utf-8"));
|
|
20875
21109
|
const pid = data.pid;
|
|
20876
21110
|
const port = data.port;
|
|
20877
21111
|
if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0 || pid > MAX_PID) {
|
|
@@ -20893,11 +21127,11 @@ function daemonStatus() {
|
|
|
20893
21127
|
console.log(` Service : ${serviceLabel}
|
|
20894
21128
|
`);
|
|
20895
21129
|
}
|
|
20896
|
-
var
|
|
21130
|
+
var import_fs43, import_chalk7, MAX_PID;
|
|
20897
21131
|
var init_daemon2 = __esm({
|
|
20898
21132
|
"src/daemon/index.ts"() {
|
|
20899
21133
|
"use strict";
|
|
20900
|
-
|
|
21134
|
+
import_fs43 = __toESM(require("fs"));
|
|
20901
21135
|
import_chalk7 = __toESM(require("chalk"));
|
|
20902
21136
|
init_server();
|
|
20903
21137
|
init_state2();
|
|
@@ -22016,14 +22250,14 @@ var require_util = __commonJS({
|
|
|
22016
22250
|
}
|
|
22017
22251
|
const port = url.port != null ? url.port : url.protocol === "https:" ? 443 : 80;
|
|
22018
22252
|
let origin = url.origin != null ? url.origin : `${url.protocol || ""}//${url.hostname || ""}:${port}`;
|
|
22019
|
-
let
|
|
22253
|
+
let path72 = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`;
|
|
22020
22254
|
if (origin[origin.length - 1] === "/") {
|
|
22021
22255
|
origin = origin.slice(0, origin.length - 1);
|
|
22022
22256
|
}
|
|
22023
|
-
if (
|
|
22024
|
-
|
|
22257
|
+
if (path72 && path72[0] !== "/") {
|
|
22258
|
+
path72 = `/${path72}`;
|
|
22025
22259
|
}
|
|
22026
|
-
return new URL(`${origin}${
|
|
22260
|
+
return new URL(`${origin}${path72}`);
|
|
22027
22261
|
}
|
|
22028
22262
|
if (!isHttpOrHttpsPrefixed(url.origin || url.protocol)) {
|
|
22029
22263
|
throw new InvalidArgumentError("Invalid URL protocol: the URL must start with `http:` or `https:`.");
|
|
@@ -22844,9 +23078,9 @@ var require_diagnostics = __commonJS({
|
|
|
22844
23078
|
"undici:client:sendHeaders",
|
|
22845
23079
|
(evt) => {
|
|
22846
23080
|
const {
|
|
22847
|
-
request: { method, path:
|
|
23081
|
+
request: { method, path: path72, origin }
|
|
22848
23082
|
} = evt;
|
|
22849
|
-
debugLog("sending request to %s %s%s", method, origin,
|
|
23083
|
+
debugLog("sending request to %s %s%s", method, origin, path72);
|
|
22850
23084
|
}
|
|
22851
23085
|
);
|
|
22852
23086
|
}
|
|
@@ -22864,14 +23098,14 @@ var require_diagnostics = __commonJS({
|
|
|
22864
23098
|
"undici:request:headers",
|
|
22865
23099
|
(evt) => {
|
|
22866
23100
|
const {
|
|
22867
|
-
request: { method, path:
|
|
23101
|
+
request: { method, path: path72, origin },
|
|
22868
23102
|
response: { statusCode }
|
|
22869
23103
|
} = evt;
|
|
22870
23104
|
debugLog(
|
|
22871
23105
|
"received response to %s %s%s - HTTP %d",
|
|
22872
23106
|
method,
|
|
22873
23107
|
origin,
|
|
22874
|
-
|
|
23108
|
+
path72,
|
|
22875
23109
|
statusCode
|
|
22876
23110
|
);
|
|
22877
23111
|
}
|
|
@@ -22880,23 +23114,23 @@ var require_diagnostics = __commonJS({
|
|
|
22880
23114
|
"undici:request:trailers",
|
|
22881
23115
|
(evt) => {
|
|
22882
23116
|
const {
|
|
22883
|
-
request: { method, path:
|
|
23117
|
+
request: { method, path: path72, origin }
|
|
22884
23118
|
} = evt;
|
|
22885
|
-
debugLog("trailers received from %s %s%s", method, origin,
|
|
23119
|
+
debugLog("trailers received from %s %s%s", method, origin, path72);
|
|
22886
23120
|
}
|
|
22887
23121
|
);
|
|
22888
23122
|
diagnosticsChannel.subscribe(
|
|
22889
23123
|
"undici:request:error",
|
|
22890
23124
|
(evt) => {
|
|
22891
23125
|
const {
|
|
22892
|
-
request: { method, path:
|
|
23126
|
+
request: { method, path: path72, origin },
|
|
22893
23127
|
error
|
|
22894
23128
|
} = evt;
|
|
22895
23129
|
debugLog(
|
|
22896
23130
|
"request to %s %s%s errored - %s",
|
|
22897
23131
|
method,
|
|
22898
23132
|
origin,
|
|
22899
|
-
|
|
23133
|
+
path72,
|
|
22900
23134
|
error.message
|
|
22901
23135
|
);
|
|
22902
23136
|
}
|
|
@@ -22999,7 +23233,7 @@ var require_request = __commonJS({
|
|
|
22999
23233
|
var kHandler = /* @__PURE__ */ Symbol("handler");
|
|
23000
23234
|
var Request = class {
|
|
23001
23235
|
constructor(origin, {
|
|
23002
|
-
path:
|
|
23236
|
+
path: path72,
|
|
23003
23237
|
method,
|
|
23004
23238
|
body,
|
|
23005
23239
|
headers,
|
|
@@ -23016,11 +23250,11 @@ var require_request = __commonJS({
|
|
|
23016
23250
|
maxRedirections,
|
|
23017
23251
|
typeOfService
|
|
23018
23252
|
}, handler) {
|
|
23019
|
-
if (typeof
|
|
23253
|
+
if (typeof path72 !== "string") {
|
|
23020
23254
|
throw new InvalidArgumentError("path must be a string");
|
|
23021
|
-
} else if (
|
|
23255
|
+
} else if (path72[0] !== "/" && !(path72.startsWith("http://") || path72.startsWith("https://")) && method !== "CONNECT") {
|
|
23022
23256
|
throw new InvalidArgumentError("path must be an absolute URL or start with a slash");
|
|
23023
|
-
} else if (invalidPathRegex.test(
|
|
23257
|
+
} else if (invalidPathRegex.test(path72)) {
|
|
23024
23258
|
throw new InvalidArgumentError("invalid request path");
|
|
23025
23259
|
}
|
|
23026
23260
|
if (typeof method !== "string") {
|
|
@@ -23095,7 +23329,7 @@ var require_request = __commonJS({
|
|
|
23095
23329
|
this.completed = false;
|
|
23096
23330
|
this.aborted = false;
|
|
23097
23331
|
this.upgrade = upgrade || null;
|
|
23098
|
-
this.path = query ? serializePathWithQuery(
|
|
23332
|
+
this.path = query ? serializePathWithQuery(path72, query) : path72;
|
|
23099
23333
|
this.origin = origin;
|
|
23100
23334
|
this.protocol = getProtocolFromUrlString(origin);
|
|
23101
23335
|
this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent;
|
|
@@ -28134,7 +28368,7 @@ var require_client_h1 = __commonJS({
|
|
|
28134
28368
|
return method !== "GET" && method !== "HEAD" && method !== "OPTIONS" && method !== "TRACE" && method !== "CONNECT";
|
|
28135
28369
|
}
|
|
28136
28370
|
function writeH1(client, request2) {
|
|
28137
|
-
const { method, path:
|
|
28371
|
+
const { method, path: path72, host, upgrade, blocking, reset } = request2;
|
|
28138
28372
|
let { body, headers, contentLength } = request2;
|
|
28139
28373
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH" || method === "QUERY" || method === "PROPFIND" || method === "PROPPATCH";
|
|
28140
28374
|
if (util.isFormDataLike(body)) {
|
|
@@ -28203,7 +28437,7 @@ var require_client_h1 = __commonJS({
|
|
|
28203
28437
|
if (socket.setTypeOfService) {
|
|
28204
28438
|
socket.setTypeOfService(request2.typeOfService);
|
|
28205
28439
|
}
|
|
28206
|
-
let header = `${method} ${
|
|
28440
|
+
let header = `${method} ${path72} HTTP/1.1\r
|
|
28207
28441
|
`;
|
|
28208
28442
|
if (typeof host === "string") {
|
|
28209
28443
|
header += `host: ${host}\r
|
|
@@ -28856,7 +29090,7 @@ var require_client_h2 = __commonJS({
|
|
|
28856
29090
|
function writeH2(client, request2) {
|
|
28857
29091
|
const requestTimeout = request2.bodyTimeout ?? client[kBodyTimeout];
|
|
28858
29092
|
const session = client[kHTTP2Session];
|
|
28859
|
-
const { method, path:
|
|
29093
|
+
const { method, path: path72, host, upgrade, expectContinue, signal, protocol, headers: reqHeaders } = request2;
|
|
28860
29094
|
let { body } = request2;
|
|
28861
29095
|
if (upgrade != null && upgrade !== "websocket") {
|
|
28862
29096
|
util.errorRequest(client, request2, new InvalidArgumentError(`Custom upgrade "${upgrade}" not supported over HTTP/2`));
|
|
@@ -28924,7 +29158,7 @@ var require_client_h2 = __commonJS({
|
|
|
28924
29158
|
}
|
|
28925
29159
|
headers[HTTP2_HEADER_METHOD] = "CONNECT";
|
|
28926
29160
|
headers[HTTP2_HEADER_PROTOCOL] = "websocket";
|
|
28927
|
-
headers[HTTP2_HEADER_PATH] =
|
|
29161
|
+
headers[HTTP2_HEADER_PATH] = path72;
|
|
28928
29162
|
if (protocol === "ws:" || protocol === "wss:") {
|
|
28929
29163
|
headers[HTTP2_HEADER_SCHEME] = protocol === "ws:" ? "http" : "https";
|
|
28930
29164
|
} else {
|
|
@@ -28965,7 +29199,7 @@ var require_client_h2 = __commonJS({
|
|
|
28965
29199
|
stream.setTimeout(requestTimeout);
|
|
28966
29200
|
return true;
|
|
28967
29201
|
}
|
|
28968
|
-
headers[HTTP2_HEADER_PATH] =
|
|
29202
|
+
headers[HTTP2_HEADER_PATH] = path72;
|
|
28969
29203
|
headers[HTTP2_HEADER_SCHEME] = protocol === "http:" ? "http" : "https";
|
|
28970
29204
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
|
|
28971
29205
|
if (body && typeof body.read === "function") {
|
|
@@ -31267,10 +31501,10 @@ var require_proxy_agent = __commonJS({
|
|
|
31267
31501
|
};
|
|
31268
31502
|
const {
|
|
31269
31503
|
origin,
|
|
31270
|
-
path:
|
|
31504
|
+
path: path72 = "/",
|
|
31271
31505
|
headers = {}
|
|
31272
31506
|
} = opts;
|
|
31273
|
-
opts.path = origin +
|
|
31507
|
+
opts.path = origin + path72;
|
|
31274
31508
|
if (!("host" in headers) && !("Host" in headers)) {
|
|
31275
31509
|
const { host } = new URL(origin);
|
|
31276
31510
|
headers.host = host;
|
|
@@ -33333,20 +33567,20 @@ var require_mock_utils = __commonJS({
|
|
|
33333
33567
|
}
|
|
33334
33568
|
return normalizedQp;
|
|
33335
33569
|
}
|
|
33336
|
-
function safeUrl(
|
|
33337
|
-
if (typeof
|
|
33338
|
-
return
|
|
33570
|
+
function safeUrl(path72) {
|
|
33571
|
+
if (typeof path72 !== "string") {
|
|
33572
|
+
return path72;
|
|
33339
33573
|
}
|
|
33340
|
-
const pathSegments =
|
|
33574
|
+
const pathSegments = path72.split("?", 3);
|
|
33341
33575
|
if (pathSegments.length !== 2) {
|
|
33342
|
-
return
|
|
33576
|
+
return path72;
|
|
33343
33577
|
}
|
|
33344
33578
|
const qp = new URLSearchParams(pathSegments.pop());
|
|
33345
33579
|
qp.sort();
|
|
33346
33580
|
return [...pathSegments, qp.toString()].join("?");
|
|
33347
33581
|
}
|
|
33348
|
-
function matchKey(mockDispatch2, { path:
|
|
33349
|
-
const pathMatch = matchValue(mockDispatch2.path,
|
|
33582
|
+
function matchKey(mockDispatch2, { path: path72, method, body, headers }) {
|
|
33583
|
+
const pathMatch = matchValue(mockDispatch2.path, path72);
|
|
33350
33584
|
const methodMatch = matchValue(mockDispatch2.method, method);
|
|
33351
33585
|
const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body) : true;
|
|
33352
33586
|
const headersMatch = matchHeaders(mockDispatch2, headers);
|
|
@@ -33371,8 +33605,8 @@ var require_mock_utils = __commonJS({
|
|
|
33371
33605
|
const basePath = key.query ? serializePathWithQuery(key.path, key.query) : key.path;
|
|
33372
33606
|
const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath;
|
|
33373
33607
|
const resolvedPathWithoutTrailingSlash = removeTrailingSlash(resolvedPath);
|
|
33374
|
-
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path:
|
|
33375
|
-
return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(
|
|
33608
|
+
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path72, ignoreTrailingSlash }) => {
|
|
33609
|
+
return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(path72)), resolvedPathWithoutTrailingSlash) : matchValue(safeUrl(path72), resolvedPath);
|
|
33376
33610
|
});
|
|
33377
33611
|
if (matchedMockDispatches.length === 0) {
|
|
33378
33612
|
throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`);
|
|
@@ -33411,19 +33645,19 @@ var require_mock_utils = __commonJS({
|
|
|
33411
33645
|
mockDispatches.splice(index, 1);
|
|
33412
33646
|
}
|
|
33413
33647
|
}
|
|
33414
|
-
function removeTrailingSlash(
|
|
33415
|
-
while (
|
|
33416
|
-
|
|
33648
|
+
function removeTrailingSlash(path72) {
|
|
33649
|
+
while (path72.endsWith("/")) {
|
|
33650
|
+
path72 = path72.slice(0, -1);
|
|
33417
33651
|
}
|
|
33418
|
-
if (
|
|
33419
|
-
|
|
33652
|
+
if (path72.length === 0) {
|
|
33653
|
+
path72 = "/";
|
|
33420
33654
|
}
|
|
33421
|
-
return
|
|
33655
|
+
return path72;
|
|
33422
33656
|
}
|
|
33423
33657
|
function buildKey(opts) {
|
|
33424
|
-
const { path:
|
|
33658
|
+
const { path: path72, method, body, headers, query } = opts;
|
|
33425
33659
|
return {
|
|
33426
|
-
path:
|
|
33660
|
+
path: path72,
|
|
33427
33661
|
method,
|
|
33428
33662
|
body,
|
|
33429
33663
|
headers,
|
|
@@ -34113,10 +34347,10 @@ var require_pending_interceptors_formatter = __commonJS({
|
|
|
34113
34347
|
}
|
|
34114
34348
|
format(pendingInterceptors) {
|
|
34115
34349
|
const withPrettyHeaders = pendingInterceptors.map(
|
|
34116
|
-
({ method, path:
|
|
34350
|
+
({ method, path: path72, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
|
|
34117
34351
|
Method: method,
|
|
34118
34352
|
Origin: origin,
|
|
34119
|
-
Path:
|
|
34353
|
+
Path: path72,
|
|
34120
34354
|
"Status code": statusCode,
|
|
34121
34355
|
Persistent: persist ? PERSISTENT : NOT_PERSISTENT,
|
|
34122
34356
|
Invocations: timesInvoked,
|
|
@@ -34198,9 +34432,9 @@ var require_mock_agent = __commonJS({
|
|
|
34198
34432
|
const acceptNonStandardSearchParameters = this[kMockAgentAcceptsNonStandardSearchParameters];
|
|
34199
34433
|
const dispatchOpts = { ...opts };
|
|
34200
34434
|
if (acceptNonStandardSearchParameters && dispatchOpts.path) {
|
|
34201
|
-
const [
|
|
34435
|
+
const [path72, searchParams] = dispatchOpts.path.split("?");
|
|
34202
34436
|
const normalizedSearchParams = normalizeSearchParams(searchParams, acceptNonStandardSearchParameters);
|
|
34203
|
-
dispatchOpts.path = `${
|
|
34437
|
+
dispatchOpts.path = `${path72}?${normalizedSearchParams}`;
|
|
34204
34438
|
}
|
|
34205
34439
|
return this[kAgent].dispatch(dispatchOpts, handler);
|
|
34206
34440
|
}
|
|
@@ -34601,12 +34835,12 @@ var require_snapshot_recorder = __commonJS({
|
|
|
34601
34835
|
* @return {Promise<void>} - Resolves when snapshots are loaded
|
|
34602
34836
|
*/
|
|
34603
34837
|
async loadSnapshots(filePath) {
|
|
34604
|
-
const
|
|
34605
|
-
if (!
|
|
34838
|
+
const path72 = filePath || this.#snapshotPath;
|
|
34839
|
+
if (!path72) {
|
|
34606
34840
|
throw new InvalidArgumentError("Snapshot path is required");
|
|
34607
34841
|
}
|
|
34608
34842
|
try {
|
|
34609
|
-
const data = await readFile(resolve2(
|
|
34843
|
+
const data = await readFile(resolve2(path72), "utf8");
|
|
34610
34844
|
const parsed = JSON.parse(data);
|
|
34611
34845
|
if (Array.isArray(parsed)) {
|
|
34612
34846
|
this.#snapshots.clear();
|
|
@@ -34620,7 +34854,7 @@ var require_snapshot_recorder = __commonJS({
|
|
|
34620
34854
|
if (error.code === "ENOENT") {
|
|
34621
34855
|
this.#snapshots.clear();
|
|
34622
34856
|
} else {
|
|
34623
|
-
throw new UndiciError(`Failed to load snapshots from ${
|
|
34857
|
+
throw new UndiciError(`Failed to load snapshots from ${path72}`, { cause: error });
|
|
34624
34858
|
}
|
|
34625
34859
|
}
|
|
34626
34860
|
}
|
|
@@ -34631,11 +34865,11 @@ var require_snapshot_recorder = __commonJS({
|
|
|
34631
34865
|
* @returns {Promise<void>} - Resolves when snapshots are saved
|
|
34632
34866
|
*/
|
|
34633
34867
|
async saveSnapshots(filePath) {
|
|
34634
|
-
const
|
|
34635
|
-
if (!
|
|
34868
|
+
const path72 = filePath || this.#snapshotPath;
|
|
34869
|
+
if (!path72) {
|
|
34636
34870
|
throw new InvalidArgumentError("Snapshot path is required");
|
|
34637
34871
|
}
|
|
34638
|
-
const resolvedPath = resolve2(
|
|
34872
|
+
const resolvedPath = resolve2(path72);
|
|
34639
34873
|
await mkdir(dirname2(resolvedPath), { recursive: true });
|
|
34640
34874
|
const data = Array.from(this.#snapshots.entries()).map(([hash, snapshot]) => ({
|
|
34641
34875
|
hash,
|
|
@@ -35260,15 +35494,15 @@ var require_redirect_handler = __commonJS({
|
|
|
35260
35494
|
return;
|
|
35261
35495
|
}
|
|
35262
35496
|
const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin)));
|
|
35263
|
-
const
|
|
35264
|
-
const redirectUrlString = `${origin}${
|
|
35497
|
+
const path72 = search ? `${pathname}${search}` : pathname;
|
|
35498
|
+
const redirectUrlString = `${origin}${path72}`;
|
|
35265
35499
|
for (const historyUrl of this.history) {
|
|
35266
35500
|
if (historyUrl.toString() === redirectUrlString) {
|
|
35267
35501
|
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.`);
|
|
35268
35502
|
}
|
|
35269
35503
|
}
|
|
35270
35504
|
this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin);
|
|
35271
|
-
this.opts.path =
|
|
35505
|
+
this.opts.path = path72;
|
|
35272
35506
|
this.opts.origin = origin;
|
|
35273
35507
|
this.opts.query = null;
|
|
35274
35508
|
}
|
|
@@ -41475,11 +41709,11 @@ var require_fetch = __commonJS({
|
|
|
41475
41709
|
function dispatch({ body }) {
|
|
41476
41710
|
const url = requestCurrentURL(request2);
|
|
41477
41711
|
const agent = fetchParams.controller.dispatcher;
|
|
41478
|
-
const
|
|
41712
|
+
const path72 = url.pathname + url.search;
|
|
41479
41713
|
const hasTrailingQuestionMark = url.search.length === 0 && url.href[url.href.length - url.hash.length - 1] === "?";
|
|
41480
41714
|
return new Promise((resolve2, reject) => agent.dispatch(
|
|
41481
41715
|
{
|
|
41482
|
-
path: hasTrailingQuestionMark ? `${
|
|
41716
|
+
path: hasTrailingQuestionMark ? `${path72}?` : path72,
|
|
41483
41717
|
origin: url.origin,
|
|
41484
41718
|
method: request2.method,
|
|
41485
41719
|
body: agent.isMockActive ? request2.body && (request2.body.source || request2.body.stream) : body,
|
|
@@ -42410,9 +42644,9 @@ var require_util4 = __commonJS({
|
|
|
42410
42644
|
}
|
|
42411
42645
|
}
|
|
42412
42646
|
}
|
|
42413
|
-
function validateCookiePath(
|
|
42414
|
-
for (let i = 0; i <
|
|
42415
|
-
const code =
|
|
42647
|
+
function validateCookiePath(path72) {
|
|
42648
|
+
for (let i = 0; i < path72.length; ++i) {
|
|
42649
|
+
const code = path72.charCodeAt(i);
|
|
42416
42650
|
if (code < 32 || // exclude CTLs (0-31)
|
|
42417
42651
|
code === 127 || // DEL
|
|
42418
42652
|
code === 59) {
|
|
@@ -45582,11 +45816,11 @@ var require_undici = __commonJS({
|
|
|
45582
45816
|
if (typeof opts.path !== "string") {
|
|
45583
45817
|
throw new InvalidArgumentError("invalid opts.path");
|
|
45584
45818
|
}
|
|
45585
|
-
let
|
|
45819
|
+
let path72 = opts.path;
|
|
45586
45820
|
if (!opts.path.startsWith("/")) {
|
|
45587
|
-
|
|
45821
|
+
path72 = `/${path72}`;
|
|
45588
45822
|
}
|
|
45589
|
-
url = new URL(util.parseOrigin(url).origin +
|
|
45823
|
+
url = new URL(util.parseOrigin(url).origin + path72);
|
|
45590
45824
|
} else {
|
|
45591
45825
|
if (!opts) {
|
|
45592
45826
|
opts = typeof url === "object" ? url : {};
|
|
@@ -45699,10 +45933,14 @@ ${captureLines}` : capture.stack;
|
|
|
45699
45933
|
var tail_exports = {};
|
|
45700
45934
|
__export(tail_exports, {
|
|
45701
45935
|
agentLabel: () => agentLabel,
|
|
45936
|
+
eventsUrl: () => eventsUrl,
|
|
45702
45937
|
sessionTag: () => sessionTag,
|
|
45703
45938
|
shortenPathSummary: () => shortenPathSummary,
|
|
45704
45939
|
startTail: () => startTail
|
|
45705
45940
|
});
|
|
45941
|
+
function eventsUrl(port, canApprove) {
|
|
45942
|
+
return `http://127.0.0.1:${port}/events${canApprove ? "?capabilities=input" : ""}`;
|
|
45943
|
+
}
|
|
45706
45944
|
function shortenPathSummary(s) {
|
|
45707
45945
|
if (!s || !s.startsWith("/")) return s;
|
|
45708
45946
|
const parts = s.split("/").filter(Boolean);
|
|
@@ -45724,20 +45962,20 @@ function getModelContextLimit(model) {
|
|
|
45724
45962
|
return 2e5;
|
|
45725
45963
|
}
|
|
45726
45964
|
function readSessionUsage() {
|
|
45727
|
-
const projectsDir =
|
|
45728
|
-
if (!
|
|
45965
|
+
const projectsDir = import_path68.default.join(import_os60.default.homedir(), ".claude", "projects");
|
|
45966
|
+
if (!import_fs72.default.existsSync(projectsDir)) return null;
|
|
45729
45967
|
let latestFile = null;
|
|
45730
45968
|
let latestMtime = 0;
|
|
45731
45969
|
try {
|
|
45732
|
-
for (const dir of
|
|
45733
|
-
const dirPath =
|
|
45970
|
+
for (const dir of import_fs72.default.readdirSync(projectsDir)) {
|
|
45971
|
+
const dirPath = import_path68.default.join(projectsDir, dir);
|
|
45734
45972
|
try {
|
|
45735
|
-
if (!
|
|
45736
|
-
for (const file of
|
|
45973
|
+
if (!import_fs72.default.statSync(dirPath).isDirectory()) continue;
|
|
45974
|
+
for (const file of import_fs72.default.readdirSync(dirPath)) {
|
|
45737
45975
|
if (!file.endsWith(".jsonl") || file.startsWith("agent-")) continue;
|
|
45738
|
-
const filePath =
|
|
45976
|
+
const filePath = import_path68.default.join(dirPath, file);
|
|
45739
45977
|
try {
|
|
45740
|
-
const mtime =
|
|
45978
|
+
const mtime = import_fs72.default.statSync(filePath).mtimeMs;
|
|
45741
45979
|
if (mtime > latestMtime) {
|
|
45742
45980
|
latestMtime = mtime;
|
|
45743
45981
|
latestFile = filePath;
|
|
@@ -45752,7 +45990,7 @@ function readSessionUsage() {
|
|
|
45752
45990
|
}
|
|
45753
45991
|
if (!latestFile) return null;
|
|
45754
45992
|
try {
|
|
45755
|
-
const lines =
|
|
45993
|
+
const lines = import_fs72.default.readFileSync(latestFile, "utf-8").split("\n");
|
|
45756
45994
|
let lastModel = "";
|
|
45757
45995
|
let lastInput = 0;
|
|
45758
45996
|
let lastOutput = 0;
|
|
@@ -45852,9 +46090,9 @@ function renderPending(activity) {
|
|
|
45852
46090
|
}
|
|
45853
46091
|
async function ensureDaemon() {
|
|
45854
46092
|
let pidPort = null;
|
|
45855
|
-
if (
|
|
46093
|
+
if (import_fs72.default.existsSync(PID_FILE)) {
|
|
45856
46094
|
try {
|
|
45857
|
-
const { port } = JSON.parse(
|
|
46095
|
+
const { port } = JSON.parse(import_fs72.default.readFileSync(PID_FILE, "utf-8"));
|
|
45858
46096
|
pidPort = port;
|
|
45859
46097
|
} catch {
|
|
45860
46098
|
console.error(import_chalk40.default.dim("\u26A0\uFE0F Could not read PID file; falling back to default port."));
|
|
@@ -45880,7 +46118,7 @@ async function ensureDaemon() {
|
|
|
45880
46118
|
child.unref();
|
|
45881
46119
|
if (startupFd !== void 0) {
|
|
45882
46120
|
try {
|
|
45883
|
-
|
|
46121
|
+
import_fs72.default.closeSync(startupFd);
|
|
45884
46122
|
} catch {
|
|
45885
46123
|
}
|
|
45886
46124
|
}
|
|
@@ -46019,9 +46257,9 @@ function buildRecoveryCardLines(req) {
|
|
|
46019
46257
|
];
|
|
46020
46258
|
}
|
|
46021
46259
|
function readApproversFromDisk() {
|
|
46022
|
-
const configPath =
|
|
46260
|
+
const configPath = import_path68.default.join(import_os60.default.homedir(), ".node9", "config.json");
|
|
46023
46261
|
try {
|
|
46024
|
-
const raw = JSON.parse(
|
|
46262
|
+
const raw = JSON.parse(import_fs72.default.readFileSync(configPath, "utf-8"));
|
|
46025
46263
|
const settings = raw.settings ?? {};
|
|
46026
46264
|
return settings.approvers ?? {};
|
|
46027
46265
|
} catch {
|
|
@@ -46037,15 +46275,15 @@ function approverStatusLine() {
|
|
|
46037
46275
|
return `${fmt("native", "native")} ${fmt("cloud", "cloud")} ${fmt("terminal", "terminal")}`;
|
|
46038
46276
|
}
|
|
46039
46277
|
function toggleApprover(channel) {
|
|
46040
|
-
const configPath =
|
|
46278
|
+
const configPath = import_path68.default.join(import_os60.default.homedir(), ".node9", "config.json");
|
|
46041
46279
|
try {
|
|
46042
|
-
const raw = JSON.parse(
|
|
46280
|
+
const raw = JSON.parse(import_fs72.default.readFileSync(configPath, "utf-8"));
|
|
46043
46281
|
const settings = raw.settings ?? {};
|
|
46044
46282
|
const approvers = settings.approvers ?? {};
|
|
46045
46283
|
approvers[channel] = approvers[channel] === false;
|
|
46046
46284
|
settings.approvers = approvers;
|
|
46047
46285
|
raw.settings = settings;
|
|
46048
|
-
|
|
46286
|
+
import_fs72.default.writeFileSync(configPath, JSON.stringify(raw, null, 2) + "\n");
|
|
46049
46287
|
} catch (err2) {
|
|
46050
46288
|
process.stderr.write(`[node9] toggleApprover failed: ${String(err2)}
|
|
46051
46289
|
`);
|
|
@@ -46217,8 +46455,8 @@ async function startTail(options = {}) {
|
|
|
46217
46455
|
}
|
|
46218
46456
|
postDecisionHttp(req2.id, httpDecision, authToken, port, httpOpts).catch((err2) => {
|
|
46219
46457
|
try {
|
|
46220
|
-
|
|
46221
|
-
|
|
46458
|
+
import_fs72.default.appendFileSync(
|
|
46459
|
+
import_path68.default.join(import_os60.default.homedir(), ".node9", "hook-debug.log"),
|
|
46222
46460
|
`[tail] POST /decision failed: ${String(err2)}
|
|
46223
46461
|
`
|
|
46224
46462
|
);
|
|
@@ -46282,9 +46520,9 @@ async function startTail(options = {}) {
|
|
|
46282
46520
|
};
|
|
46283
46521
|
process.stdin.on("keypress", onKeypress);
|
|
46284
46522
|
}
|
|
46285
|
-
const auditLog =
|
|
46523
|
+
const auditLog = import_path68.default.join(import_os60.default.homedir(), ".node9", "audit.log");
|
|
46286
46524
|
try {
|
|
46287
|
-
const unackedDlp =
|
|
46525
|
+
const unackedDlp = import_fs72.default.readFileSync(auditLog, "utf-8").split("\n").filter((l) => l.includes('"response-dlp"')).length;
|
|
46288
46526
|
if (unackedDlp > 0) {
|
|
46289
46527
|
console.log("");
|
|
46290
46528
|
console.log(
|
|
@@ -46324,7 +46562,7 @@ async function startTail(options = {}) {
|
|
|
46324
46562
|
if (stallWarned) return;
|
|
46325
46563
|
if (Date.now() - lastActivityFromDaemon < STALL_THRESHOLD_MS) return;
|
|
46326
46564
|
try {
|
|
46327
|
-
const auditMtime =
|
|
46565
|
+
const auditMtime = import_fs72.default.statSync(auditLog).mtimeMs;
|
|
46328
46566
|
if (Date.now() - auditMtime >= STALL_THRESHOLD_MS) return;
|
|
46329
46567
|
console.log("");
|
|
46330
46568
|
console.log(
|
|
@@ -46337,7 +46575,7 @@ async function startTail(options = {}) {
|
|
|
46337
46575
|
}
|
|
46338
46576
|
}, STALL_THRESHOLD_MS / 2);
|
|
46339
46577
|
stallWatchdog.unref();
|
|
46340
|
-
const sseUrl =
|
|
46578
|
+
const sseUrl = eventsUrl(port, canApprove);
|
|
46341
46579
|
const req = import_http5.default.get(
|
|
46342
46580
|
sseUrl,
|
|
46343
46581
|
{
|
|
@@ -46509,21 +46747,21 @@ async function startTail(options = {}) {
|
|
|
46509
46747
|
process.exit(1);
|
|
46510
46748
|
});
|
|
46511
46749
|
}
|
|
46512
|
-
var import_http5, import_chalk40,
|
|
46750
|
+
var import_http5, import_chalk40, import_fs72, import_os60, import_path68, import_readline6, import_child_process14, PID_FILE, ICONS, MODEL_CONTEXT_LIMITS, RESET2, BOLD2, RED, YELLOW, CYAN, GRAY, GREEN, HIDE_CURSOR, SHOW_CURSOR, ERASE_DOWN, pendingShownForId, pendingWrappedLines, DIVIDER;
|
|
46513
46751
|
var init_tail = __esm({
|
|
46514
46752
|
"src/tui/tail.ts"() {
|
|
46515
46753
|
"use strict";
|
|
46516
46754
|
import_http5 = __toESM(require("http"));
|
|
46517
46755
|
import_chalk40 = __toESM(require("chalk"));
|
|
46518
|
-
|
|
46756
|
+
import_fs72 = __toESM(require("fs"));
|
|
46519
46757
|
import_os60 = __toESM(require("os"));
|
|
46520
|
-
|
|
46758
|
+
import_path68 = __toESM(require("path"));
|
|
46521
46759
|
import_readline6 = __toESM(require("readline"));
|
|
46522
46760
|
import_child_process14 = require("child_process");
|
|
46523
46761
|
init_startup_log();
|
|
46524
46762
|
init_daemon2();
|
|
46525
46763
|
init_daemon();
|
|
46526
|
-
PID_FILE =
|
|
46764
|
+
PID_FILE = import_path68.default.join(import_os60.default.homedir(), ".node9", "daemon.pid");
|
|
46527
46765
|
ICONS = {
|
|
46528
46766
|
bash: "\u{1F4BB}",
|
|
46529
46767
|
shell: "\u{1F4BB}",
|
|
@@ -46645,9 +46883,9 @@ function formatTimeLeft(resetsAt) {
|
|
|
46645
46883
|
return ` (${m}m left)`;
|
|
46646
46884
|
}
|
|
46647
46885
|
function safeReadJson(filePath) {
|
|
46648
|
-
if (!
|
|
46886
|
+
if (!import_fs73.default.existsSync(filePath)) return null;
|
|
46649
46887
|
try {
|
|
46650
|
-
return JSON.parse(
|
|
46888
|
+
return JSON.parse(import_fs73.default.readFileSync(filePath, "utf-8"));
|
|
46651
46889
|
} catch {
|
|
46652
46890
|
return null;
|
|
46653
46891
|
}
|
|
@@ -46668,12 +46906,12 @@ function countHooksInFile(filePath) {
|
|
|
46668
46906
|
return Object.keys(cfg.hooks).length;
|
|
46669
46907
|
}
|
|
46670
46908
|
function countRulesInDir(rulesDir) {
|
|
46671
|
-
if (!
|
|
46909
|
+
if (!import_fs73.default.existsSync(rulesDir)) return 0;
|
|
46672
46910
|
let count = 0;
|
|
46673
46911
|
try {
|
|
46674
|
-
for (const entry of
|
|
46912
|
+
for (const entry of import_fs73.default.readdirSync(rulesDir, { withFileTypes: true })) {
|
|
46675
46913
|
if (entry.isDirectory()) {
|
|
46676
|
-
count += countRulesInDir(
|
|
46914
|
+
count += countRulesInDir(import_path69.default.join(rulesDir, entry.name));
|
|
46677
46915
|
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
46678
46916
|
count++;
|
|
46679
46917
|
}
|
|
@@ -46684,46 +46922,46 @@ function countRulesInDir(rulesDir) {
|
|
|
46684
46922
|
}
|
|
46685
46923
|
function isSamePath(a, b) {
|
|
46686
46924
|
try {
|
|
46687
|
-
return
|
|
46925
|
+
return import_path69.default.resolve(a) === import_path69.default.resolve(b);
|
|
46688
46926
|
} catch {
|
|
46689
46927
|
return false;
|
|
46690
46928
|
}
|
|
46691
46929
|
}
|
|
46692
46930
|
function countConfigs(cwd) {
|
|
46693
46931
|
const homeDir2 = import_os61.default.homedir();
|
|
46694
|
-
const claudeDir =
|
|
46932
|
+
const claudeDir = import_path69.default.join(homeDir2, ".claude");
|
|
46695
46933
|
let claudeMdCount = 0;
|
|
46696
46934
|
let rulesCount = 0;
|
|
46697
46935
|
let hooksCount = 0;
|
|
46698
46936
|
const userMcpServers = /* @__PURE__ */ new Set();
|
|
46699
46937
|
const projectMcpServers = /* @__PURE__ */ new Set();
|
|
46700
|
-
if (
|
|
46701
|
-
rulesCount += countRulesInDir(
|
|
46702
|
-
const userSettings =
|
|
46938
|
+
if (import_fs73.default.existsSync(import_path69.default.join(claudeDir, "CLAUDE.md"))) claudeMdCount++;
|
|
46939
|
+
rulesCount += countRulesInDir(import_path69.default.join(claudeDir, "rules"));
|
|
46940
|
+
const userSettings = import_path69.default.join(claudeDir, "settings.json");
|
|
46703
46941
|
for (const name of getMcpServerNames(userSettings)) userMcpServers.add(name);
|
|
46704
46942
|
hooksCount += countHooksInFile(userSettings);
|
|
46705
|
-
const userClaudeJson =
|
|
46943
|
+
const userClaudeJson = import_path69.default.join(homeDir2, ".claude.json");
|
|
46706
46944
|
for (const name of getMcpServerNames(userClaudeJson)) userMcpServers.add(name);
|
|
46707
46945
|
for (const name of getDisabledMcpServers(userClaudeJson, "disabledMcpServers")) {
|
|
46708
46946
|
userMcpServers.delete(name);
|
|
46709
46947
|
}
|
|
46710
46948
|
if (cwd) {
|
|
46711
|
-
if (
|
|
46712
|
-
if (
|
|
46713
|
-
const projectClaudeDir =
|
|
46949
|
+
if (import_fs73.default.existsSync(import_path69.default.join(cwd, "CLAUDE.md"))) claudeMdCount++;
|
|
46950
|
+
if (import_fs73.default.existsSync(import_path69.default.join(cwd, "CLAUDE.local.md"))) claudeMdCount++;
|
|
46951
|
+
const projectClaudeDir = import_path69.default.join(cwd, ".claude");
|
|
46714
46952
|
const overlapsUserScope = isSamePath(projectClaudeDir, claudeDir);
|
|
46715
46953
|
if (!overlapsUserScope) {
|
|
46716
|
-
if (
|
|
46717
|
-
rulesCount += countRulesInDir(
|
|
46718
|
-
const projSettings =
|
|
46954
|
+
if (import_fs73.default.existsSync(import_path69.default.join(projectClaudeDir, "CLAUDE.md"))) claudeMdCount++;
|
|
46955
|
+
rulesCount += countRulesInDir(import_path69.default.join(projectClaudeDir, "rules"));
|
|
46956
|
+
const projSettings = import_path69.default.join(projectClaudeDir, "settings.json");
|
|
46719
46957
|
for (const name of getMcpServerNames(projSettings)) projectMcpServers.add(name);
|
|
46720
46958
|
hooksCount += countHooksInFile(projSettings);
|
|
46721
46959
|
}
|
|
46722
|
-
if (
|
|
46723
|
-
const localSettings =
|
|
46960
|
+
if (import_fs73.default.existsSync(import_path69.default.join(projectClaudeDir, "CLAUDE.local.md"))) claudeMdCount++;
|
|
46961
|
+
const localSettings = import_path69.default.join(projectClaudeDir, "settings.local.json");
|
|
46724
46962
|
for (const name of getMcpServerNames(localSettings)) projectMcpServers.add(name);
|
|
46725
46963
|
hooksCount += countHooksInFile(localSettings);
|
|
46726
|
-
const mcpJsonServers = getMcpServerNames(
|
|
46964
|
+
const mcpJsonServers = getMcpServerNames(import_path69.default.join(cwd, ".mcp.json"));
|
|
46727
46965
|
const disabledMcpJson = getDisabledMcpServers(localSettings, "disabledMcpjsonServers");
|
|
46728
46966
|
for (const name of disabledMcpJson) mcpJsonServers.delete(name);
|
|
46729
46967
|
for (const name of mcpJsonServers) projectMcpServers.add(name);
|
|
@@ -46756,12 +46994,12 @@ function readActiveShieldsHud() {
|
|
|
46756
46994
|
return shieldsCache.value;
|
|
46757
46995
|
}
|
|
46758
46996
|
try {
|
|
46759
|
-
const shieldsPath =
|
|
46760
|
-
if (!
|
|
46997
|
+
const shieldsPath = import_path69.default.join(import_os61.default.homedir(), ".node9", "shields.json");
|
|
46998
|
+
if (!import_fs73.default.existsSync(shieldsPath)) {
|
|
46761
46999
|
shieldsCache = { value: [], ts: now };
|
|
46762
47000
|
return [];
|
|
46763
47001
|
}
|
|
46764
|
-
const parsed = JSON.parse(
|
|
47002
|
+
const parsed = JSON.parse(import_fs73.default.readFileSync(shieldsPath, "utf-8"));
|
|
46765
47003
|
if (!Array.isArray(parsed.active)) {
|
|
46766
47004
|
shieldsCache = { value: [], ts: now };
|
|
46767
47005
|
return [];
|
|
@@ -46863,17 +47101,17 @@ function renderContextLine(stdin) {
|
|
|
46863
47101
|
async function main() {
|
|
46864
47102
|
try {
|
|
46865
47103
|
const [stdin, daemonStatus2] = await Promise.all([readStdin(), queryDaemon()]);
|
|
46866
|
-
if (
|
|
47104
|
+
if (import_fs73.default.existsSync(import_path69.default.join(import_os61.default.homedir(), ".node9", "hud-debug"))) {
|
|
46867
47105
|
try {
|
|
46868
|
-
const logPath =
|
|
47106
|
+
const logPath = import_path69.default.join(import_os61.default.homedir(), ".node9", "hud-debug.log");
|
|
46869
47107
|
const MAX_LOG_SIZE = 10 * 1024 * 1024;
|
|
46870
47108
|
let size = 0;
|
|
46871
47109
|
try {
|
|
46872
|
-
size =
|
|
47110
|
+
size = import_fs73.default.statSync(logPath).size;
|
|
46873
47111
|
} catch {
|
|
46874
47112
|
}
|
|
46875
47113
|
if (size < MAX_LOG_SIZE) {
|
|
46876
|
-
|
|
47114
|
+
import_fs73.default.appendFileSync(
|
|
46877
47115
|
logPath,
|
|
46878
47116
|
JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), stdin }) + "\n"
|
|
46879
47117
|
);
|
|
@@ -46894,11 +47132,11 @@ async function main() {
|
|
|
46894
47132
|
try {
|
|
46895
47133
|
const cwd = stdin.cwd ?? process.cwd();
|
|
46896
47134
|
for (const configPath of [
|
|
46897
|
-
|
|
46898
|
-
|
|
47135
|
+
import_path69.default.join(cwd, "node9.config.json"),
|
|
47136
|
+
import_path69.default.join(import_os61.default.homedir(), ".node9", "config.json")
|
|
46899
47137
|
]) {
|
|
46900
|
-
if (!
|
|
46901
|
-
const cfg = JSON.parse(
|
|
47138
|
+
if (!import_fs73.default.existsSync(configPath)) continue;
|
|
47139
|
+
const cfg = JSON.parse(import_fs73.default.readFileSync(configPath, "utf-8"));
|
|
46902
47140
|
const hud = cfg.settings?.hud;
|
|
46903
47141
|
if (hud && "showEnvironmentCounts" in hud) return hud.showEnvironmentCounts !== false;
|
|
46904
47142
|
}
|
|
@@ -46916,12 +47154,12 @@ async function main() {
|
|
|
46916
47154
|
renderOffline();
|
|
46917
47155
|
}
|
|
46918
47156
|
}
|
|
46919
|
-
var
|
|
47157
|
+
var import_fs73, import_path69, import_os61, import_http6, RESET3, BOLD3, DIM, RED2, GREEN2, YELLOW2, BLUE, MAGENTA, CYAN2, WHITE, BAR_FILLED, BAR_EMPTY, BAR_WIDTH, shieldsCache, SHIELDS_CACHE_TTL_MS;
|
|
46920
47158
|
var init_hud = __esm({
|
|
46921
47159
|
"src/cli/hud.ts"() {
|
|
46922
47160
|
"use strict";
|
|
46923
|
-
|
|
46924
|
-
|
|
47161
|
+
import_fs73 = __toESM(require("fs"));
|
|
47162
|
+
import_path69 = __toESM(require("path"));
|
|
46925
47163
|
import_os61 = __toESM(require("os"));
|
|
46926
47164
|
import_http6 = __toESM(require("http"));
|
|
46927
47165
|
init_daemon();
|
|
@@ -47044,8 +47282,8 @@ function writeCredentialsAndConfig(apiKey, opts = {}) {
|
|
|
47044
47282
|
// src/cli.ts
|
|
47045
47283
|
init_daemon2();
|
|
47046
47284
|
var import_chalk41 = __toESM(require("chalk"));
|
|
47047
|
-
var
|
|
47048
|
-
var
|
|
47285
|
+
var import_fs74 = __toESM(require("fs"));
|
|
47286
|
+
var import_path70 = __toESM(require("path"));
|
|
47049
47287
|
var import_os62 = __toESM(require("os"));
|
|
47050
47288
|
var import_child_process15 = require("child_process");
|
|
47051
47289
|
var import_prompts2 = require("@inquirer/prompts");
|
|
@@ -47233,28 +47471,28 @@ async function runProxy(targetCommand) {
|
|
|
47233
47471
|
|
|
47234
47472
|
// src/cli/daemon-starter.ts
|
|
47235
47473
|
var import_child_process5 = require("child_process");
|
|
47236
|
-
var
|
|
47237
|
-
var
|
|
47474
|
+
var import_path42 = __toESM(require("path"));
|
|
47475
|
+
var import_fs44 = __toESM(require("fs"));
|
|
47238
47476
|
var import_os39 = __toESM(require("os"));
|
|
47239
47477
|
init_daemon();
|
|
47240
47478
|
init_startup_log();
|
|
47241
47479
|
function isTestingMode() {
|
|
47242
47480
|
return /^(1|true|yes)$/i.test(process.env.NODE9_TESTING ?? "");
|
|
47243
47481
|
}
|
|
47244
|
-
var SKIP_STAMP = () =>
|
|
47482
|
+
var SKIP_STAMP = () => import_path42.default.join(import_os39.default.homedir(), ".node9", ".autostart-skip-stamp");
|
|
47245
47483
|
var SKIP_THROTTLE_MS = 60 * 60 * 1e3;
|
|
47246
47484
|
function logAutostartSkipThrottled(reason) {
|
|
47247
47485
|
try {
|
|
47248
47486
|
const stamp = SKIP_STAMP();
|
|
47249
47487
|
try {
|
|
47250
|
-
if (Date.now() -
|
|
47488
|
+
if (Date.now() - import_fs44.default.statSync(stamp).mtimeMs < SKIP_THROTTLE_MS) return;
|
|
47251
47489
|
} catch {
|
|
47252
47490
|
}
|
|
47253
|
-
const dir =
|
|
47254
|
-
if (!
|
|
47255
|
-
|
|
47256
|
-
|
|
47257
|
-
|
|
47491
|
+
const dir = import_path42.default.join(import_os39.default.homedir(), ".node9");
|
|
47492
|
+
if (!import_fs44.default.existsSync(dir)) import_fs44.default.mkdirSync(dir, { recursive: true });
|
|
47493
|
+
import_fs44.default.writeFileSync(stamp, "", "utf-8");
|
|
47494
|
+
import_fs44.default.appendFileSync(
|
|
47495
|
+
import_path42.default.join(dir, "hook-debug.log"),
|
|
47258
47496
|
`[${(/* @__PURE__ */ new Date()).toISOString()}] daemon-autostart-skip: ${reason}
|
|
47259
47497
|
`,
|
|
47260
47498
|
"utf-8"
|
|
@@ -47263,11 +47501,20 @@ function logAutostartSkipThrottled(reason) {
|
|
|
47263
47501
|
}
|
|
47264
47502
|
}
|
|
47265
47503
|
async function autoStartDaemonAndWait() {
|
|
47504
|
+
let alreadyServing = false;
|
|
47505
|
+
try {
|
|
47506
|
+
alreadyServing = await isDaemonReachable();
|
|
47507
|
+
} catch {
|
|
47508
|
+
}
|
|
47509
|
+
if (alreadyServing) {
|
|
47510
|
+
logAutostartSkipThrottled("already-serving");
|
|
47511
|
+
return true;
|
|
47512
|
+
}
|
|
47266
47513
|
if (isTestingMode()) return false;
|
|
47267
|
-
if (!
|
|
47514
|
+
if (!import_path42.default.isAbsolute(process.argv[1])) return false;
|
|
47268
47515
|
let resolvedArgv1;
|
|
47269
47516
|
try {
|
|
47270
|
-
resolvedArgv1 =
|
|
47517
|
+
resolvedArgv1 = import_fs44.default.realpathSync(process.argv[1]);
|
|
47271
47518
|
} catch {
|
|
47272
47519
|
return false;
|
|
47273
47520
|
}
|
|
@@ -47305,7 +47552,7 @@ async function autoStartDaemonAndWait() {
|
|
|
47305
47552
|
} finally {
|
|
47306
47553
|
if (startupFd !== void 0) {
|
|
47307
47554
|
try {
|
|
47308
|
-
|
|
47555
|
+
import_fs44.default.closeSync(startupFd);
|
|
47309
47556
|
} catch {
|
|
47310
47557
|
}
|
|
47311
47558
|
}
|
|
@@ -47318,9 +47565,9 @@ init_service();
|
|
|
47318
47565
|
|
|
47319
47566
|
// src/cli/commands/check.ts
|
|
47320
47567
|
var import_chalk9 = __toESM(require("chalk"));
|
|
47321
|
-
var
|
|
47568
|
+
var import_fs48 = __toESM(require("fs"));
|
|
47322
47569
|
var import_child_process7 = require("child_process");
|
|
47323
|
-
var
|
|
47570
|
+
var import_path46 = __toESM(require("path"));
|
|
47324
47571
|
var import_os43 = __toESM(require("os"));
|
|
47325
47572
|
init_orchestrator();
|
|
47326
47573
|
init_state();
|
|
@@ -47332,11 +47579,11 @@ init_policy();
|
|
|
47332
47579
|
// src/undo.ts
|
|
47333
47580
|
var import_child_process6 = require("child_process");
|
|
47334
47581
|
var import_crypto12 = __toESM(require("crypto"));
|
|
47335
|
-
var
|
|
47582
|
+
var import_fs45 = __toESM(require("fs"));
|
|
47336
47583
|
var import_net3 = __toESM(require("net"));
|
|
47337
|
-
var
|
|
47584
|
+
var import_path43 = __toESM(require("path"));
|
|
47338
47585
|
var import_os40 = __toESM(require("os"));
|
|
47339
|
-
var ACTIVITY_SOCKET_PATH3 = process.platform === "win32" ? "\\\\.\\pipe\\node9-activity" :
|
|
47586
|
+
var ACTIVITY_SOCKET_PATH3 = process.platform === "win32" ? "\\\\.\\pipe\\node9-activity" : import_path43.default.join(import_os40.default.tmpdir(), "node9-activity.sock");
|
|
47340
47587
|
function notifySnapshotTaken(hash, tool, argsSummary, fileCount) {
|
|
47341
47588
|
try {
|
|
47342
47589
|
const payload = JSON.stringify({
|
|
@@ -47356,22 +47603,22 @@ function notifySnapshotTaken(hash, tool, argsSummary, fileCount) {
|
|
|
47356
47603
|
} catch {
|
|
47357
47604
|
}
|
|
47358
47605
|
}
|
|
47359
|
-
var SNAPSHOT_STACK_PATH =
|
|
47360
|
-
var UNDO_LATEST_PATH =
|
|
47606
|
+
var SNAPSHOT_STACK_PATH = import_path43.default.join(import_os40.default.homedir(), ".node9", "snapshots.json");
|
|
47607
|
+
var UNDO_LATEST_PATH = import_path43.default.join(import_os40.default.homedir(), ".node9", "undo_latest.txt");
|
|
47361
47608
|
var MAX_SNAPSHOTS = 10;
|
|
47362
47609
|
var GIT_TIMEOUT = 15e3;
|
|
47363
47610
|
function readStack() {
|
|
47364
47611
|
try {
|
|
47365
|
-
if (
|
|
47366
|
-
return JSON.parse(
|
|
47612
|
+
if (import_fs45.default.existsSync(SNAPSHOT_STACK_PATH))
|
|
47613
|
+
return JSON.parse(import_fs45.default.readFileSync(SNAPSHOT_STACK_PATH, "utf-8"));
|
|
47367
47614
|
} catch {
|
|
47368
47615
|
}
|
|
47369
47616
|
return [];
|
|
47370
47617
|
}
|
|
47371
47618
|
function writeStack(stack) {
|
|
47372
|
-
const dir =
|
|
47373
|
-
if (!
|
|
47374
|
-
|
|
47619
|
+
const dir = import_path43.default.dirname(SNAPSHOT_STACK_PATH);
|
|
47620
|
+
if (!import_fs45.default.existsSync(dir)) import_fs45.default.mkdirSync(dir, { recursive: true });
|
|
47621
|
+
import_fs45.default.writeFileSync(SNAPSHOT_STACK_PATH, JSON.stringify(stack, null, 2));
|
|
47375
47622
|
}
|
|
47376
47623
|
function extractFilePath(args) {
|
|
47377
47624
|
if (!args || typeof args !== "object") return null;
|
|
@@ -47391,12 +47638,12 @@ function buildArgsSummary(tool, args) {
|
|
|
47391
47638
|
return "";
|
|
47392
47639
|
}
|
|
47393
47640
|
function findProjectRoot(filePath) {
|
|
47394
|
-
let dir =
|
|
47641
|
+
let dir = import_path43.default.dirname(filePath);
|
|
47395
47642
|
while (true) {
|
|
47396
|
-
if (
|
|
47643
|
+
if (import_fs45.default.existsSync(import_path43.default.join(dir, ".git")) || import_fs45.default.existsSync(import_path43.default.join(dir, "package.json"))) {
|
|
47397
47644
|
return dir;
|
|
47398
47645
|
}
|
|
47399
|
-
const parent =
|
|
47646
|
+
const parent = import_path43.default.dirname(dir);
|
|
47400
47647
|
if (parent === dir) return process.cwd();
|
|
47401
47648
|
dir = parent;
|
|
47402
47649
|
}
|
|
@@ -47404,7 +47651,7 @@ function findProjectRoot(filePath) {
|
|
|
47404
47651
|
function normalizeCwdForHash(cwd) {
|
|
47405
47652
|
let normalized;
|
|
47406
47653
|
try {
|
|
47407
|
-
normalized =
|
|
47654
|
+
normalized = import_fs45.default.realpathSync(cwd);
|
|
47408
47655
|
} catch {
|
|
47409
47656
|
normalized = cwd;
|
|
47410
47657
|
}
|
|
@@ -47414,16 +47661,16 @@ function normalizeCwdForHash(cwd) {
|
|
|
47414
47661
|
}
|
|
47415
47662
|
function getShadowRepoDir(cwd) {
|
|
47416
47663
|
const hash = import_crypto12.default.createHash("sha256").update(normalizeCwdForHash(cwd)).digest("hex").slice(0, 16);
|
|
47417
|
-
return
|
|
47664
|
+
return import_path43.default.join(import_os40.default.homedir(), ".node9", "snapshots", hash);
|
|
47418
47665
|
}
|
|
47419
47666
|
function cleanOrphanedIndexFiles(shadowDir) {
|
|
47420
47667
|
try {
|
|
47421
47668
|
const cutoff = Date.now() - 6e4;
|
|
47422
|
-
for (const f of
|
|
47669
|
+
for (const f of import_fs45.default.readdirSync(shadowDir)) {
|
|
47423
47670
|
if (f.startsWith("index_")) {
|
|
47424
|
-
const fp =
|
|
47671
|
+
const fp = import_path43.default.join(shadowDir, f);
|
|
47425
47672
|
try {
|
|
47426
|
-
if (
|
|
47673
|
+
if (import_fs45.default.statSync(fp).mtimeMs < cutoff) import_fs45.default.unlinkSync(fp);
|
|
47427
47674
|
} catch {
|
|
47428
47675
|
}
|
|
47429
47676
|
}
|
|
@@ -47435,7 +47682,7 @@ function writeShadowExcludes(shadowDir, ignorePaths) {
|
|
|
47435
47682
|
const hardcoded = [".git", ".node9"];
|
|
47436
47683
|
const lines = [...hardcoded, ...ignorePaths].join("\n");
|
|
47437
47684
|
try {
|
|
47438
|
-
|
|
47685
|
+
import_fs45.default.writeFileSync(import_path43.default.join(shadowDir, "info", "exclude"), lines + "\n", "utf8");
|
|
47439
47686
|
} catch {
|
|
47440
47687
|
}
|
|
47441
47688
|
}
|
|
@@ -47448,25 +47695,25 @@ function ensureShadowRepo(shadowDir, cwd) {
|
|
|
47448
47695
|
timeout: 3e3
|
|
47449
47696
|
});
|
|
47450
47697
|
if (check.status === 0) {
|
|
47451
|
-
const ptPath =
|
|
47698
|
+
const ptPath = import_path43.default.join(shadowDir, "project-path.txt");
|
|
47452
47699
|
try {
|
|
47453
|
-
const stored =
|
|
47700
|
+
const stored = import_fs45.default.readFileSync(ptPath, "utf8").trim();
|
|
47454
47701
|
if (stored === normalizedCwd) return true;
|
|
47455
47702
|
if (process.env.NODE9_DEBUG === "1")
|
|
47456
47703
|
console.error(
|
|
47457
47704
|
`[Node9] Shadow repo path mismatch: stored="${stored}" expected="${normalizedCwd}" \u2014 reinitializing`
|
|
47458
47705
|
);
|
|
47459
|
-
|
|
47706
|
+
import_fs45.default.rmSync(shadowDir, { recursive: true, force: true });
|
|
47460
47707
|
} catch {
|
|
47461
47708
|
try {
|
|
47462
|
-
|
|
47709
|
+
import_fs45.default.writeFileSync(ptPath, normalizedCwd, "utf8");
|
|
47463
47710
|
} catch {
|
|
47464
47711
|
}
|
|
47465
47712
|
return true;
|
|
47466
47713
|
}
|
|
47467
47714
|
}
|
|
47468
47715
|
try {
|
|
47469
|
-
|
|
47716
|
+
import_fs45.default.mkdirSync(shadowDir, { recursive: true });
|
|
47470
47717
|
} catch {
|
|
47471
47718
|
}
|
|
47472
47719
|
const init = (0, import_child_process6.spawnSync)("git", ["init", "--bare", shadowDir], { timeout: 5e3 });
|
|
@@ -47475,7 +47722,7 @@ function ensureShadowRepo(shadowDir, cwd) {
|
|
|
47475
47722
|
if (process.env.NODE9_DEBUG === "1") console.error("[Node9] git init --bare failed:", reason);
|
|
47476
47723
|
return false;
|
|
47477
47724
|
}
|
|
47478
|
-
const configFile =
|
|
47725
|
+
const configFile = import_path43.default.join(shadowDir, "config");
|
|
47479
47726
|
(0, import_child_process6.spawnSync)("git", ["config", "--file", configFile, "core.untrackedCache", "true"], {
|
|
47480
47727
|
timeout: 3e3
|
|
47481
47728
|
});
|
|
@@ -47483,7 +47730,7 @@ function ensureShadowRepo(shadowDir, cwd) {
|
|
|
47483
47730
|
timeout: 3e3
|
|
47484
47731
|
});
|
|
47485
47732
|
try {
|
|
47486
|
-
|
|
47733
|
+
import_fs45.default.writeFileSync(import_path43.default.join(shadowDir, "project-path.txt"), normalizedCwd, "utf8");
|
|
47487
47734
|
} catch {
|
|
47488
47735
|
}
|
|
47489
47736
|
return true;
|
|
@@ -47506,12 +47753,12 @@ async function createShadowSnapshot(tool = "unknown", args = {}, ignorePaths = [
|
|
|
47506
47753
|
let indexFile = null;
|
|
47507
47754
|
try {
|
|
47508
47755
|
const rawFilePath = extractFilePath(args);
|
|
47509
|
-
const absFilePath = rawFilePath &&
|
|
47756
|
+
const absFilePath = rawFilePath && import_path43.default.isAbsolute(rawFilePath) ? rawFilePath : null;
|
|
47510
47757
|
const cwd = absFilePath ? findProjectRoot(absFilePath) : process.cwd();
|
|
47511
47758
|
const shadowDir = getShadowRepoDir(cwd);
|
|
47512
47759
|
if (!ensureShadowRepo(shadowDir, cwd)) return null;
|
|
47513
47760
|
writeShadowExcludes(shadowDir, ignorePaths);
|
|
47514
|
-
indexFile =
|
|
47761
|
+
indexFile = import_path43.default.join(shadowDir, `index_${process.pid}_${Date.now()}`);
|
|
47515
47762
|
const shadowEnv = {
|
|
47516
47763
|
...process.env,
|
|
47517
47764
|
GIT_DIR: shadowDir,
|
|
@@ -47583,7 +47830,7 @@ async function createShadowSnapshot(tool = "unknown", args = {}, ignorePaths = [
|
|
|
47583
47830
|
writeStack(stack);
|
|
47584
47831
|
const entry = stack[stack.length - 1];
|
|
47585
47832
|
notifySnapshotTaken(commitHash.slice(0, 7), tool, entry.argsSummary, capturedFiles.length);
|
|
47586
|
-
|
|
47833
|
+
import_fs45.default.writeFileSync(UNDO_LATEST_PATH, commitHash);
|
|
47587
47834
|
if (shouldGc) {
|
|
47588
47835
|
(0, import_child_process6.spawn)("git", ["gc", "--auto"], { env: shadowEnv, detached: true, stdio: "ignore" }).unref();
|
|
47589
47836
|
}
|
|
@@ -47594,7 +47841,7 @@ async function createShadowSnapshot(tool = "unknown", args = {}, ignorePaths = [
|
|
|
47594
47841
|
} finally {
|
|
47595
47842
|
if (indexFile) {
|
|
47596
47843
|
try {
|
|
47597
|
-
|
|
47844
|
+
import_fs45.default.unlinkSync(indexFile);
|
|
47598
47845
|
} catch {
|
|
47599
47846
|
}
|
|
47600
47847
|
}
|
|
@@ -47670,9 +47917,9 @@ function applyUndo(hash, cwd) {
|
|
|
47670
47917
|
timeout: GIT_TIMEOUT
|
|
47671
47918
|
}).stdout?.toString().trim().split("\n").filter(Boolean) ?? [];
|
|
47672
47919
|
for (const file of [...tracked, ...untracked]) {
|
|
47673
|
-
const fullPath =
|
|
47674
|
-
if (!snapshotFiles.has(file) &&
|
|
47675
|
-
|
|
47920
|
+
const fullPath = import_path43.default.join(dir, file);
|
|
47921
|
+
if (!snapshotFiles.has(file) && import_fs45.default.existsSync(fullPath)) {
|
|
47922
|
+
import_fs45.default.unlinkSync(fullPath);
|
|
47676
47923
|
}
|
|
47677
47924
|
}
|
|
47678
47925
|
return true;
|
|
@@ -47682,12 +47929,12 @@ function applyUndo(hash, cwd) {
|
|
|
47682
47929
|
}
|
|
47683
47930
|
|
|
47684
47931
|
// src/skill-pin.ts
|
|
47685
|
-
var
|
|
47686
|
-
var
|
|
47932
|
+
var import_fs46 = __toESM(require("fs"));
|
|
47933
|
+
var import_path44 = __toESM(require("path"));
|
|
47687
47934
|
var import_os41 = __toESM(require("os"));
|
|
47688
47935
|
var import_crypto13 = __toESM(require("crypto"));
|
|
47689
47936
|
function getPinsFilePath2() {
|
|
47690
|
-
return
|
|
47937
|
+
return import_path44.default.join(import_os41.default.homedir(), ".node9", "skill-pins.json");
|
|
47691
47938
|
}
|
|
47692
47939
|
var MAX_FILES = 5e3;
|
|
47693
47940
|
var MAX_TOTAL_BYTES = 50 * 1024 * 1024;
|
|
@@ -47701,18 +47948,18 @@ function walkDir(root) {
|
|
|
47701
47948
|
if (out.length >= MAX_FILES) return;
|
|
47702
47949
|
let entries;
|
|
47703
47950
|
try {
|
|
47704
|
-
entries =
|
|
47951
|
+
entries = import_fs46.default.readdirSync(dir, { withFileTypes: true });
|
|
47705
47952
|
} catch {
|
|
47706
47953
|
return;
|
|
47707
47954
|
}
|
|
47708
47955
|
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
47709
47956
|
for (const entry of entries) {
|
|
47710
47957
|
if (out.length >= MAX_FILES) return;
|
|
47711
|
-
const full =
|
|
47712
|
-
const rel = relDir ?
|
|
47958
|
+
const full = import_path44.default.join(dir, entry.name);
|
|
47959
|
+
const rel = relDir ? import_path44.default.posix.join(relDir, entry.name) : entry.name;
|
|
47713
47960
|
let lst;
|
|
47714
47961
|
try {
|
|
47715
|
-
lst =
|
|
47962
|
+
lst = import_fs46.default.lstatSync(full);
|
|
47716
47963
|
} catch {
|
|
47717
47964
|
continue;
|
|
47718
47965
|
}
|
|
@@ -47724,7 +47971,7 @@ function walkDir(root) {
|
|
|
47724
47971
|
if (!lst.isFile()) continue;
|
|
47725
47972
|
if (totalBytes + lst.size > MAX_TOTAL_BYTES) continue;
|
|
47726
47973
|
try {
|
|
47727
|
-
const buf =
|
|
47974
|
+
const buf = import_fs46.default.readFileSync(full);
|
|
47728
47975
|
totalBytes += buf.length;
|
|
47729
47976
|
out.push({ rel, hash: sha256Bytes(buf) });
|
|
47730
47977
|
} catch {
|
|
@@ -47738,14 +47985,14 @@ function walkDir(root) {
|
|
|
47738
47985
|
function hashSkillRoot(absPath) {
|
|
47739
47986
|
let lst;
|
|
47740
47987
|
try {
|
|
47741
|
-
lst =
|
|
47988
|
+
lst = import_fs46.default.lstatSync(absPath);
|
|
47742
47989
|
} catch {
|
|
47743
47990
|
return { exists: false, contentHash: "", fileCount: 0 };
|
|
47744
47991
|
}
|
|
47745
47992
|
if (lst.isSymbolicLink()) return { exists: false, contentHash: "", fileCount: 0 };
|
|
47746
47993
|
if (lst.isFile()) {
|
|
47747
47994
|
try {
|
|
47748
|
-
return { exists: true, contentHash: sha256Bytes(
|
|
47995
|
+
return { exists: true, contentHash: sha256Bytes(import_fs46.default.readFileSync(absPath)), fileCount: 1 };
|
|
47749
47996
|
} catch {
|
|
47750
47997
|
return { exists: false, contentHash: "", fileCount: 0 };
|
|
47751
47998
|
}
|
|
@@ -47763,7 +48010,7 @@ function getRootKey(absPath) {
|
|
|
47763
48010
|
function readSkillPinsSafe() {
|
|
47764
48011
|
const filePath = getPinsFilePath2();
|
|
47765
48012
|
try {
|
|
47766
|
-
const raw =
|
|
48013
|
+
const raw = import_fs46.default.readFileSync(filePath, "utf-8");
|
|
47767
48014
|
if (!raw.trim()) return { ok: false, reason: "corrupt", detail: "empty file" };
|
|
47768
48015
|
const parsed = JSON.parse(raw);
|
|
47769
48016
|
if (!parsed.roots || typeof parsed.roots !== "object" || Array.isArray(parsed.roots)) {
|
|
@@ -47783,10 +48030,10 @@ function readSkillPins() {
|
|
|
47783
48030
|
}
|
|
47784
48031
|
function writeSkillPins(data) {
|
|
47785
48032
|
const filePath = getPinsFilePath2();
|
|
47786
|
-
|
|
48033
|
+
import_fs46.default.mkdirSync(import_path44.default.dirname(filePath), { recursive: true });
|
|
47787
48034
|
const tmp = `${filePath}.${import_crypto13.default.randomBytes(6).toString("hex")}.tmp`;
|
|
47788
|
-
|
|
47789
|
-
|
|
48035
|
+
import_fs46.default.writeFileSync(tmp, JSON.stringify(data, null, 2), { mode: 384 });
|
|
48036
|
+
import_fs46.default.renameSync(tmp, filePath);
|
|
47790
48037
|
}
|
|
47791
48038
|
function removePin2(rootKey) {
|
|
47792
48039
|
const pins = readSkillPins();
|
|
@@ -47830,36 +48077,36 @@ function verifyAndPinRoots(roots) {
|
|
|
47830
48077
|
return { kind: "verified" };
|
|
47831
48078
|
}
|
|
47832
48079
|
function defaultSkillRoots(_cwd) {
|
|
47833
|
-
const marketplaces =
|
|
48080
|
+
const marketplaces = import_path44.default.join(import_os41.default.homedir(), ".claude", "plugins", "marketplaces");
|
|
47834
48081
|
const roots = [];
|
|
47835
48082
|
let registries;
|
|
47836
48083
|
try {
|
|
47837
|
-
registries =
|
|
48084
|
+
registries = import_fs46.default.readdirSync(marketplaces, { withFileTypes: true });
|
|
47838
48085
|
} catch {
|
|
47839
48086
|
return [];
|
|
47840
48087
|
}
|
|
47841
48088
|
for (const registry of registries) {
|
|
47842
48089
|
if (!registry.isDirectory()) continue;
|
|
47843
|
-
const pluginsDir =
|
|
48090
|
+
const pluginsDir = import_path44.default.join(marketplaces, registry.name, "plugins");
|
|
47844
48091
|
let plugins;
|
|
47845
48092
|
try {
|
|
47846
|
-
plugins =
|
|
48093
|
+
plugins = import_fs46.default.readdirSync(pluginsDir, { withFileTypes: true });
|
|
47847
48094
|
} catch {
|
|
47848
48095
|
continue;
|
|
47849
48096
|
}
|
|
47850
48097
|
for (const plugin of plugins) {
|
|
47851
48098
|
if (!plugin.isDirectory()) continue;
|
|
47852
|
-
roots.push(
|
|
48099
|
+
roots.push(import_path44.default.join(pluginsDir, plugin.name));
|
|
47853
48100
|
}
|
|
47854
48101
|
}
|
|
47855
48102
|
return roots;
|
|
47856
48103
|
}
|
|
47857
48104
|
function resolveUserSkillRoot(entry, cwd) {
|
|
47858
48105
|
if (!entry) return null;
|
|
47859
|
-
if (entry.startsWith("~/") || entry === "~") return
|
|
47860
|
-
if (
|
|
47861
|
-
if (!cwd || !
|
|
47862
|
-
return
|
|
48106
|
+
if (entry.startsWith("~/") || entry === "~") return import_path44.default.join(import_os41.default.homedir(), entry.slice(1));
|
|
48107
|
+
if (import_path44.default.isAbsolute(entry)) return entry;
|
|
48108
|
+
if (!cwd || !import_path44.default.isAbsolute(cwd)) return null;
|
|
48109
|
+
return import_path44.default.join(cwd, entry);
|
|
47863
48110
|
}
|
|
47864
48111
|
|
|
47865
48112
|
// src/cli/commands/check.ts
|
|
@@ -47867,12 +48114,12 @@ init_dlp();
|
|
|
47867
48114
|
init_audit();
|
|
47868
48115
|
|
|
47869
48116
|
// src/review-pending.ts
|
|
47870
|
-
var
|
|
48117
|
+
var import_fs47 = __toESM(require("fs"));
|
|
47871
48118
|
var import_os42 = __toESM(require("os"));
|
|
47872
|
-
var
|
|
48119
|
+
var import_path45 = __toESM(require("path"));
|
|
47873
48120
|
init_hasher();
|
|
47874
48121
|
function storePath() {
|
|
47875
|
-
return process.env.NODE9_PENDING_STORE ||
|
|
48122
|
+
return process.env.NODE9_PENDING_STORE || import_path45.default.join(import_os42.default.homedir(), ".node9", "pending-reviews.json");
|
|
47876
48123
|
}
|
|
47877
48124
|
var TTL_MS2 = 6 * 60 * 60 * 1e3;
|
|
47878
48125
|
var MAX_ENTRIES = 500;
|
|
@@ -47889,7 +48136,7 @@ function reviewCorrelationKey(payload) {
|
|
|
47889
48136
|
}
|
|
47890
48137
|
function read() {
|
|
47891
48138
|
try {
|
|
47892
|
-
const parsed = JSON.parse(
|
|
48139
|
+
const parsed = JSON.parse(import_fs47.default.readFileSync(storePath(), "utf-8"));
|
|
47893
48140
|
if (parsed && Array.isArray(parsed.entries)) return parsed;
|
|
47894
48141
|
} catch {
|
|
47895
48142
|
}
|
|
@@ -47898,11 +48145,11 @@ function read() {
|
|
|
47898
48145
|
function write(store) {
|
|
47899
48146
|
try {
|
|
47900
48147
|
const p = storePath();
|
|
47901
|
-
const dir =
|
|
47902
|
-
if (!
|
|
48148
|
+
const dir = import_path45.default.dirname(p);
|
|
48149
|
+
if (!import_fs47.default.existsSync(dir)) import_fs47.default.mkdirSync(dir, { recursive: true });
|
|
47903
48150
|
const tmp = `${p}.${process.pid}.tmp`;
|
|
47904
|
-
|
|
47905
|
-
|
|
48151
|
+
import_fs47.default.writeFileSync(tmp, JSON.stringify(store));
|
|
48152
|
+
import_fs47.default.renameSync(tmp, p);
|
|
47906
48153
|
} catch {
|
|
47907
48154
|
}
|
|
47908
48155
|
}
|
|
@@ -48015,9 +48262,9 @@ function registerCheckCommand(program2) {
|
|
|
48015
48262
|
} catch (err2) {
|
|
48016
48263
|
const tempConfig = getConfig();
|
|
48017
48264
|
if (process.env.NODE9_DEBUG === "1" || tempConfig.settings.enableHookLogDebug) {
|
|
48018
|
-
const logPath =
|
|
48265
|
+
const logPath = import_path46.default.join(import_os43.default.homedir(), ".node9", "hook-debug.log");
|
|
48019
48266
|
const errMsg = err2 instanceof Error ? err2.message : String(err2);
|
|
48020
|
-
|
|
48267
|
+
import_fs48.default.appendFileSync(
|
|
48021
48268
|
logPath,
|
|
48022
48269
|
`[${(/* @__PURE__ */ new Date()).toISOString()}] JSON_PARSE_ERROR: ${errMsg}
|
|
48023
48270
|
RAW: ${raw}
|
|
@@ -48030,14 +48277,14 @@ RAW: ${raw}
|
|
|
48030
48277
|
const prompt = typeof payload.prompt === "string" ? payload.prompt : "";
|
|
48031
48278
|
if (process.env.NODE9_DEBUG === "1") {
|
|
48032
48279
|
try {
|
|
48033
|
-
const logPath =
|
|
48034
|
-
if (!
|
|
48035
|
-
|
|
48280
|
+
const logPath = import_path46.default.join(import_os43.default.homedir(), ".node9", "hook-debug.log");
|
|
48281
|
+
if (!import_fs48.default.existsSync(import_path46.default.dirname(logPath)))
|
|
48282
|
+
import_fs48.default.mkdirSync(import_path46.default.dirname(logPath), { recursive: true });
|
|
48036
48283
|
const sanitized = JSON.stringify({
|
|
48037
48284
|
...payload,
|
|
48038
48285
|
prompt: `<redacted, ${prompt.length} bytes>`
|
|
48039
48286
|
});
|
|
48040
|
-
|
|
48287
|
+
import_fs48.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] STDIN: ${sanitized}
|
|
48041
48288
|
`);
|
|
48042
48289
|
} catch {
|
|
48043
48290
|
}
|
|
@@ -48058,8 +48305,8 @@ RAW: ${raw}
|
|
|
48058
48305
|
);
|
|
48059
48306
|
const reason = `\u{1F6A8} Node9 DLP: ${dlpMatch.patternName} detected in prompt (${dlpMatch.redactedSample}). Prompt was not submitted \u2014 remove the credential and try again.`;
|
|
48060
48307
|
try {
|
|
48061
|
-
const ttyFd =
|
|
48062
|
-
|
|
48308
|
+
const ttyFd = import_fs48.default.openSync("/dev/tty", "w");
|
|
48309
|
+
import_fs48.default.writeSync(
|
|
48063
48310
|
ttyFd,
|
|
48064
48311
|
import_chalk9.default.bgRed.white.bold(`
|
|
48065
48312
|
\u{1F6A8} NODE9 DLP \u2014 PROMPT BLOCKED
|
|
@@ -48069,7 +48316,7 @@ RAW: ${raw}
|
|
|
48069
48316
|
|
|
48070
48317
|
`)
|
|
48071
48318
|
);
|
|
48072
|
-
|
|
48319
|
+
import_fs48.default.closeSync(ttyFd);
|
|
48073
48320
|
} catch {
|
|
48074
48321
|
}
|
|
48075
48322
|
const isCodex = agent2 === "Codex";
|
|
@@ -48088,17 +48335,17 @@ RAW: ${raw}
|
|
|
48088
48335
|
process.exit(2);
|
|
48089
48336
|
}
|
|
48090
48337
|
const payloadCwd = typeof payload.cwd === "string" ? payload.cwd : Array.isArray(payload.workspacePaths) && typeof payload.workspacePaths[0] === "string" ? payload.workspacePaths[0] : void 0;
|
|
48091
|
-
const safeCwdForConfig = typeof payloadCwd === "string" &&
|
|
48338
|
+
const safeCwdForConfig = typeof payloadCwd === "string" && import_path46.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
|
|
48092
48339
|
const config = getConfig(safeCwdForConfig);
|
|
48093
48340
|
const daemonDown = !isDaemonRunning();
|
|
48094
48341
|
if (config.settings.autoStartDaemon && daemonDown && !process.env.NODE9_NO_AUTO_DAEMON) {
|
|
48095
48342
|
try {
|
|
48096
48343
|
const scriptPath = process.argv[1];
|
|
48097
|
-
if (typeof scriptPath !== "string" || !
|
|
48344
|
+
if (typeof scriptPath !== "string" || !import_path46.default.isAbsolute(scriptPath))
|
|
48098
48345
|
throw new Error("node9: argv[1] is not an absolute path");
|
|
48099
|
-
const resolvedScript =
|
|
48100
|
-
const packageDist =
|
|
48101
|
-
if (!resolvedScript.startsWith(packageDist +
|
|
48346
|
+
const resolvedScript = import_fs48.default.realpathSync(scriptPath);
|
|
48347
|
+
const packageDist = import_fs48.default.realpathSync(import_path46.default.resolve(__dirname, "../.."));
|
|
48348
|
+
if (!resolvedScript.startsWith(packageDist + import_path46.default.sep) && resolvedScript !== packageDist)
|
|
48102
48349
|
throw new Error(
|
|
48103
48350
|
`node9: daemon spawn aborted \u2014 argv[1] (${resolvedScript}) is outside package dist (${packageDist})`
|
|
48104
48351
|
);
|
|
@@ -48128,17 +48375,17 @@ RAW: ${raw}
|
|
|
48128
48375
|
} finally {
|
|
48129
48376
|
if (startupFd !== void 0) {
|
|
48130
48377
|
try {
|
|
48131
|
-
|
|
48378
|
+
import_fs48.default.closeSync(startupFd);
|
|
48132
48379
|
} catch {
|
|
48133
48380
|
}
|
|
48134
48381
|
}
|
|
48135
48382
|
}
|
|
48136
48383
|
} catch (spawnErr) {
|
|
48137
|
-
const logPath =
|
|
48384
|
+
const logPath = import_path46.default.join(import_os43.default.homedir(), ".node9", "hook-debug.log");
|
|
48138
48385
|
const msg = spawnErr instanceof Error ? spawnErr.message : String(spawnErr);
|
|
48139
48386
|
recordStartupState("failed", "spawn-aborted", msg);
|
|
48140
48387
|
try {
|
|
48141
|
-
|
|
48388
|
+
import_fs48.default.appendFileSync(
|
|
48142
48389
|
logPath,
|
|
48143
48390
|
`[${(/* @__PURE__ */ new Date()).toISOString()}] daemon-autostart-failed: ${msg}
|
|
48144
48391
|
`
|
|
@@ -48152,10 +48399,10 @@ RAW: ${raw}
|
|
|
48152
48399
|
);
|
|
48153
48400
|
}
|
|
48154
48401
|
if (process.env.NODE9_DEBUG === "1" || config.settings.enableHookLogDebug) {
|
|
48155
|
-
const logPath =
|
|
48156
|
-
if (!
|
|
48157
|
-
|
|
48158
|
-
|
|
48402
|
+
const logPath = import_path46.default.join(import_os43.default.homedir(), ".node9", "hook-debug.log");
|
|
48403
|
+
if (!import_fs48.default.existsSync(import_path46.default.dirname(logPath)))
|
|
48404
|
+
import_fs48.default.mkdirSync(import_path46.default.dirname(logPath), { recursive: true });
|
|
48405
|
+
import_fs48.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] STDIN: ${raw}
|
|
48159
48406
|
`);
|
|
48160
48407
|
}
|
|
48161
48408
|
const rawToolName = sanitize2(extractToolName(payload));
|
|
@@ -48169,8 +48416,8 @@ RAW: ${raw}
|
|
|
48169
48416
|
const isHumanDecision = blockedByContext.toLowerCase().includes("user") || blockedByContext.toLowerCase().includes("daemon") || blockedByContext.toLowerCase().includes("decision");
|
|
48170
48417
|
let ttyFd = null;
|
|
48171
48418
|
try {
|
|
48172
|
-
ttyFd =
|
|
48173
|
-
const writeTty = (line) =>
|
|
48419
|
+
ttyFd = import_fs48.default.openSync("/dev/tty", "w");
|
|
48420
|
+
const writeTty = (line) => import_fs48.default.writeSync(ttyFd, line + "\n");
|
|
48174
48421
|
if (blockedByContext.includes("DLP") || blockedByContext.includes("Secret Detected") || blockedByContext.includes("Credential Review")) {
|
|
48175
48422
|
writeTty(import_chalk9.default.bgRed.white.bold(`
|
|
48176
48423
|
\u{1F6A8} NODE9 DLP ALERT \u2014 CREDENTIAL DETECTED `));
|
|
@@ -48189,7 +48436,7 @@ RAW: ${raw}
|
|
|
48189
48436
|
} finally {
|
|
48190
48437
|
if (ttyFd !== null)
|
|
48191
48438
|
try {
|
|
48192
|
-
|
|
48439
|
+
import_fs48.default.closeSync(ttyFd);
|
|
48193
48440
|
} catch {
|
|
48194
48441
|
}
|
|
48195
48442
|
}
|
|
@@ -48246,8 +48493,8 @@ RAW: ${raw}
|
|
|
48246
48493
|
} catch {
|
|
48247
48494
|
}
|
|
48248
48495
|
try {
|
|
48249
|
-
const ttyFd =
|
|
48250
|
-
|
|
48496
|
+
const ttyFd = import_fs48.default.openSync("/dev/tty", "w");
|
|
48497
|
+
import_fs48.default.writeSync(
|
|
48251
48498
|
ttyFd,
|
|
48252
48499
|
import_chalk9.default.yellow(
|
|
48253
48500
|
`
|
|
@@ -48255,7 +48502,7 @@ RAW: ${raw}
|
|
|
48255
48502
|
`
|
|
48256
48503
|
)
|
|
48257
48504
|
);
|
|
48258
|
-
|
|
48505
|
+
import_fs48.default.closeSync(ttyFd);
|
|
48259
48506
|
} catch {
|
|
48260
48507
|
}
|
|
48261
48508
|
if (agent === "GitHub Copilot") {
|
|
@@ -48287,17 +48534,17 @@ RAW: ${raw}
|
|
|
48287
48534
|
const safeSessionId = /^[A-Za-z0-9_\-]{1,128}$/.test(rawSessionId) ? rawSessionId : "";
|
|
48288
48535
|
if (skillPinCfg.enabled && safeSessionId) {
|
|
48289
48536
|
try {
|
|
48290
|
-
const sessionsDir =
|
|
48291
|
-
const flagPath =
|
|
48537
|
+
const sessionsDir = import_path46.default.join(import_os43.default.homedir(), ".node9", "skill-sessions");
|
|
48538
|
+
const flagPath = import_path46.default.join(sessionsDir, `${safeSessionId}.json`);
|
|
48292
48539
|
let flag = null;
|
|
48293
48540
|
try {
|
|
48294
|
-
flag = JSON.parse(
|
|
48541
|
+
flag = JSON.parse(import_fs48.default.readFileSync(flagPath, "utf-8"));
|
|
48295
48542
|
} catch {
|
|
48296
48543
|
}
|
|
48297
48544
|
const writeFlag = (data2) => {
|
|
48298
48545
|
try {
|
|
48299
|
-
|
|
48300
|
-
|
|
48546
|
+
import_fs48.default.mkdirSync(sessionsDir, { recursive: true });
|
|
48547
|
+
import_fs48.default.writeFileSync(
|
|
48301
48548
|
flagPath,
|
|
48302
48549
|
JSON.stringify({ ...data2, timestamp: (/* @__PURE__ */ new Date()).toISOString() }, null, 2),
|
|
48303
48550
|
{ mode: 384 }
|
|
@@ -48308,8 +48555,8 @@ RAW: ${raw}
|
|
|
48308
48555
|
const sendSkillWarn = (detail, recoveryCmd) => {
|
|
48309
48556
|
let ttyFd = null;
|
|
48310
48557
|
try {
|
|
48311
|
-
ttyFd =
|
|
48312
|
-
const w = (line) =>
|
|
48558
|
+
ttyFd = import_fs48.default.openSync("/dev/tty", "w");
|
|
48559
|
+
const w = (line) => import_fs48.default.writeSync(ttyFd, line + "\n");
|
|
48313
48560
|
w(import_chalk9.default.yellow(`
|
|
48314
48561
|
\u26A0\uFE0F Node9: installed skill drift detected`));
|
|
48315
48562
|
w(import_chalk9.default.gray(` ${detail}`));
|
|
@@ -48324,7 +48571,7 @@ RAW: ${raw}
|
|
|
48324
48571
|
} finally {
|
|
48325
48572
|
if (ttyFd !== null)
|
|
48326
48573
|
try {
|
|
48327
|
-
|
|
48574
|
+
import_fs48.default.closeSync(ttyFd);
|
|
48328
48575
|
} catch {
|
|
48329
48576
|
}
|
|
48330
48577
|
}
|
|
@@ -48340,7 +48587,7 @@ RAW: ${raw}
|
|
|
48340
48587
|
return;
|
|
48341
48588
|
}
|
|
48342
48589
|
if (!flag || flag.state !== "verified" && flag.state !== "warned") {
|
|
48343
|
-
const absoluteCwd = typeof payloadCwd === "string" &&
|
|
48590
|
+
const absoluteCwd = typeof payloadCwd === "string" && import_path46.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
|
|
48344
48591
|
const extraRoots = skillPinCfg.roots;
|
|
48345
48592
|
const resolvedExtra = extraRoots.map((r) => resolveUserSkillRoot(r, absoluteCwd)).filter((r) => typeof r === "string");
|
|
48346
48593
|
const roots = [...defaultSkillRoots(absoluteCwd), ...resolvedExtra];
|
|
@@ -48381,10 +48628,10 @@ RAW: ${raw}
|
|
|
48381
48628
|
}
|
|
48382
48629
|
try {
|
|
48383
48630
|
const cutoff = Date.now() - 7 * 24 * 60 * 60 * 1e3;
|
|
48384
|
-
for (const name of
|
|
48385
|
-
const p =
|
|
48631
|
+
for (const name of import_fs48.default.readdirSync(sessionsDir)) {
|
|
48632
|
+
const p = import_path46.default.join(sessionsDir, name);
|
|
48386
48633
|
try {
|
|
48387
|
-
if (
|
|
48634
|
+
if (import_fs48.default.statSync(p).mtimeMs < cutoff) import_fs48.default.unlinkSync(p);
|
|
48388
48635
|
} catch {
|
|
48389
48636
|
}
|
|
48390
48637
|
}
|
|
@@ -48394,9 +48641,9 @@ RAW: ${raw}
|
|
|
48394
48641
|
} catch (err2) {
|
|
48395
48642
|
if (process.env.NODE9_DEBUG === "1") {
|
|
48396
48643
|
try {
|
|
48397
|
-
const dbg =
|
|
48644
|
+
const dbg = import_path46.default.join(import_os43.default.homedir(), ".node9", "hook-debug.log");
|
|
48398
48645
|
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
48399
|
-
|
|
48646
|
+
import_fs48.default.appendFileSync(dbg, `[${(/* @__PURE__ */ new Date()).toISOString()}] SKILL_PIN_ERROR: ${msg}
|
|
48400
48647
|
`);
|
|
48401
48648
|
} catch {
|
|
48402
48649
|
}
|
|
@@ -48406,7 +48653,7 @@ RAW: ${raw}
|
|
|
48406
48653
|
if (shouldSnapshot(toolName, toolInput, config)) {
|
|
48407
48654
|
await createShadowSnapshot(toolName, toolInput, config.policy.snapshot.ignorePaths);
|
|
48408
48655
|
}
|
|
48409
|
-
const safeCwdForAuth = typeof payloadCwd === "string" &&
|
|
48656
|
+
const safeCwdForAuth = typeof payloadCwd === "string" && import_path46.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
|
|
48410
48657
|
const askMode = resolveAskMode(agent, opts, config);
|
|
48411
48658
|
const result = await authorizeHeadless(toolName, toolInput, meta, {
|
|
48412
48659
|
cwd: safeCwdForAuth,
|
|
@@ -48424,12 +48671,12 @@ RAW: ${raw}
|
|
|
48424
48671
|
}
|
|
48425
48672
|
if (result.noApprovalMechanism && !isDaemonRunning() && !process.env.NODE9_NO_AUTO_DAEMON && !process.stdout.isTTY && config.settings.autoStartDaemon) {
|
|
48426
48673
|
try {
|
|
48427
|
-
const tty =
|
|
48428
|
-
|
|
48674
|
+
const tty = import_fs48.default.openSync("/dev/tty", "w");
|
|
48675
|
+
import_fs48.default.writeSync(
|
|
48429
48676
|
tty,
|
|
48430
48677
|
import_chalk9.default.cyan("\n\u{1F6E1}\uFE0F Node9: Starting approval daemon automatically...\n")
|
|
48431
48678
|
);
|
|
48432
|
-
|
|
48679
|
+
import_fs48.default.closeSync(tty);
|
|
48433
48680
|
} catch {
|
|
48434
48681
|
}
|
|
48435
48682
|
const daemonReady = await autoStartDaemonAndWait();
|
|
@@ -48456,9 +48703,9 @@ RAW: ${raw}
|
|
|
48456
48703
|
});
|
|
48457
48704
|
} catch (err2) {
|
|
48458
48705
|
if (process.env.NODE9_DEBUG === "1") {
|
|
48459
|
-
const logPath =
|
|
48706
|
+
const logPath = import_path46.default.join(import_os43.default.homedir(), ".node9", "hook-debug.log");
|
|
48460
48707
|
const errMsg = err2 instanceof Error ? err2.message : String(err2);
|
|
48461
|
-
|
|
48708
|
+
import_fs48.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] ERROR: ${errMsg}
|
|
48462
48709
|
`);
|
|
48463
48710
|
}
|
|
48464
48711
|
process.exit(0);
|
|
@@ -48492,8 +48739,8 @@ RAW: ${raw}
|
|
|
48492
48739
|
}
|
|
48493
48740
|
|
|
48494
48741
|
// src/cli/commands/log.ts
|
|
48495
|
-
var
|
|
48496
|
-
var
|
|
48742
|
+
var import_fs49 = __toESM(require("fs"));
|
|
48743
|
+
var import_path47 = __toESM(require("path"));
|
|
48497
48744
|
var import_os44 = __toESM(require("os"));
|
|
48498
48745
|
init_audit();
|
|
48499
48746
|
init_config();
|
|
@@ -48604,10 +48851,10 @@ function registerLogCommand(program2) {
|
|
|
48604
48851
|
if (rawToolName !== tool) entry.agentToolName = rawToolName;
|
|
48605
48852
|
const payloadSessionId = payload.session_id ?? payload.conversationId;
|
|
48606
48853
|
if (payloadSessionId) entry.sessionId = payloadSessionId;
|
|
48607
|
-
const logPath =
|
|
48608
|
-
if (!
|
|
48609
|
-
|
|
48610
|
-
|
|
48854
|
+
const logPath = import_path47.default.join(import_os44.default.homedir(), ".node9", "audit.log");
|
|
48855
|
+
if (!import_fs49.default.existsSync(import_path47.default.dirname(logPath)))
|
|
48856
|
+
import_fs49.default.mkdirSync(import_path47.default.dirname(logPath), { recursive: true });
|
|
48857
|
+
import_fs49.default.appendFileSync(logPath, JSON.stringify(entry) + "\n");
|
|
48611
48858
|
if ((tool === "Bash" || tool === "bash") && isDaemonRunning()) {
|
|
48612
48859
|
const command = typeof rawInput === "object" && rawInput !== null && "command" in rawInput && typeof rawInput.command === "string" ? rawInput.command : null;
|
|
48613
48860
|
if (command) {
|
|
@@ -48641,7 +48888,7 @@ function registerLogCommand(program2) {
|
|
|
48641
48888
|
}
|
|
48642
48889
|
}
|
|
48643
48890
|
const payloadCwd = typeof payload.cwd === "string" ? payload.cwd : Array.isArray(payload.workspacePaths) && typeof payload.workspacePaths[0] === "string" ? payload.workspacePaths[0] : void 0;
|
|
48644
|
-
const safeCwd = typeof payloadCwd === "string" &&
|
|
48891
|
+
const safeCwd = typeof payloadCwd === "string" && import_path47.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
|
|
48645
48892
|
const config = getConfig(safeCwd);
|
|
48646
48893
|
{
|
|
48647
48894
|
const toolOutput = payload.tool_response?.output;
|
|
@@ -48718,9 +48965,9 @@ function registerLogCommand(program2) {
|
|
|
48718
48965
|
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
48719
48966
|
process.stderr.write(`[Node9] audit log error: ${msg}
|
|
48720
48967
|
`);
|
|
48721
|
-
const debugPath =
|
|
48968
|
+
const debugPath = import_path47.default.join(import_os44.default.homedir(), ".node9", "hook-debug.log");
|
|
48722
48969
|
try {
|
|
48723
|
-
|
|
48970
|
+
import_fs49.default.appendFileSync(debugPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] LOG_ERROR: ${msg}
|
|
48724
48971
|
`);
|
|
48725
48972
|
} catch {
|
|
48726
48973
|
}
|
|
@@ -48745,15 +48992,15 @@ function registerLogCommand(program2) {
|
|
|
48745
48992
|
|
|
48746
48993
|
// src/cli/commands/shield.ts
|
|
48747
48994
|
var import_chalk10 = __toESM(require("chalk"));
|
|
48748
|
-
var
|
|
48749
|
-
var
|
|
48995
|
+
var import_fs51 = __toESM(require("fs"));
|
|
48996
|
+
var import_path49 = __toESM(require("path"));
|
|
48750
48997
|
var import_os45 = __toESM(require("os"));
|
|
48751
48998
|
init_shields();
|
|
48752
48999
|
init_build();
|
|
48753
49000
|
|
|
48754
49001
|
// src/shields/create.ts
|
|
48755
|
-
var
|
|
48756
|
-
var
|
|
49002
|
+
var import_fs50 = __toESM(require("fs"));
|
|
49003
|
+
var import_path48 = __toESM(require("path"));
|
|
48757
49004
|
init_dist();
|
|
48758
49005
|
init_shields();
|
|
48759
49006
|
init_audit();
|
|
@@ -48773,8 +49020,8 @@ function createShield(def, opts = {}) {
|
|
|
48773
49020
|
error: `"${name}" is a built-in shield \u2014 choose a different name (a user shield with this name would shadow the built-in).`
|
|
48774
49021
|
};
|
|
48775
49022
|
}
|
|
48776
|
-
const filePath =
|
|
48777
|
-
if (!opts.overwrite &&
|
|
49023
|
+
const filePath = import_path48.default.join(USER_SHIELDS_DIR_PATH, `${name}.json`);
|
|
49024
|
+
if (!opts.overwrite && import_fs50.default.existsSync(filePath)) {
|
|
48778
49025
|
return {
|
|
48779
49026
|
ok: false,
|
|
48780
49027
|
error: `Shield "${name}" already exists at ${filePath}. Pass --overwrite to replace it.`
|
|
@@ -48839,8 +49086,8 @@ var COMMUNITY_INDEX_URL = "https://raw.githubusercontent.com/node9ai/node9-proxy
|
|
|
48839
49086
|
function readCloudShields() {
|
|
48840
49087
|
const out = /* @__PURE__ */ new Set();
|
|
48841
49088
|
try {
|
|
48842
|
-
const file =
|
|
48843
|
-
const raw = JSON.parse(
|
|
49089
|
+
const file = import_path49.default.join(import_os45.default.homedir(), ".node9", "rules-cache.json");
|
|
49090
|
+
const raw = JSON.parse(import_fs51.default.readFileSync(file, "utf-8"));
|
|
48844
49091
|
for (const r of raw.rules ?? []) {
|
|
48845
49092
|
const rule = r;
|
|
48846
49093
|
const fromSource = rule.source?.startsWith("SHIELD:") ? rule.source.slice("SHIELD:".length).toLowerCase() : void 0;
|
|
@@ -49157,7 +49404,7 @@ function registerShieldCommand(program2) {
|
|
|
49157
49404
|
if (opts.fromFile) {
|
|
49158
49405
|
let raw;
|
|
49159
49406
|
try {
|
|
49160
|
-
raw = JSON.parse(
|
|
49407
|
+
raw = JSON.parse(import_fs51.default.readFileSync(opts.fromFile, "utf-8"));
|
|
49161
49408
|
} catch (err2) {
|
|
49162
49409
|
console.error(
|
|
49163
49410
|
import_chalk10.default.red(`
|
|
@@ -49277,11 +49524,12 @@ function registerConfigShowCommand(program2) {
|
|
|
49277
49524
|
|
|
49278
49525
|
// src/cli/commands/doctor.ts
|
|
49279
49526
|
var import_chalk11 = __toESM(require("chalk"));
|
|
49280
|
-
var
|
|
49281
|
-
var
|
|
49527
|
+
var import_fs52 = __toESM(require("fs"));
|
|
49528
|
+
var import_path50 = __toESM(require("path"));
|
|
49282
49529
|
var import_os46 = __toESM(require("os"));
|
|
49283
49530
|
var import_child_process8 = require("child_process");
|
|
49284
49531
|
init_daemon();
|
|
49532
|
+
init_build_id();
|
|
49285
49533
|
init_config();
|
|
49286
49534
|
init_agent_wiring();
|
|
49287
49535
|
init_sync();
|
|
@@ -49350,10 +49598,10 @@ function registerDoctorCommand(program2, version2) {
|
|
|
49350
49598
|
);
|
|
49351
49599
|
}
|
|
49352
49600
|
section("Configuration");
|
|
49353
|
-
const globalConfigPath =
|
|
49354
|
-
if (
|
|
49601
|
+
const globalConfigPath = import_path50.default.join(homeDir2, ".node9", "config.json");
|
|
49602
|
+
if (import_fs52.default.existsSync(globalConfigPath)) {
|
|
49355
49603
|
try {
|
|
49356
|
-
JSON.parse(
|
|
49604
|
+
JSON.parse(import_fs52.default.readFileSync(globalConfigPath, "utf-8"));
|
|
49357
49605
|
pass("~/.node9/config.json found and valid");
|
|
49358
49606
|
} catch {
|
|
49359
49607
|
fail("~/.node9/config.json is invalid JSON", "Run: node9 init --force");
|
|
@@ -49361,10 +49609,10 @@ function registerDoctorCommand(program2, version2) {
|
|
|
49361
49609
|
} else {
|
|
49362
49610
|
warn("~/.node9/config.json not found (using defaults)", "Run: node9 init");
|
|
49363
49611
|
}
|
|
49364
|
-
const projectConfigPath =
|
|
49365
|
-
if (
|
|
49612
|
+
const projectConfigPath = import_path50.default.join(process.cwd(), "node9.config.json");
|
|
49613
|
+
if (import_fs52.default.existsSync(projectConfigPath)) {
|
|
49366
49614
|
try {
|
|
49367
|
-
JSON.parse(
|
|
49615
|
+
JSON.parse(import_fs52.default.readFileSync(projectConfigPath, "utf-8"));
|
|
49368
49616
|
pass("node9.config.json found and valid (project)");
|
|
49369
49617
|
} catch {
|
|
49370
49618
|
fail(
|
|
@@ -49373,8 +49621,8 @@ function registerDoctorCommand(program2, version2) {
|
|
|
49373
49621
|
);
|
|
49374
49622
|
}
|
|
49375
49623
|
}
|
|
49376
|
-
const credsPath =
|
|
49377
|
-
if (
|
|
49624
|
+
const credsPath = import_path50.default.join(homeDir2, ".node9", "credentials.json");
|
|
49625
|
+
if (import_fs52.default.existsSync(credsPath)) {
|
|
49378
49626
|
pass("Cloud credentials found (~/.node9/credentials.json)");
|
|
49379
49627
|
} else {
|
|
49380
49628
|
warn(
|
|
@@ -49408,6 +49656,17 @@ function registerDoctorCommand(program2, version2) {
|
|
|
49408
49656
|
pass(
|
|
49409
49657
|
`Daemon running on ${DAEMON_HOST}:${DAEMON_PORT} \u2014 terminal & native approvals enabled`
|
|
49410
49658
|
);
|
|
49659
|
+
const probe = await probeDaemonHealth();
|
|
49660
|
+
const drift = describeBuildDrift(
|
|
49661
|
+
probe.kind === "health" ? probe.health : probe.kind === "no-health" ? "no-health" : null,
|
|
49662
|
+
CURRENT_BUILD
|
|
49663
|
+
);
|
|
49664
|
+
if (drift) {
|
|
49665
|
+
warn(
|
|
49666
|
+
drift,
|
|
49667
|
+
"Stop the running daemon (pid in ~/.node9/daemon.pid), then: node9 daemon --background"
|
|
49668
|
+
);
|
|
49669
|
+
}
|
|
49411
49670
|
} else {
|
|
49412
49671
|
warn(
|
|
49413
49672
|
"Daemon not running \u2014 terminal & native approvals unavailable",
|
|
@@ -49429,7 +49688,7 @@ function registerDoctorCommand(program2, version2) {
|
|
|
49429
49688
|
cloudEnabled: !!getConfig().settings.approvers?.cloud
|
|
49430
49689
|
});
|
|
49431
49690
|
if (autostart) warn(autostart.message, autostart.hint);
|
|
49432
|
-
if (
|
|
49691
|
+
if (import_fs52.default.existsSync(import_path50.default.join(import_os46.default.homedir(), ".node9", "credentials.json")) && getConfig().settings.approvers?.cloud) {
|
|
49433
49692
|
section("Policy sync");
|
|
49434
49693
|
const health = readSyncHealth();
|
|
49435
49694
|
if (isPolicyStale(Date.now(), health)) {
|
|
@@ -49447,7 +49706,7 @@ function registerDoctorCommand(program2, version2) {
|
|
|
49447
49706
|
try {
|
|
49448
49707
|
const { shipLagBytes: shipLagBytes2, readWatermark: readWatermark2, AUDIT_SHIP_WATERMARK: AUDIT_SHIP_WATERMARK2 } = await Promise.resolve().then(() => (init_audit_shipper(), audit_shipper_exports));
|
|
49449
49708
|
const cfg = getConfig();
|
|
49450
|
-
const creds =
|
|
49709
|
+
const creds = import_fs52.default.existsSync(import_path50.default.join(import_os46.default.homedir(), ".node9", "credentials.json"));
|
|
49451
49710
|
if (!creds) {
|
|
49452
49711
|
warn("Not logged in \u2014 audit rows stay local", "Run: node9 login <api-key>");
|
|
49453
49712
|
} else if (!cfg.settings.approvers.cloud) {
|
|
@@ -49497,8 +49756,8 @@ function registerDoctorCommand(program2, version2) {
|
|
|
49497
49756
|
|
|
49498
49757
|
// src/cli/commands/audit.ts
|
|
49499
49758
|
var import_chalk12 = __toESM(require("chalk"));
|
|
49500
|
-
var
|
|
49501
|
-
var
|
|
49759
|
+
var import_fs53 = __toESM(require("fs"));
|
|
49760
|
+
var import_path51 = __toESM(require("path"));
|
|
49502
49761
|
init_decision();
|
|
49503
49762
|
var import_os47 = __toESM(require("os"));
|
|
49504
49763
|
function formatRelativeTime(timestamp) {
|
|
@@ -49513,14 +49772,14 @@ function formatRelativeTime(timestamp) {
|
|
|
49513
49772
|
}
|
|
49514
49773
|
function registerAuditCommand(program2) {
|
|
49515
49774
|
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) => {
|
|
49516
|
-
const logPath =
|
|
49517
|
-
if (!
|
|
49775
|
+
const logPath = import_path51.default.join(import_os47.default.homedir(), ".node9", "audit.log");
|
|
49776
|
+
if (!import_fs53.default.existsSync(logPath)) {
|
|
49518
49777
|
console.log(
|
|
49519
49778
|
import_chalk12.default.yellow("No audit logs found. Run node9 with an agent to generate entries.")
|
|
49520
49779
|
);
|
|
49521
49780
|
return;
|
|
49522
49781
|
}
|
|
49523
|
-
const raw =
|
|
49782
|
+
const raw = import_fs53.default.readFileSync(logPath, "utf-8");
|
|
49524
49783
|
const lines = raw.split("\n").filter((l) => l.trim() !== "");
|
|
49525
49784
|
let entries = lines.flatMap((line) => {
|
|
49526
49785
|
try {
|
|
@@ -49582,9 +49841,9 @@ function registerAuditCommand(program2) {
|
|
|
49582
49841
|
var import_chalk13 = __toESM(require("chalk"));
|
|
49583
49842
|
|
|
49584
49843
|
// src/cli/aggregate/report-audit.ts
|
|
49585
|
-
var
|
|
49844
|
+
var import_fs54 = __toESM(require("fs"));
|
|
49586
49845
|
var import_os48 = __toESM(require("os"));
|
|
49587
|
-
var
|
|
49846
|
+
var import_path52 = __toESM(require("path"));
|
|
49588
49847
|
init_costSync();
|
|
49589
49848
|
init_litellm();
|
|
49590
49849
|
init_cost_codex();
|
|
@@ -49668,8 +49927,8 @@ function getDateRange(period, now) {
|
|
|
49668
49927
|
}
|
|
49669
49928
|
}
|
|
49670
49929
|
function parseAuditLog(logPath) {
|
|
49671
|
-
if (!
|
|
49672
|
-
const raw =
|
|
49930
|
+
if (!import_fs54.default.existsSync(logPath)) return [];
|
|
49931
|
+
const raw = import_fs54.default.readFileSync(logPath, "utf-8");
|
|
49673
49932
|
return raw.split("\n").flatMap((line) => {
|
|
49674
49933
|
if (!line.trim()) return [];
|
|
49675
49934
|
try {
|
|
@@ -49723,25 +49982,25 @@ function freezeClaudeCost(acc) {
|
|
|
49723
49982
|
};
|
|
49724
49983
|
}
|
|
49725
49984
|
function processClaudeCostProject(proj, projectsDir, start, end, acc) {
|
|
49726
|
-
const projPath =
|
|
49985
|
+
const projPath = import_path52.default.join(projectsDir, proj);
|
|
49727
49986
|
let files;
|
|
49728
49987
|
try {
|
|
49729
|
-
const stat =
|
|
49988
|
+
const stat = import_fs54.default.statSync(projPath);
|
|
49730
49989
|
if (!stat.isDirectory()) return;
|
|
49731
|
-
files =
|
|
49990
|
+
files = import_fs54.default.readdirSync(projPath).filter((f) => f.endsWith(".jsonl") && !f.startsWith("agent-"));
|
|
49732
49991
|
} catch {
|
|
49733
49992
|
return;
|
|
49734
49993
|
}
|
|
49735
49994
|
const startMs = start.getTime();
|
|
49736
49995
|
for (const file of files) {
|
|
49737
|
-
const filePath =
|
|
49996
|
+
const filePath = import_path52.default.join(projPath, file);
|
|
49738
49997
|
try {
|
|
49739
|
-
if (
|
|
49998
|
+
if (import_fs54.default.statSync(filePath).mtimeMs < startMs) continue;
|
|
49740
49999
|
} catch {
|
|
49741
50000
|
continue;
|
|
49742
50001
|
}
|
|
49743
50002
|
try {
|
|
49744
|
-
const raw =
|
|
50003
|
+
const raw = import_fs54.default.readFileSync(filePath, "utf-8");
|
|
49745
50004
|
for (const line of raw.split("\n")) {
|
|
49746
50005
|
if (!line.trim()) continue;
|
|
49747
50006
|
let entry;
|
|
@@ -49791,10 +50050,10 @@ function processClaudeCostProject(proj, projectsDir, start, end, acc) {
|
|
|
49791
50050
|
}
|
|
49792
50051
|
function loadClaudeCost(start, end, projectsDir) {
|
|
49793
50052
|
const acc = emptyClaudeCostAccumulator();
|
|
49794
|
-
if (!
|
|
50053
|
+
if (!import_fs54.default.existsSync(projectsDir)) return freezeClaudeCost(acc);
|
|
49795
50054
|
let dirs;
|
|
49796
50055
|
try {
|
|
49797
|
-
dirs =
|
|
50056
|
+
dirs = import_fs54.default.readdirSync(projectsDir);
|
|
49798
50057
|
} catch {
|
|
49799
50058
|
return freezeClaudeCost(acc);
|
|
49800
50059
|
}
|
|
@@ -49806,7 +50065,7 @@ function loadClaudeCost(start, end, projectsDir) {
|
|
|
49806
50065
|
function processCodexCostFile(filePath, start, end, acc) {
|
|
49807
50066
|
let lines;
|
|
49808
50067
|
try {
|
|
49809
|
-
lines =
|
|
50068
|
+
lines = import_fs54.default.readFileSync(filePath, "utf-8").split("\n");
|
|
49810
50069
|
} catch {
|
|
49811
50070
|
return;
|
|
49812
50071
|
}
|
|
@@ -49861,31 +50120,31 @@ function processCodexCostFile(filePath, start, end, acc) {
|
|
|
49861
50120
|
}
|
|
49862
50121
|
function listCodexSessionFiles2(sessionsBase) {
|
|
49863
50122
|
const jsonlFiles = [];
|
|
49864
|
-
if (!
|
|
50123
|
+
if (!import_fs54.default.existsSync(sessionsBase)) return jsonlFiles;
|
|
49865
50124
|
try {
|
|
49866
|
-
for (const year of
|
|
49867
|
-
const yearPath =
|
|
50125
|
+
for (const year of import_fs54.default.readdirSync(sessionsBase)) {
|
|
50126
|
+
const yearPath = import_path52.default.join(sessionsBase, year);
|
|
49868
50127
|
try {
|
|
49869
|
-
if (!
|
|
50128
|
+
if (!import_fs54.default.statSync(yearPath).isDirectory()) continue;
|
|
49870
50129
|
} catch {
|
|
49871
50130
|
continue;
|
|
49872
50131
|
}
|
|
49873
|
-
for (const month of
|
|
49874
|
-
const monthPath =
|
|
50132
|
+
for (const month of import_fs54.default.readdirSync(yearPath)) {
|
|
50133
|
+
const monthPath = import_path52.default.join(yearPath, month);
|
|
49875
50134
|
try {
|
|
49876
|
-
if (!
|
|
50135
|
+
if (!import_fs54.default.statSync(monthPath).isDirectory()) continue;
|
|
49877
50136
|
} catch {
|
|
49878
50137
|
continue;
|
|
49879
50138
|
}
|
|
49880
|
-
for (const day of
|
|
49881
|
-
const dayPath =
|
|
50139
|
+
for (const day of import_fs54.default.readdirSync(monthPath)) {
|
|
50140
|
+
const dayPath = import_path52.default.join(monthPath, day);
|
|
49882
50141
|
try {
|
|
49883
|
-
if (!
|
|
50142
|
+
if (!import_fs54.default.statSync(dayPath).isDirectory()) continue;
|
|
49884
50143
|
} catch {
|
|
49885
50144
|
continue;
|
|
49886
50145
|
}
|
|
49887
|
-
for (const file of
|
|
49888
|
-
if (file.endsWith(".jsonl")) jsonlFiles.push(
|
|
50146
|
+
for (const file of import_fs54.default.readdirSync(dayPath)) {
|
|
50147
|
+
if (file.endsWith(".jsonl")) jsonlFiles.push(import_path52.default.join(dayPath, file));
|
|
49889
50148
|
}
|
|
49890
50149
|
}
|
|
49891
50150
|
}
|
|
@@ -49950,13 +50209,13 @@ function freezeGeminiCost(acc) {
|
|
|
49950
50209
|
function processGeminiCostFile(filePath, projectKey, start, end, acc) {
|
|
49951
50210
|
const startMs = start.getTime();
|
|
49952
50211
|
try {
|
|
49953
|
-
if (
|
|
50212
|
+
if (import_fs54.default.statSync(filePath).mtimeMs < startMs) return;
|
|
49954
50213
|
} catch {
|
|
49955
50214
|
return;
|
|
49956
50215
|
}
|
|
49957
50216
|
let raw;
|
|
49958
50217
|
try {
|
|
49959
|
-
raw =
|
|
50218
|
+
raw = import_fs54.default.readFileSync(filePath, "utf-8");
|
|
49960
50219
|
} catch {
|
|
49961
50220
|
return;
|
|
49962
50221
|
}
|
|
@@ -50005,30 +50264,30 @@ function listGeminiSessionFiles2(geminiTmpDir2) {
|
|
|
50005
50264
|
const out = [];
|
|
50006
50265
|
let dirs;
|
|
50007
50266
|
try {
|
|
50008
|
-
if (!
|
|
50009
|
-
dirs =
|
|
50267
|
+
if (!import_fs54.default.statSync(geminiTmpDir2).isDirectory()) return out;
|
|
50268
|
+
dirs = import_fs54.default.readdirSync(geminiTmpDir2);
|
|
50010
50269
|
} catch {
|
|
50011
50270
|
return out;
|
|
50012
50271
|
}
|
|
50013
50272
|
for (const proj of dirs) {
|
|
50014
|
-
const chatsDir =
|
|
50273
|
+
const chatsDir = import_path52.default.join(geminiTmpDir2, proj, "chats");
|
|
50015
50274
|
let files;
|
|
50016
50275
|
try {
|
|
50017
|
-
if (!
|
|
50018
|
-
files =
|
|
50276
|
+
if (!import_fs54.default.statSync(chatsDir).isDirectory()) continue;
|
|
50277
|
+
files = import_fs54.default.readdirSync(chatsDir);
|
|
50019
50278
|
} catch {
|
|
50020
50279
|
continue;
|
|
50021
50280
|
}
|
|
50022
50281
|
for (const f of files) {
|
|
50023
50282
|
if (!f.endsWith(".jsonl")) continue;
|
|
50024
|
-
out.push({ projectKey: proj, file:
|
|
50283
|
+
out.push({ projectKey: proj, file: import_path52.default.join(chatsDir, f) });
|
|
50025
50284
|
}
|
|
50026
50285
|
}
|
|
50027
50286
|
return out;
|
|
50028
50287
|
}
|
|
50029
50288
|
function loadGeminiCost(start, end, geminiTmpDir2) {
|
|
50030
50289
|
const acc = emptyGeminiAccumulator();
|
|
50031
|
-
if (!
|
|
50290
|
+
if (!import_fs54.default.existsSync(geminiTmpDir2)) return freezeGeminiCost(acc);
|
|
50032
50291
|
for (const { projectKey, file } of listGeminiSessionFiles2(geminiTmpDir2)) {
|
|
50033
50292
|
processGeminiCostFile(file, projectKey, start, end, acc);
|
|
50034
50293
|
}
|
|
@@ -50046,11 +50305,11 @@ function dimensionOfBlock(checkedBy, ruleName) {
|
|
|
50046
50305
|
}
|
|
50047
50306
|
function aggregateReportFromAudit(period, opts = {}) {
|
|
50048
50307
|
const now = opts.now ?? /* @__PURE__ */ new Date();
|
|
50049
|
-
const auditLogPath = opts.auditLogPath ??
|
|
50050
|
-
const claudeProjectsDir = opts.claudeProjectsDir ??
|
|
50051
|
-
const codexSessionsDir2 = opts.codexSessionsDir ??
|
|
50052
|
-
const geminiTmpDir2 = opts.geminiTmpDir ??
|
|
50053
|
-
const hasAuditFile =
|
|
50308
|
+
const auditLogPath = opts.auditLogPath ?? import_path52.default.join(import_os48.default.homedir(), ".node9", "audit.log");
|
|
50309
|
+
const claudeProjectsDir = opts.claudeProjectsDir ?? import_path52.default.join(import_os48.default.homedir(), ".claude", "projects");
|
|
50310
|
+
const codexSessionsDir2 = opts.codexSessionsDir ?? import_path52.default.join(import_os48.default.homedir(), ".codex", "sessions");
|
|
50311
|
+
const geminiTmpDir2 = opts.geminiTmpDir ?? import_path52.default.join(import_os48.default.homedir(), ".gemini", "tmp");
|
|
50312
|
+
const hasAuditFile = import_fs54.default.existsSync(auditLogPath);
|
|
50054
50313
|
const allEntries = opts.preloadedAuditEntries ?? parseAuditLog(auditLogPath);
|
|
50055
50314
|
const unackedDlp = allEntries.filter((e) => e.source === "response-dlp");
|
|
50056
50315
|
const { start, end } = getDateRange(period, now);
|
|
@@ -50759,7 +51018,8 @@ function renderTerminalReport(data, responseDlpEntries, excludeTests) {
|
|
|
50759
51018
|
// src/cli/commands/daemon-cmd.ts
|
|
50760
51019
|
var import_chalk14 = __toESM(require("chalk"));
|
|
50761
51020
|
var import_child_process9 = require("child_process");
|
|
50762
|
-
|
|
51021
|
+
init_daemon();
|
|
51022
|
+
var import_fs55 = __toESM(require("fs"));
|
|
50763
51023
|
init_startup_log();
|
|
50764
51024
|
init_daemon2();
|
|
50765
51025
|
var VALID_ACTIONS = "start | stop | restart | status | install | uninstall";
|
|
@@ -50798,7 +51058,10 @@ function registerDaemonCommand(program2) {
|
|
|
50798
51058
|
if (cmd === "stop") return stopDaemon();
|
|
50799
51059
|
if (cmd === "restart") {
|
|
50800
51060
|
stopDaemon();
|
|
50801
|
-
|
|
51061
|
+
for (let i = 0; i < 15; i++) {
|
|
51062
|
+
if (!await isDaemonReachable(300)) break;
|
|
51063
|
+
await new Promise((r) => setTimeout(r, 200));
|
|
51064
|
+
}
|
|
50802
51065
|
const restartFd = openStartupLogFd();
|
|
50803
51066
|
recordStartupState("starting");
|
|
50804
51067
|
const child = (0, import_child_process9.spawn)(process.execPath, [process.argv[1], "daemon"], {
|
|
@@ -50813,7 +51076,7 @@ function registerDaemonCommand(program2) {
|
|
|
50813
51076
|
child.unref();
|
|
50814
51077
|
if (restartFd !== void 0) {
|
|
50815
51078
|
try {
|
|
50816
|
-
|
|
51079
|
+
import_fs55.default.closeSync(restartFd);
|
|
50817
51080
|
} catch {
|
|
50818
51081
|
}
|
|
50819
51082
|
}
|
|
@@ -50864,7 +51127,7 @@ function registerDaemonCommand(program2) {
|
|
|
50864
51127
|
} finally {
|
|
50865
51128
|
if (startupFd !== void 0) {
|
|
50866
51129
|
try {
|
|
50867
|
-
|
|
51130
|
+
import_fs55.default.closeSync(startupFd);
|
|
50868
51131
|
} catch {
|
|
50869
51132
|
}
|
|
50870
51133
|
}
|
|
@@ -50878,11 +51141,12 @@ function registerDaemonCommand(program2) {
|
|
|
50878
51141
|
|
|
50879
51142
|
// src/cli/commands/status.ts
|
|
50880
51143
|
var import_chalk15 = __toESM(require("chalk"));
|
|
50881
|
-
var
|
|
50882
|
-
var
|
|
51144
|
+
var import_fs56 = __toESM(require("fs"));
|
|
51145
|
+
var import_path53 = __toESM(require("path"));
|
|
50883
51146
|
var import_os49 = __toESM(require("os"));
|
|
50884
51147
|
init_core();
|
|
50885
51148
|
init_daemon();
|
|
51149
|
+
init_build_id();
|
|
50886
51150
|
init_agent_wiring();
|
|
50887
51151
|
init_sync();
|
|
50888
51152
|
init_service();
|
|
@@ -50906,7 +51170,7 @@ function printAgentSection(label2, hookPairs, wrapped) {
|
|
|
50906
51170
|
}
|
|
50907
51171
|
}
|
|
50908
51172
|
function registerStatusCommand(program2) {
|
|
50909
|
-
program2.command("status").description("Show current Node9 mode, policy source, and persistent decisions").action(() => {
|
|
51173
|
+
program2.command("status").description("Show current Node9 mode, policy source, and persistent decisions").action(async () => {
|
|
50910
51174
|
const creds = getCredentials();
|
|
50911
51175
|
const daemonRunning = isDaemonRunning();
|
|
50912
51176
|
const mergedConfig = getConfig();
|
|
@@ -50937,6 +51201,14 @@ function registerStatusCommand(program2) {
|
|
|
50937
51201
|
console.log(
|
|
50938
51202
|
import_chalk15.default.green(" \u25CF Daemon running") + import_chalk15.default.gray(` \u2192 http://127.0.0.1:${DAEMON_PORT}/`)
|
|
50939
51203
|
);
|
|
51204
|
+
const probe = await probeDaemonHealth();
|
|
51205
|
+
const drift = describeBuildDrift(
|
|
51206
|
+
probe.kind === "health" ? probe.health : probe.kind === "no-health" ? "no-health" : null,
|
|
51207
|
+
CURRENT_BUILD
|
|
51208
|
+
);
|
|
51209
|
+
if (drift) {
|
|
51210
|
+
console.log(import_chalk15.default.yellow(` \u26A0 ${drift}`) + import_chalk15.default.gray(" \u2014 run: node9 doctor"));
|
|
51211
|
+
}
|
|
50940
51212
|
} else {
|
|
50941
51213
|
console.log(import_chalk15.default.gray(" \u25CB Daemon stopped"));
|
|
50942
51214
|
}
|
|
@@ -50958,13 +51230,13 @@ function registerStatusCommand(program2) {
|
|
|
50958
51230
|
console.log("");
|
|
50959
51231
|
const modeLabel = settings.mode === "audit" ? import_chalk15.default.blue("audit") : settings.mode === "strict" ? import_chalk15.default.red("strict") : import_chalk15.default.white("standard");
|
|
50960
51232
|
console.log(` Mode: ${modeLabel}`);
|
|
50961
|
-
const projectConfig =
|
|
50962
|
-
const globalConfig =
|
|
51233
|
+
const projectConfig = import_path53.default.join(process.cwd(), "node9.config.json");
|
|
51234
|
+
const globalConfig = import_path53.default.join(import_os49.default.homedir(), ".node9", "config.json");
|
|
50963
51235
|
console.log(
|
|
50964
|
-
` Local: ${
|
|
51236
|
+
` Local: ${import_fs56.default.existsSync(projectConfig) ? import_chalk15.default.green("Active (node9.config.json)") : import_chalk15.default.gray("Not present")}`
|
|
50965
51237
|
);
|
|
50966
51238
|
console.log(
|
|
50967
|
-
` Global: ${
|
|
51239
|
+
` Global: ${import_fs56.default.existsSync(globalConfig) ? import_chalk15.default.green("Active (~/.node9/config.json)") : import_chalk15.default.gray("Not present")}`
|
|
50968
51240
|
);
|
|
50969
51241
|
if (mergedConfig.policy.sandboxPaths.length > 0) {
|
|
50970
51242
|
console.log(
|
|
@@ -51006,8 +51278,8 @@ function registerStatusCommand(program2) {
|
|
|
51006
51278
|
|
|
51007
51279
|
// src/cli/commands/init.ts
|
|
51008
51280
|
var import_chalk16 = __toESM(require("chalk"));
|
|
51009
|
-
var
|
|
51010
|
-
var
|
|
51281
|
+
var import_fs57 = __toESM(require("fs"));
|
|
51282
|
+
var import_path54 = __toESM(require("path"));
|
|
51011
51283
|
var import_os50 = __toESM(require("os"));
|
|
51012
51284
|
var import_https6 = __toESM(require("https"));
|
|
51013
51285
|
init_core();
|
|
@@ -51099,16 +51371,16 @@ function registerInitCommand(program2) {
|
|
|
51099
51371
|
}
|
|
51100
51372
|
console.log("");
|
|
51101
51373
|
}
|
|
51102
|
-
const configPath =
|
|
51103
|
-
const isFirstInstall = !
|
|
51104
|
-
if (
|
|
51374
|
+
const configPath = import_path54.default.join(import_os50.default.homedir(), ".node9", "config.json");
|
|
51375
|
+
const isFirstInstall = !import_fs57.default.existsSync(configPath);
|
|
51376
|
+
if (import_fs57.default.existsSync(configPath) && !options.force) {
|
|
51105
51377
|
try {
|
|
51106
|
-
const existing = JSON.parse(
|
|
51378
|
+
const existing = JSON.parse(import_fs57.default.readFileSync(configPath, "utf-8"));
|
|
51107
51379
|
const settings = existing.settings ?? {};
|
|
51108
51380
|
if (settings.mode !== chosenMode) {
|
|
51109
51381
|
settings.mode = chosenMode;
|
|
51110
51382
|
existing.settings = settings;
|
|
51111
|
-
|
|
51383
|
+
import_fs57.default.writeFileSync(configPath, JSON.stringify(existing, null, 2) + "\n");
|
|
51112
51384
|
console.log(import_chalk16.default.green(`\u2705 Mode updated: ${chosenMode}`));
|
|
51113
51385
|
} else {
|
|
51114
51386
|
console.log(import_chalk16.default.blue(`\u2139\uFE0F Config already exists: ${configPath}`));
|
|
@@ -51121,9 +51393,9 @@ function registerInitCommand(program2) {
|
|
|
51121
51393
|
...DEFAULT_CONFIG,
|
|
51122
51394
|
settings: { ...DEFAULT_CONFIG.settings, mode: chosenMode }
|
|
51123
51395
|
};
|
|
51124
|
-
const dir =
|
|
51125
|
-
if (!
|
|
51126
|
-
|
|
51396
|
+
const dir = import_path54.default.dirname(configPath);
|
|
51397
|
+
if (!import_fs57.default.existsSync(dir)) import_fs57.default.mkdirSync(dir, { recursive: true });
|
|
51398
|
+
import_fs57.default.writeFileSync(configPath, JSON.stringify(configToSave, null, 2) + "\n");
|
|
51127
51399
|
console.log(import_chalk16.default.green(`\u2705 Config created: ${configPath}`));
|
|
51128
51400
|
console.log(import_chalk16.default.gray(` Mode: ${chosenMode}`));
|
|
51129
51401
|
}
|
|
@@ -51223,14 +51495,14 @@ function registerInitCommand(program2) {
|
|
|
51223
51495
|
|
|
51224
51496
|
// src/cli/commands/heal.ts
|
|
51225
51497
|
var import_chalk17 = __toESM(require("chalk"));
|
|
51226
|
-
var
|
|
51498
|
+
var import_fs58 = __toESM(require("fs"));
|
|
51227
51499
|
init_agent_wiring();
|
|
51228
51500
|
init_setup();
|
|
51229
51501
|
init_hook_baseline();
|
|
51230
51502
|
var hasHookSurface = (a) => a.hooks.length > 0;
|
|
51231
51503
|
function backupForHeal(file) {
|
|
51232
51504
|
try {
|
|
51233
|
-
if (file &&
|
|
51505
|
+
if (file && import_fs58.default.existsSync(file)) import_fs58.default.copyFileSync(file, `${file}.node9-heal-bak`);
|
|
51234
51506
|
} catch {
|
|
51235
51507
|
}
|
|
51236
51508
|
}
|
|
@@ -51397,7 +51669,7 @@ function registerConnectCommand(program2) {
|
|
|
51397
51669
|
}
|
|
51398
51670
|
|
|
51399
51671
|
// src/cli/commands/undo.ts
|
|
51400
|
-
var
|
|
51672
|
+
var import_path55 = __toESM(require("path"));
|
|
51401
51673
|
var import_chalk20 = __toESM(require("chalk"));
|
|
51402
51674
|
|
|
51403
51675
|
// src/tui/undo-navigator.ts
|
|
@@ -51556,7 +51828,7 @@ function findMatchingCwd(startDir, history) {
|
|
|
51556
51828
|
let dir = startDir;
|
|
51557
51829
|
while (true) {
|
|
51558
51830
|
if (cwds.has(dir)) return dir;
|
|
51559
|
-
const parent =
|
|
51831
|
+
const parent = import_path55.default.dirname(dir);
|
|
51560
51832
|
if (parent === dir) return null;
|
|
51561
51833
|
dir = parent;
|
|
51562
51834
|
}
|
|
@@ -52190,9 +52462,9 @@ function registerMcpGatewayCommand(program2) {
|
|
|
52190
52462
|
|
|
52191
52463
|
// src/mcp-server/index.ts
|
|
52192
52464
|
var import_readline5 = __toESM(require("readline"));
|
|
52193
|
-
var
|
|
52465
|
+
var import_fs60 = __toESM(require("fs"));
|
|
52194
52466
|
var import_os52 = __toESM(require("os"));
|
|
52195
|
-
var
|
|
52467
|
+
var import_path57 = __toESM(require("path"));
|
|
52196
52468
|
var import_child_process11 = require("child_process");
|
|
52197
52469
|
init_decision();
|
|
52198
52470
|
init_core();
|
|
@@ -52200,9 +52472,9 @@ init_daemon();
|
|
|
52200
52472
|
init_shields();
|
|
52201
52473
|
|
|
52202
52474
|
// src/auth/egress-config.ts
|
|
52203
|
-
var
|
|
52475
|
+
var import_fs59 = __toESM(require("fs"));
|
|
52204
52476
|
var import_os51 = __toESM(require("os"));
|
|
52205
|
-
var
|
|
52477
|
+
var import_path56 = __toESM(require("path"));
|
|
52206
52478
|
var DEFAULT_EGRESS = {
|
|
52207
52479
|
enabled: false,
|
|
52208
52480
|
mode: "review",
|
|
@@ -52211,12 +52483,12 @@ var DEFAULT_EGRESS = {
|
|
|
52211
52483
|
allowPrivate: true
|
|
52212
52484
|
};
|
|
52213
52485
|
function egressConfigPath() {
|
|
52214
|
-
return
|
|
52486
|
+
return import_path56.default.join(import_os51.default.homedir(), ".node9", "config.json");
|
|
52215
52487
|
}
|
|
52216
52488
|
function readEgressRawConfig() {
|
|
52217
52489
|
let text;
|
|
52218
52490
|
try {
|
|
52219
|
-
text =
|
|
52491
|
+
text = import_fs59.default.readFileSync(egressConfigPath(), "utf8");
|
|
52220
52492
|
} catch (err2) {
|
|
52221
52493
|
if (err2.code === "ENOENT") return {};
|
|
52222
52494
|
throw err2;
|
|
@@ -52231,8 +52503,8 @@ function readEgressRawConfig() {
|
|
|
52231
52503
|
}
|
|
52232
52504
|
function writeEgressRawConfig(config) {
|
|
52233
52505
|
const p = egressConfigPath();
|
|
52234
|
-
|
|
52235
|
-
|
|
52506
|
+
import_fs59.default.mkdirSync(import_path56.default.dirname(p), { recursive: true });
|
|
52507
|
+
import_fs59.default.writeFileSync(p, JSON.stringify(config, null, 2) + "\n", { mode: 384 });
|
|
52236
52508
|
}
|
|
52237
52509
|
function applyEgress(config, change) {
|
|
52238
52510
|
const policy = config.policy = config.policy ?? {};
|
|
@@ -52617,13 +52889,13 @@ function handleStatus() {
|
|
|
52617
52889
|
lines.push(`Active shields: ${activeShields.length > 0 ? activeShields.join(", ") : "none"}`);
|
|
52618
52890
|
lines.push(`Smart rules: ${config.policy.smartRules.length} loaded`);
|
|
52619
52891
|
lines.push(`DLP: ${config.policy.dlp?.enabled !== false ? "enabled" : "disabled"}`);
|
|
52620
|
-
const projectConfig =
|
|
52621
|
-
const globalConfig =
|
|
52892
|
+
const projectConfig = import_path57.default.join(process.cwd(), "node9.config.json");
|
|
52893
|
+
const globalConfig = import_path57.default.join(import_os52.default.homedir(), ".node9", "config.json");
|
|
52622
52894
|
lines.push(
|
|
52623
|
-
`Project config (node9.config.json): ${
|
|
52895
|
+
`Project config (node9.config.json): ${import_fs60.default.existsSync(projectConfig) ? "present" : "not found"}`
|
|
52624
52896
|
);
|
|
52625
52897
|
lines.push(
|
|
52626
|
-
`Global config (~/.node9/config.json): ${
|
|
52898
|
+
`Global config (~/.node9/config.json): ${import_fs60.default.existsSync(globalConfig) ? "present" : "not found"}`
|
|
52627
52899
|
);
|
|
52628
52900
|
return lines.join("\n");
|
|
52629
52901
|
}
|
|
@@ -52729,21 +53001,21 @@ function handleEgressDeny(args) {
|
|
|
52729
53001
|
addEgressHost("deny", host);
|
|
52730
53002
|
return `Denied egress to ${host} (deny always wins over allow).`;
|
|
52731
53003
|
}
|
|
52732
|
-
var GLOBAL_CONFIG_PATH =
|
|
53004
|
+
var GLOBAL_CONFIG_PATH = import_path57.default.join(import_os52.default.homedir(), ".node9", "config.json");
|
|
52733
53005
|
var APPROVER_CHANNELS = ["native", "browser", "cloud", "terminal"];
|
|
52734
53006
|
function readGlobalConfigRaw() {
|
|
52735
53007
|
try {
|
|
52736
|
-
if (
|
|
52737
|
-
return JSON.parse(
|
|
53008
|
+
if (import_fs60.default.existsSync(GLOBAL_CONFIG_PATH)) {
|
|
53009
|
+
return JSON.parse(import_fs60.default.readFileSync(GLOBAL_CONFIG_PATH, "utf-8"));
|
|
52738
53010
|
}
|
|
52739
53011
|
} catch {
|
|
52740
53012
|
}
|
|
52741
53013
|
return {};
|
|
52742
53014
|
}
|
|
52743
53015
|
function writeGlobalConfigRaw(data) {
|
|
52744
|
-
const dir =
|
|
52745
|
-
if (!
|
|
52746
|
-
|
|
53016
|
+
const dir = import_path57.default.dirname(GLOBAL_CONFIG_PATH);
|
|
53017
|
+
if (!import_fs60.default.existsSync(dir)) import_fs60.default.mkdirSync(dir, { recursive: true });
|
|
53018
|
+
import_fs60.default.writeFileSync(GLOBAL_CONFIG_PATH, JSON.stringify(data, null, 2) + "\n");
|
|
52747
53019
|
}
|
|
52748
53020
|
function handleApproverList() {
|
|
52749
53021
|
const config = getConfig();
|
|
@@ -52787,9 +53059,9 @@ function handleApproverSet(args) {
|
|
|
52787
53059
|
function handleAuditGet(args) {
|
|
52788
53060
|
const limit = Math.min(typeof args.limit === "number" ? args.limit : 20, 100);
|
|
52789
53061
|
const filter = typeof args.filter === "string" && args.filter !== "all" ? args.filter : null;
|
|
52790
|
-
const auditPath =
|
|
52791
|
-
if (!
|
|
52792
|
-
const rawLines =
|
|
53062
|
+
const auditPath = import_path57.default.join(import_os52.default.homedir(), ".node9", "audit.log");
|
|
53063
|
+
if (!import_fs60.default.existsSync(auditPath)) return "No audit log found.";
|
|
53064
|
+
const rawLines = import_fs60.default.readFileSync(auditPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
52793
53065
|
const wanted = filter === "block" ? "deny" : filter;
|
|
52794
53066
|
const parsed = [];
|
|
52795
53067
|
for (const line of rawLines) {
|
|
@@ -53165,7 +53437,7 @@ function registerTrustCommand(program2) {
|
|
|
53165
53437
|
// src/cli/commands/mcp-pin.ts
|
|
53166
53438
|
var import_chalk24 = __toESM(require("chalk"));
|
|
53167
53439
|
init_mcp_pin();
|
|
53168
|
-
var
|
|
53440
|
+
var import_fs61 = __toESM(require("fs"));
|
|
53169
53441
|
|
|
53170
53442
|
// src/cli/commands/mcp-gateway-cmd.ts
|
|
53171
53443
|
var import_chalk23 = __toESM(require("chalk"));
|
|
@@ -53373,7 +53645,7 @@ function registerMcpPinCommand(program2) {
|
|
|
53373
53645
|
let repoCorrupt = false;
|
|
53374
53646
|
if (found.source === "repo") {
|
|
53375
53647
|
try {
|
|
53376
|
-
const raw =
|
|
53648
|
+
const raw = import_fs61.default.readFileSync(found.path, "utf-8");
|
|
53377
53649
|
const parsed = JSON.parse(raw);
|
|
53378
53650
|
repoEntries = parsed.servers ?? {};
|
|
53379
53651
|
} catch {
|
|
@@ -53966,8 +54238,8 @@ function registerPostureCommand(program2) {
|
|
|
53966
54238
|
var import_chalk30 = __toESM(require("chalk"));
|
|
53967
54239
|
|
|
53968
54240
|
// src/ci-check/fetch.ts
|
|
53969
|
-
var
|
|
53970
|
-
var
|
|
54241
|
+
var import_fs62 = __toESM(require("fs"));
|
|
54242
|
+
var import_path58 = __toESM(require("path"));
|
|
53971
54243
|
var import_node_child_process = require("child_process");
|
|
53972
54244
|
var import_undici = __toESM(require_undici());
|
|
53973
54245
|
var cachedGhToken;
|
|
@@ -54051,7 +54323,7 @@ function parseRepoUrl(input) {
|
|
|
54051
54323
|
function isLocalPath(input) {
|
|
54052
54324
|
if (input.startsWith(".") || input.startsWith("/") || input.startsWith("~")) return true;
|
|
54053
54325
|
try {
|
|
54054
|
-
return
|
|
54326
|
+
return import_fs62.default.existsSync(input) && import_fs62.default.statSync(input).isDirectory();
|
|
54055
54327
|
} catch {
|
|
54056
54328
|
return false;
|
|
54057
54329
|
}
|
|
@@ -54166,10 +54438,10 @@ function readLocalTree(dir) {
|
|
|
54166
54438
|
const files = [];
|
|
54167
54439
|
const notes = [];
|
|
54168
54440
|
const add = (rel) => {
|
|
54169
|
-
const abs =
|
|
54441
|
+
const abs = import_path58.default.join(root, rel);
|
|
54170
54442
|
try {
|
|
54171
|
-
if (
|
|
54172
|
-
files.push({ path: rel, content:
|
|
54443
|
+
if (import_fs62.default.existsSync(abs) && import_fs62.default.statSync(abs).isFile()) {
|
|
54444
|
+
files.push({ path: rel, content: import_fs62.default.readFileSync(abs, "utf8") });
|
|
54173
54445
|
}
|
|
54174
54446
|
} catch {
|
|
54175
54447
|
}
|
|
@@ -54189,7 +54461,7 @@ function readLocalTree(dir) {
|
|
|
54189
54461
|
dirsVisited++;
|
|
54190
54462
|
let entries;
|
|
54191
54463
|
try {
|
|
54192
|
-
entries =
|
|
54464
|
+
entries = import_fs62.default.readdirSync(import_path58.default.join(root, relDir), { withFileTypes: true });
|
|
54193
54465
|
} catch {
|
|
54194
54466
|
return;
|
|
54195
54467
|
}
|
|
@@ -54210,11 +54482,11 @@ function readLocalTree(dir) {
|
|
|
54210
54482
|
`repo is large \u2014 some agent-surface files may be INCOMPLETE (capped at ${MAX_SURFACE_FILES} files / ${MAX_DIRS} dirs).`
|
|
54211
54483
|
);
|
|
54212
54484
|
for (const rel of matches) collect(rel);
|
|
54213
|
-
const wfDir =
|
|
54485
|
+
const wfDir = import_path58.default.join(root, WORKFLOW_DIR);
|
|
54214
54486
|
try {
|
|
54215
|
-
if (
|
|
54216
|
-
for (const name of
|
|
54217
|
-
if (/\.ya?ml$/.test(name)) add(
|
|
54487
|
+
if (import_fs62.default.existsSync(wfDir)) {
|
|
54488
|
+
for (const name of import_fs62.default.readdirSync(wfDir)) {
|
|
54489
|
+
if (/\.ya?ml$/.test(name)) add(import_path58.default.join(WORKFLOW_DIR, name));
|
|
54218
54490
|
}
|
|
54219
54491
|
}
|
|
54220
54492
|
} catch {
|
|
@@ -54519,7 +54791,7 @@ function severityFromScore(score) {
|
|
|
54519
54791
|
if (score >= 1) return "advisory";
|
|
54520
54792
|
return null;
|
|
54521
54793
|
}
|
|
54522
|
-
function analyzeWorkflow(
|
|
54794
|
+
function analyzeWorkflow(path72, content) {
|
|
54523
54795
|
let raw;
|
|
54524
54796
|
try {
|
|
54525
54797
|
raw = (0, import_yaml.parse)(content) ?? {};
|
|
@@ -54645,7 +54917,7 @@ function analyzeWorkflow(path71, content) {
|
|
|
54645
54917
|
dimension: "workflows",
|
|
54646
54918
|
severity,
|
|
54647
54919
|
title,
|
|
54648
|
-
file:
|
|
54920
|
+
file: path72,
|
|
54649
54921
|
signals,
|
|
54650
54922
|
mitigations: mitigations.length ? mitigations : void 0,
|
|
54651
54923
|
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) \u2014 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 \u2014 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."
|
|
@@ -54721,7 +54993,7 @@ function evalAgentJob(job, wf, raw, untrustedTrigger, reusable) {
|
|
|
54721
54993
|
if (reusable && !loadedGun && SEVERITY_RANK2[severity] > SEVERITY_RANK2.medium) severity = "medium";
|
|
54722
54994
|
return { severity, secrets, injectable, canReadEnv };
|
|
54723
54995
|
}
|
|
54724
|
-
function analyzeWorkflowSecrets(
|
|
54996
|
+
function analyzeWorkflowSecrets(path72, content) {
|
|
54725
54997
|
let raw;
|
|
54726
54998
|
try {
|
|
54727
54999
|
raw = (0, import_yaml.parse)(content) ?? {};
|
|
@@ -54741,7 +55013,7 @@ function analyzeWorkflowSecrets(path71, content) {
|
|
|
54741
55013
|
dimension: "data",
|
|
54742
55014
|
severity: worst.severity,
|
|
54743
55015
|
title: worst.severity === "advisory" ? "Secrets reachable by the agent \u2014 hardening" : "Exfiltratable secrets reachable by an injectable agent",
|
|
54744
|
-
file:
|
|
55016
|
+
file: path72,
|
|
54745
55017
|
signals: [
|
|
54746
55018
|
`agent can reach: ${worst.secrets.map((s) => s.name).join(", ")}`,
|
|
54747
55019
|
worst.injectable ? "the agent is externally triggerable (untrusted trigger, no gate)" : "gated / not externally triggerable \u2014 latent risk only",
|
|
@@ -54768,7 +55040,7 @@ function hookCommands(hooks) {
|
|
|
54768
55040
|
}
|
|
54769
55041
|
return out;
|
|
54770
55042
|
}
|
|
54771
|
-
function analyzeAgentConfig(
|
|
55043
|
+
function analyzeAgentConfig(path72, content) {
|
|
54772
55044
|
let cfg;
|
|
54773
55045
|
try {
|
|
54774
55046
|
cfg = JSON.parse(content);
|
|
@@ -54787,7 +55059,7 @@ function analyzeAgentConfig(path71, content) {
|
|
|
54787
55059
|
dimension: "toolRules",
|
|
54788
55060
|
severity: high ? "high" : "medium",
|
|
54789
55061
|
title: high ? "Agent hook runs UNPINNED/remote third-party code on every action" : "Agent hook runs third-party code in the agent hot path",
|
|
54790
|
-
file:
|
|
55062
|
+
file: path72,
|
|
54791
55063
|
signals: [
|
|
54792
55064
|
`hook command: \`${cmd.slice(0, 120)}\``,
|
|
54793
55065
|
remoteExec ? "fetch-and-run (curl|wget / pipe-to-shell) \u2014 unpinnable remote code execution on every contributor" : unpinned ? "unpinned \u2014 a compromised/yanked package = code execution on every contributor" : "pinned, but still a standing supply-chain dependency in the agent hot path"
|
|
@@ -54807,7 +55079,7 @@ function analyzeAgentConfig(path71, content) {
|
|
|
54807
55079
|
dimension: "toolRules",
|
|
54808
55080
|
severity: hasBackstop ? "medium" : "high",
|
|
54809
55081
|
title: hasBackstop ? "Committed agent config pre-authorizes broad tools" : "Committed agent config pre-authorizes broad tools with no deny backstop",
|
|
54810
|
-
file:
|
|
55082
|
+
file: path72,
|
|
54811
55083
|
signals: [
|
|
54812
55084
|
`broad allow(s): ${broad.slice(0, 5).join(", ")}`,
|
|
54813
55085
|
hasBackstop ? "a `deny` list backstops the broad allow" : "no `deny` entry covers Bash/Write/Edit \u2014 every contributor is pre-authorized for catastrophic tools"
|
|
@@ -54820,16 +55092,16 @@ function analyzeAgentConfig(path71, content) {
|
|
|
54820
55092
|
|
|
54821
55093
|
// src/ci-check/mcp.ts
|
|
54822
55094
|
init_dist();
|
|
54823
|
-
function analyzeMcp(
|
|
55095
|
+
function analyzeMcp(path72, content) {
|
|
54824
55096
|
let cfg;
|
|
54825
55097
|
try {
|
|
54826
55098
|
cfg = JSON.parse(content);
|
|
54827
55099
|
} catch {
|
|
54828
55100
|
return [];
|
|
54829
55101
|
}
|
|
54830
|
-
return analyzeMcpServers(cfg.mcpServers ?? {},
|
|
55102
|
+
return analyzeMcpServers(cfg.mcpServers ?? {}, path72);
|
|
54831
55103
|
}
|
|
54832
|
-
function analyzeMcpServers(servers,
|
|
55104
|
+
function analyzeMcpServers(servers, path72) {
|
|
54833
55105
|
const findings = [];
|
|
54834
55106
|
for (const [name, srv] of Object.entries(servers ?? {})) {
|
|
54835
55107
|
if (!srv || srv.disabled) continue;
|
|
@@ -54840,7 +55112,7 @@ function analyzeMcpServers(servers, path71) {
|
|
|
54840
55112
|
dimension: "mcp",
|
|
54841
55113
|
severity: "medium",
|
|
54842
55114
|
title: `MCP server "${name}" runs an unpinned executable`,
|
|
54843
|
-
file:
|
|
55115
|
+
file: path72,
|
|
54844
55116
|
signals: [`\`${argv.slice(0, 120)}\` \u2014 unversioned/@latest npx`],
|
|
54845
55117
|
fix: "Pin the MCP server package to an exact version so a PR (or a registry compromise) can\u2019t swap the toolchain."
|
|
54846
55118
|
});
|
|
@@ -54854,7 +55126,7 @@ function analyzeMcpServers(servers, path71) {
|
|
|
54854
55126
|
dimension: "mcp",
|
|
54855
55127
|
severity: "high",
|
|
54856
55128
|
title: `MCP server "${name}" has an inline credential`,
|
|
54857
|
-
file:
|
|
55129
|
+
file: path72,
|
|
54858
55130
|
signals: [
|
|
54859
55131
|
`env.${k} matches ${hit.patternName} \u2014 agent-reachable secret committed to the repo`
|
|
54860
55132
|
],
|
|
@@ -54868,7 +55140,7 @@ function analyzeMcpServers(servers, path71) {
|
|
|
54868
55140
|
|
|
54869
55141
|
// src/ci-check/codex.ts
|
|
54870
55142
|
var import_smol_toml5 = require("smol-toml");
|
|
54871
|
-
function analyzeCodexConfig(
|
|
55143
|
+
function analyzeCodexConfig(path72, content) {
|
|
54872
55144
|
let cfg;
|
|
54873
55145
|
try {
|
|
54874
55146
|
cfg = (0, import_smol_toml5.parse)(content);
|
|
@@ -54876,7 +55148,7 @@ function analyzeCodexConfig(path71, content) {
|
|
|
54876
55148
|
return [];
|
|
54877
55149
|
}
|
|
54878
55150
|
const findings = [];
|
|
54879
|
-
findings.push(...analyzeMcpServers(cfg.mcp_servers ?? {},
|
|
55151
|
+
findings.push(...analyzeMcpServers(cfg.mcp_servers ?? {}, path72));
|
|
54880
55152
|
const sandbox = typeof cfg.sandbox_mode === "string" ? cfg.sandbox_mode : "";
|
|
54881
55153
|
const approval = typeof cfg.approval_policy === "string" ? cfg.approval_policy : "";
|
|
54882
55154
|
const fullAccess = /danger-full-access/i.test(sandbox);
|
|
@@ -54891,7 +55163,7 @@ function analyzeCodexConfig(path71, content) {
|
|
|
54891
55163
|
dimension: "toolRules",
|
|
54892
55164
|
severity: fullAccess ? "high" : "medium",
|
|
54893
55165
|
title: fullAccess ? "Codex config grants a full-access sandbox" : "Codex config never requires approval",
|
|
54894
|
-
file:
|
|
55166
|
+
file: path72,
|
|
54895
55167
|
signals,
|
|
54896
55168
|
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.'
|
|
54897
55169
|
});
|
|
@@ -54947,10 +55219,10 @@ function decodeSuspiciousBase64(text) {
|
|
|
54947
55219
|
}
|
|
54948
55220
|
return out;
|
|
54949
55221
|
}
|
|
54950
|
-
function mk(severity, title, signals, fix,
|
|
54951
|
-
return { check: "CI-6", dimension: "instructions", severity, title, file:
|
|
55222
|
+
function mk(severity, title, signals, fix, path72) {
|
|
55223
|
+
return { check: "CI-6", dimension: "instructions", severity, title, file: path72, signals, fix };
|
|
54952
55224
|
}
|
|
54953
|
-
function analyzeInstructionFile(
|
|
55225
|
+
function analyzeInstructionFile(path72, content) {
|
|
54954
55226
|
const findings = [];
|
|
54955
55227
|
const decoded = decodeSuspiciousBase64(content);
|
|
54956
55228
|
if (TAG_CHARS.test(content))
|
|
@@ -54962,7 +55234,7 @@ function analyzeInstructionFile(path71, content) {
|
|
|
54962
55234
|
"contains Unicode tag characters (U+E0000\u2013E007F) \u2014 an invisible instruction-smuggling channel with no legitimate use in text"
|
|
54963
55235
|
],
|
|
54964
55236
|
"Remove the tag characters. Instruction files must be plain, reviewable text.",
|
|
54965
|
-
|
|
55237
|
+
path72
|
|
54966
55238
|
)
|
|
54967
55239
|
);
|
|
54968
55240
|
if (BIDI_OVERRIDE.test(content))
|
|
@@ -54974,7 +55246,7 @@ function analyzeInstructionFile(path71, content) {
|
|
|
54974
55246
|
"contains a bidi override (U+202D/U+202E) \u2014 a Trojan-Source technique that visually reorders text so a human reads something different from what the agent parses"
|
|
54975
55247
|
],
|
|
54976
55248
|
"Remove the bidi override characters.",
|
|
54977
|
-
|
|
55249
|
+
path72
|
|
54978
55250
|
)
|
|
54979
55251
|
);
|
|
54980
55252
|
else if (BIDI_EMBED_ISOLATE.test(content))
|
|
@@ -54986,7 +55258,7 @@ function analyzeInstructionFile(path71, content) {
|
|
|
54986
55258
|
"contains bidi embed/isolate characters (U+202A\u2013202C / U+2066\u20132069) \u2014 legitimate in right-to-left text, but confirm they are not being used to hide or reorder instructions"
|
|
54987
55259
|
],
|
|
54988
55260
|
"Confirm the bidi marks are legitimate RTL formatting; remove otherwise.",
|
|
54989
|
-
|
|
55261
|
+
path72
|
|
54990
55262
|
)
|
|
54991
55263
|
);
|
|
54992
55264
|
const zw = suspiciousZeroWidth(content);
|
|
@@ -55000,7 +55272,7 @@ function analyzeInstructionFile(path71, content) {
|
|
|
55000
55272
|
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 \u2014 a concealment technique (hides text from human review while the agent reads it as contiguous)"
|
|
55001
55273
|
],
|
|
55002
55274
|
"Remove the zero-width characters. Instruction files must be plain, reviewable text.",
|
|
55003
|
-
|
|
55275
|
+
path72
|
|
55004
55276
|
)
|
|
55005
55277
|
);
|
|
55006
55278
|
}
|
|
@@ -55016,7 +55288,7 @@ function analyzeInstructionFile(path71, content) {
|
|
|
55016
55288
|
`contains a prompt-override / role-impersonation directive (\`${m[0].slice(0, 60).trim()}\`)${ovEnc ? " \u2014 concealed in a base64 blob" : ""}`
|
|
55017
55289
|
],
|
|
55018
55290
|
"Remove the override text. An instruction file should not tell the agent to ignore its own rules.",
|
|
55019
|
-
|
|
55291
|
+
path72
|
|
55020
55292
|
)
|
|
55021
55293
|
);
|
|
55022
55294
|
}
|
|
@@ -55028,7 +55300,7 @@ function analyzeInstructionFile(path71, content) {
|
|
|
55028
55300
|
"Instruction directs the agent to fetch and run remote code",
|
|
55029
55301
|
[`\`${fo[0].slice(0, 70).trim()}\` \u2014 fetch-and-obey, outside an install/setup section`],
|
|
55030
55302
|
"Do not instruct the agent to pipe remote content into a shell; pin and vendor scripts instead.",
|
|
55031
|
-
|
|
55303
|
+
path72
|
|
55032
55304
|
)
|
|
55033
55305
|
);
|
|
55034
55306
|
}
|
|
@@ -55040,7 +55312,7 @@ function analyzeInstructionFile(path71, content) {
|
|
|
55040
55312
|
"Instruction points the agent at credential material",
|
|
55041
55313
|
[`references \`${sp[0].slice(0, 50).trim()}\` \u2014 directs the agent toward secrets`],
|
|
55042
55314
|
"Do not reference credential files or paths in agent instructions.",
|
|
55043
|
-
|
|
55315
|
+
path72
|
|
55044
55316
|
)
|
|
55045
55317
|
);
|
|
55046
55318
|
}
|
|
@@ -55052,7 +55324,7 @@ function analyzeInstructionFile(path71, content) {
|
|
|
55052
55324
|
"Instruction directs the agent to send data to an external endpoint",
|
|
55053
55325
|
[`\`${ex[0].slice(0, 70).trim()}\` \u2014 possible exfiltration directive`],
|
|
55054
55326
|
"Remove external post/upload directives from agent instructions.",
|
|
55055
|
-
|
|
55327
|
+
path72
|
|
55056
55328
|
)
|
|
55057
55329
|
);
|
|
55058
55330
|
}
|
|
@@ -55352,19 +55624,19 @@ function registerEgressCommand(program2) {
|
|
|
55352
55624
|
var import_chalk32 = __toESM(require("chalk"));
|
|
55353
55625
|
|
|
55354
55626
|
// src/shields/jail.ts
|
|
55355
|
-
var
|
|
55627
|
+
var import_fs63 = __toESM(require("fs"));
|
|
55356
55628
|
var import_os53 = __toESM(require("os"));
|
|
55357
|
-
var
|
|
55629
|
+
var import_path59 = __toESM(require("path"));
|
|
55358
55630
|
init_build();
|
|
55359
55631
|
init_shields();
|
|
55360
55632
|
var USER_JAIL_SHIELD = "user-jail";
|
|
55361
55633
|
function jailStorePath() {
|
|
55362
|
-
return
|
|
55634
|
+
return import_path59.default.join(import_os53.default.homedir(), ".node9", "jail-paths.json");
|
|
55363
55635
|
}
|
|
55364
55636
|
function readJailPaths() {
|
|
55365
55637
|
let text;
|
|
55366
55638
|
try {
|
|
55367
|
-
text =
|
|
55639
|
+
text = import_fs63.default.readFileSync(jailStorePath(), "utf8");
|
|
55368
55640
|
} catch (err2) {
|
|
55369
55641
|
if (err2.code === "ENOENT") return [];
|
|
55370
55642
|
throw err2;
|
|
@@ -55382,8 +55654,8 @@ function readJailPaths() {
|
|
|
55382
55654
|
}
|
|
55383
55655
|
function writeJailPaths(paths) {
|
|
55384
55656
|
const p = jailStorePath();
|
|
55385
|
-
|
|
55386
|
-
|
|
55657
|
+
import_fs63.default.mkdirSync(import_path59.default.dirname(p), { recursive: true });
|
|
55658
|
+
import_fs63.default.writeFileSync(p, JSON.stringify({ paths }, null, 2) + "\n", { mode: 384 });
|
|
55387
55659
|
}
|
|
55388
55660
|
function addJailPath(rawPath, verdict) {
|
|
55389
55661
|
const norm = rawPath.trim();
|
|
@@ -55405,14 +55677,14 @@ function removeJailPath(rawPath) {
|
|
|
55405
55677
|
return { removed, paths: after };
|
|
55406
55678
|
}
|
|
55407
55679
|
function regenerateUserJail(paths) {
|
|
55408
|
-
const file =
|
|
55680
|
+
const file = import_path59.default.join(USER_SHIELDS_DIR_PATH, `${USER_JAIL_SHIELD}.json`);
|
|
55409
55681
|
if (paths.length === 0) {
|
|
55410
55682
|
const active2 = readActiveShields();
|
|
55411
55683
|
if (active2.includes(USER_JAIL_SHIELD)) {
|
|
55412
55684
|
writeActiveShields(active2.filter((s) => s !== USER_JAIL_SHIELD));
|
|
55413
55685
|
}
|
|
55414
55686
|
try {
|
|
55415
|
-
|
|
55687
|
+
import_fs63.default.rmSync(file, { force: true });
|
|
55416
55688
|
} catch {
|
|
55417
55689
|
}
|
|
55418
55690
|
return;
|
|
@@ -55526,14 +55798,14 @@ function registerJailCommand(program2) {
|
|
|
55526
55798
|
|
|
55527
55799
|
// src/cli/commands/sandbox.ts
|
|
55528
55800
|
var import_chalk33 = __toESM(require("chalk"));
|
|
55529
|
-
var
|
|
55530
|
-
var
|
|
55801
|
+
var import_fs66 = __toESM(require("fs"));
|
|
55802
|
+
var import_path62 = __toESM(require("path"));
|
|
55531
55803
|
var import_child_process13 = require("child_process");
|
|
55532
55804
|
init_config();
|
|
55533
55805
|
|
|
55534
55806
|
// src/sandbox/config.ts
|
|
55535
|
-
var
|
|
55536
|
-
var
|
|
55807
|
+
var import_fs64 = __toESM(require("fs"));
|
|
55808
|
+
var import_path60 = __toESM(require("path"));
|
|
55537
55809
|
var import_yaml2 = require("yaml");
|
|
55538
55810
|
var SANDBOX_CONFIG_FILE = "node9.sandbox.yaml";
|
|
55539
55811
|
var FORBIDDEN_ENV = /* @__PURE__ */ new Set(["NODE9_API_KEY", "NODE9_API_URL"]);
|
|
@@ -55606,16 +55878,16 @@ function scaffoldSandboxYaml(agent) {
|
|
|
55606
55878
|
return header + (0, import_yaml2.stringify)(defaultSandboxConfig(agent));
|
|
55607
55879
|
}
|
|
55608
55880
|
function sandboxConfigPath(cwd = process.cwd()) {
|
|
55609
|
-
return
|
|
55881
|
+
return import_path60.default.join(cwd, SANDBOX_CONFIG_FILE);
|
|
55610
55882
|
}
|
|
55611
55883
|
function loadSandboxConfig(cwd = process.cwd(), fallbackAgent = "claude") {
|
|
55612
55884
|
const p = sandboxConfigPath(cwd);
|
|
55613
|
-
if (!
|
|
55885
|
+
if (!import_fs64.default.existsSync(p)) {
|
|
55614
55886
|
throw new Error(`sandbox: ${SANDBOX_CONFIG_FILE} not found \u2014 run \`node9 sandbox new\` first.`);
|
|
55615
55887
|
}
|
|
55616
55888
|
let raw;
|
|
55617
55889
|
try {
|
|
55618
|
-
raw = (0, import_yaml2.parse)(
|
|
55890
|
+
raw = (0, import_yaml2.parse)(import_fs64.default.readFileSync(p, "utf-8"));
|
|
55619
55891
|
} catch (err2) {
|
|
55620
55892
|
throw new Error(
|
|
55621
55893
|
`sandbox: ${SANDBOX_CONFIG_FILE} is not valid YAML \u2014 ${err2.message}`
|
|
@@ -55673,14 +55945,14 @@ function compileAllowlist(input) {
|
|
|
55673
55945
|
init_templates();
|
|
55674
55946
|
|
|
55675
55947
|
// src/sandbox/runtime.ts
|
|
55676
|
-
var
|
|
55948
|
+
var import_fs65 = __toESM(require("fs"));
|
|
55677
55949
|
var import_os54 = __toESM(require("os"));
|
|
55678
|
-
var
|
|
55950
|
+
var import_path61 = __toESM(require("path"));
|
|
55679
55951
|
var import_crypto14 = __toESM(require("crypto"));
|
|
55680
55952
|
var import_child_process12 = require("child_process");
|
|
55681
55953
|
init_templates();
|
|
55682
55954
|
function sandboxDataDir(cwd = process.cwd()) {
|
|
55683
|
-
return
|
|
55955
|
+
return import_path61.default.join(cwd, ".node9", "sandbox", "data");
|
|
55684
55956
|
}
|
|
55685
55957
|
function detectEngine(engine) {
|
|
55686
55958
|
const r = (0, import_child_process12.spawnSync)(engine, ["--version"], { encoding: "utf-8" });
|
|
@@ -55691,7 +55963,7 @@ function detectEngine(engine) {
|
|
|
55691
55963
|
}
|
|
55692
55964
|
function agentCredentialsMount(agent) {
|
|
55693
55965
|
const rel = agent === "codex" ? ".codex/auth.json" : ".claude/.credentials.json";
|
|
55694
|
-
return { hostPath:
|
|
55966
|
+
return { hostPath: import_path61.default.join(import_os54.default.homedir(), rel), target: `/home/${RUN_AS_USER}/${rel}` };
|
|
55695
55967
|
}
|
|
55696
55968
|
function buildRunArgs(opts) {
|
|
55697
55969
|
const { config, workspaceHostPath, dataHostPath, allowlistHostPath, agentArgs } = opts;
|
|
@@ -55701,7 +55973,7 @@ function buildRunArgs(opts) {
|
|
|
55701
55973
|
args.push("-v", `${allowlistHostPath}:${ALLOWED_DOMAINS_PATH}:ro`);
|
|
55702
55974
|
if (config.node9.mountAgentCredentials) {
|
|
55703
55975
|
const creds = agentCredentialsMount(config.agent);
|
|
55704
|
-
if (
|
|
55976
|
+
if (import_fs65.default.existsSync(creds.hostPath)) {
|
|
55705
55977
|
args.push("-v", `${creds.hostPath}:${creds.target}`);
|
|
55706
55978
|
}
|
|
55707
55979
|
}
|
|
@@ -55719,30 +55991,30 @@ function imageContentHash(dockerfile, entrypoint) {
|
|
|
55719
55991
|
return import_crypto14.default.createHash("sha256").update(dockerfile).update("\0").update(entrypoint).digest("hex").slice(0, 16);
|
|
55720
55992
|
}
|
|
55721
55993
|
function sandboxBuildDir(cwd = process.cwd()) {
|
|
55722
|
-
return
|
|
55994
|
+
return import_path61.default.join(cwd, ".node9", "sandbox", "build");
|
|
55723
55995
|
}
|
|
55724
55996
|
function writeBuildContext(cwd, dockerfile, entrypoint) {
|
|
55725
55997
|
const dir = sandboxBuildDir(cwd);
|
|
55726
|
-
|
|
55727
|
-
|
|
55728
|
-
|
|
55998
|
+
import_fs65.default.mkdirSync(dir, { recursive: true });
|
|
55999
|
+
import_fs65.default.writeFileSync(import_path61.default.join(dir, "Dockerfile"), dockerfile);
|
|
56000
|
+
import_fs65.default.writeFileSync(import_path61.default.join(dir, "entrypoint.sh"), entrypoint);
|
|
55729
56001
|
return dir;
|
|
55730
56002
|
}
|
|
55731
56003
|
function writeAllowlist(cwd, hosts) {
|
|
55732
|
-
const dir =
|
|
55733
|
-
|
|
55734
|
-
const p =
|
|
55735
|
-
|
|
56004
|
+
const dir = import_path61.default.join(cwd, ".node9", "sandbox");
|
|
56005
|
+
import_fs65.default.mkdirSync(dir, { recursive: true });
|
|
56006
|
+
const p = import_path61.default.join(dir, "allowed-domains.txt");
|
|
56007
|
+
import_fs65.default.writeFileSync(p, hosts.join("\n") + "\n");
|
|
55736
56008
|
return p;
|
|
55737
56009
|
}
|
|
55738
56010
|
function resolveHomePath(p) {
|
|
55739
|
-
return p.startsWith("~") ?
|
|
56011
|
+
return p.startsWith("~") ? import_path61.default.join(import_os54.default.homedir(), p.slice(1)) : import_path61.default.resolve(p);
|
|
55740
56012
|
}
|
|
55741
56013
|
|
|
55742
56014
|
// src/cli/commands/sandbox.ts
|
|
55743
56015
|
function seedDataDirConfig(dataDir, sandbox) {
|
|
55744
|
-
|
|
55745
|
-
const configPath =
|
|
56016
|
+
import_fs66.default.mkdirSync(dataDir, { recursive: true });
|
|
56017
|
+
const configPath = import_path62.default.join(dataDir, "config.json");
|
|
55746
56018
|
const seed = {
|
|
55747
56019
|
settings: {
|
|
55748
56020
|
approvers: {
|
|
@@ -55753,7 +56025,7 @@ function seedDataDirConfig(dataDir, sandbox) {
|
|
|
55753
56025
|
}
|
|
55754
56026
|
}
|
|
55755
56027
|
};
|
|
55756
|
-
|
|
56028
|
+
import_fs66.default.writeFileSync(configPath, JSON.stringify(seed, null, 2), { mode: 384 });
|
|
55757
56029
|
}
|
|
55758
56030
|
function registerSandboxCommand(program2, version2) {
|
|
55759
56031
|
const node9Version2 = pinnedNode9Version(version2);
|
|
@@ -55761,13 +56033,13 @@ function registerSandboxCommand(program2, version2) {
|
|
|
55761
56033
|
cmd.command("new").description(`Scaffold ${SANDBOX_CONFIG_FILE} in this project`).option("--agent <agent>", "claude (default) or codex", "claude").action((opts) => {
|
|
55762
56034
|
const agent = opts.agent === "codex" ? "codex" : "claude";
|
|
55763
56035
|
const p = sandboxConfigPath();
|
|
55764
|
-
if (
|
|
56036
|
+
if (import_fs66.default.existsSync(p)) {
|
|
55765
56037
|
console.log(
|
|
55766
56038
|
import_chalk33.default.yellow(` ${SANDBOX_CONFIG_FILE} already exists \u2014 leaving it untouched.`)
|
|
55767
56039
|
);
|
|
55768
56040
|
return;
|
|
55769
56041
|
}
|
|
55770
|
-
|
|
56042
|
+
import_fs66.default.writeFileSync(p, scaffoldSandboxYaml(agent));
|
|
55771
56043
|
console.log(
|
|
55772
56044
|
import_chalk33.default.green(` \u2713 wrote ${SANDBOX_CONFIG_FILE}`) + import_chalk33.default.dim(` (agent: ${agent})`)
|
|
55773
56045
|
);
|
|
@@ -55807,8 +56079,8 @@ function registerSandboxCommand(program2, version2) {
|
|
|
55807
56079
|
const buildDir = writeBuildContext(cwd, dockerfile, entrypoint);
|
|
55808
56080
|
const hash = imageContentHash(dockerfile, entrypoint);
|
|
55809
56081
|
const image = sandbox.runtime.image;
|
|
55810
|
-
const hashFile =
|
|
55811
|
-
const lastHash =
|
|
56082
|
+
const hashFile = import_path62.default.join(sandboxBuildDir(cwd), ".image-hash");
|
|
56083
|
+
const lastHash = import_fs66.default.existsSync(hashFile) ? import_fs66.default.readFileSync(hashFile, "utf-8").trim() : "";
|
|
55812
56084
|
const imageExists = (0, import_child_process13.spawnSync)(sandbox.runtime.engine, ["image", "inspect", image], { stdio: "ignore" }).status === 0;
|
|
55813
56085
|
const needBuild = sandbox.runtime.rebuild === "always" || !imageExists || sandbox.runtime.rebuild !== "never" && lastHash !== hash;
|
|
55814
56086
|
if (needBuild) {
|
|
@@ -55820,7 +56092,7 @@ function registerSandboxCommand(program2, version2) {
|
|
|
55820
56092
|
console.error(import_chalk33.default.red(" build failed."));
|
|
55821
56093
|
process.exit(b.status ?? 1);
|
|
55822
56094
|
}
|
|
55823
|
-
|
|
56095
|
+
import_fs66.default.writeFileSync(hashFile, hash);
|
|
55824
56096
|
}
|
|
55825
56097
|
const dataDir = sandboxDataDir(cwd);
|
|
55826
56098
|
seedDataDirConfig(dataDir, sandbox);
|
|
@@ -55834,7 +56106,7 @@ function registerSandboxCommand(program2, version2) {
|
|
|
55834
56106
|
});
|
|
55835
56107
|
if (sandbox.node9.mountAgentCredentials) {
|
|
55836
56108
|
const creds = agentCredentialsMount(sandbox.agent);
|
|
55837
|
-
if (
|
|
56109
|
+
if (import_fs66.default.existsSync(creds.hostPath)) {
|
|
55838
56110
|
console.log(import_chalk33.default.dim(` mounting ${creds.hostPath} (agent credentials, rw)`));
|
|
55839
56111
|
} else {
|
|
55840
56112
|
console.log(
|
|
@@ -55850,20 +56122,20 @@ function registerSandboxCommand(program2, version2) {
|
|
|
55850
56122
|
process.exit(r.status ?? 0);
|
|
55851
56123
|
});
|
|
55852
56124
|
cmd.command("tail").description("Stream the sandbox's audit log (host-side)").action(() => {
|
|
55853
|
-
const auditPath =
|
|
55854
|
-
if (!
|
|
56125
|
+
const auditPath = import_path62.default.join(sandboxDataDir(), "audit.log");
|
|
56126
|
+
if (!import_fs66.default.existsSync(auditPath)) {
|
|
55855
56127
|
console.log(import_chalk33.default.dim(" no sandbox audit yet."));
|
|
55856
56128
|
return;
|
|
55857
56129
|
}
|
|
55858
56130
|
(0, import_child_process13.spawnSync)("tail", ["-f", auditPath], { stdio: "inherit" });
|
|
55859
56131
|
});
|
|
55860
56132
|
cmd.command("logs").description("Dump the sandbox's audit log").action(() => {
|
|
55861
|
-
const auditPath =
|
|
55862
|
-
if (!
|
|
56133
|
+
const auditPath = import_path62.default.join(sandboxDataDir(), "audit.log");
|
|
56134
|
+
if (!import_fs66.default.existsSync(auditPath)) {
|
|
55863
56135
|
console.log(import_chalk33.default.dim(" no sandbox audit yet."));
|
|
55864
56136
|
return;
|
|
55865
56137
|
}
|
|
55866
|
-
process.stdout.write(
|
|
56138
|
+
process.stdout.write(import_fs66.default.readFileSync(auditPath, "utf-8"));
|
|
55867
56139
|
});
|
|
55868
56140
|
cmd.command("clean").description("Remove the sandbox image, build context, and data").action(() => {
|
|
55869
56141
|
const cwd = process.cwd();
|
|
@@ -55877,15 +56149,15 @@ function registerSandboxCommand(program2, version2) {
|
|
|
55877
56149
|
stdio: "ignore"
|
|
55878
56150
|
});
|
|
55879
56151
|
}
|
|
55880
|
-
|
|
56152
|
+
import_fs66.default.rmSync(import_path62.default.join(cwd, ".node9", "sandbox"), { recursive: true, force: true });
|
|
55881
56153
|
console.log(import_chalk33.default.green(" \u2713 sandbox image + build + data removed."));
|
|
55882
56154
|
});
|
|
55883
56155
|
}
|
|
55884
56156
|
|
|
55885
56157
|
// src/cli/commands/sessions.ts
|
|
55886
56158
|
var import_chalk34 = __toESM(require("chalk"));
|
|
55887
|
-
var
|
|
55888
|
-
var
|
|
56159
|
+
var import_fs67 = __toESM(require("fs"));
|
|
56160
|
+
var import_path63 = __toESM(require("path"));
|
|
55889
56161
|
init_decision();
|
|
55890
56162
|
var import_os55 = __toESM(require("os"));
|
|
55891
56163
|
init_scan_summary();
|
|
@@ -55908,7 +56180,7 @@ function encodeProjectPath(projectPath) {
|
|
|
55908
56180
|
}
|
|
55909
56181
|
function sessionJsonlPath(projectPath, sessionId) {
|
|
55910
56182
|
const encoded = encodeProjectPath(projectPath);
|
|
55911
|
-
return
|
|
56183
|
+
return import_path63.default.join(import_os55.default.homedir(), ".claude", "projects", encoded, `${sessionId}.jsonl`);
|
|
55912
56184
|
}
|
|
55913
56185
|
function projectLabel(projectPath) {
|
|
55914
56186
|
return projectPath.replace(import_os55.default.homedir(), "~");
|
|
@@ -55980,10 +56252,10 @@ function parseSessionLines(lines) {
|
|
|
55980
56252
|
return { toolCalls, costUSD, hasSnapshot, modifiedFiles };
|
|
55981
56253
|
}
|
|
55982
56254
|
function loadAuditEntries(auditPath) {
|
|
55983
|
-
const aPath = auditPath ??
|
|
56255
|
+
const aPath = auditPath ?? import_path63.default.join(import_os55.default.homedir(), ".node9", "audit.log");
|
|
55984
56256
|
let raw;
|
|
55985
56257
|
try {
|
|
55986
|
-
raw =
|
|
56258
|
+
raw = import_fs67.default.readFileSync(aPath, "utf-8");
|
|
55987
56259
|
} catch {
|
|
55988
56260
|
return [];
|
|
55989
56261
|
}
|
|
@@ -56019,8 +56291,8 @@ function auditEntriesInWindow(entries, windowStart, windowEnd) {
|
|
|
56019
56291
|
return result;
|
|
56020
56292
|
}
|
|
56021
56293
|
function buildGeminiSessions(days, allAuditEntries) {
|
|
56022
|
-
const tmpDir =
|
|
56023
|
-
if (!
|
|
56294
|
+
const tmpDir = import_path63.default.join(import_os55.default.homedir(), ".gemini", "tmp");
|
|
56295
|
+
if (!import_fs67.default.existsSync(tmpDir)) return [];
|
|
56024
56296
|
const cutoff = days !== null ? (() => {
|
|
56025
56297
|
const d = /* @__PURE__ */ new Date();
|
|
56026
56298
|
d.setDate(d.getDate() - days);
|
|
@@ -56029,35 +56301,35 @@ function buildGeminiSessions(days, allAuditEntries) {
|
|
|
56029
56301
|
})() : null;
|
|
56030
56302
|
let slugDirs;
|
|
56031
56303
|
try {
|
|
56032
|
-
slugDirs =
|
|
56304
|
+
slugDirs = import_fs67.default.readdirSync(tmpDir);
|
|
56033
56305
|
} catch {
|
|
56034
56306
|
return [];
|
|
56035
56307
|
}
|
|
56036
56308
|
const summaries = [];
|
|
56037
56309
|
for (const slug2 of slugDirs) {
|
|
56038
|
-
const slugPath =
|
|
56310
|
+
const slugPath = import_path63.default.join(tmpDir, slug2);
|
|
56039
56311
|
try {
|
|
56040
|
-
if (!
|
|
56312
|
+
if (!import_fs67.default.statSync(slugPath).isDirectory()) continue;
|
|
56041
56313
|
} catch {
|
|
56042
56314
|
continue;
|
|
56043
56315
|
}
|
|
56044
|
-
let projectRoot =
|
|
56316
|
+
let projectRoot = import_path63.default.join(import_os55.default.homedir(), slug2);
|
|
56045
56317
|
try {
|
|
56046
|
-
projectRoot =
|
|
56318
|
+
projectRoot = import_fs67.default.readFileSync(import_path63.default.join(slugPath, ".project_root"), "utf-8").trim();
|
|
56047
56319
|
} catch {
|
|
56048
56320
|
}
|
|
56049
|
-
const chatsDir =
|
|
56050
|
-
if (!
|
|
56321
|
+
const chatsDir = import_path63.default.join(slugPath, "chats");
|
|
56322
|
+
if (!import_fs67.default.existsSync(chatsDir)) continue;
|
|
56051
56323
|
let chatFiles;
|
|
56052
56324
|
try {
|
|
56053
|
-
chatFiles =
|
|
56325
|
+
chatFiles = import_fs67.default.readdirSync(chatsDir).filter((f) => f.endsWith(".json"));
|
|
56054
56326
|
} catch {
|
|
56055
56327
|
continue;
|
|
56056
56328
|
}
|
|
56057
56329
|
for (const chatFile of chatFiles) {
|
|
56058
56330
|
let raw;
|
|
56059
56331
|
try {
|
|
56060
|
-
raw =
|
|
56332
|
+
raw = import_fs67.default.readFileSync(import_path63.default.join(chatsDir, chatFile), "utf-8");
|
|
56061
56333
|
} catch {
|
|
56062
56334
|
continue;
|
|
56063
56335
|
}
|
|
@@ -56137,8 +56409,8 @@ function buildGeminiSessions(days, allAuditEntries) {
|
|
|
56137
56409
|
return summaries;
|
|
56138
56410
|
}
|
|
56139
56411
|
function buildCodexSessions(days, allAuditEntries) {
|
|
56140
|
-
const sessionsBase =
|
|
56141
|
-
if (!
|
|
56412
|
+
const sessionsBase = import_path63.default.join(import_os55.default.homedir(), ".codex", "sessions");
|
|
56413
|
+
if (!import_fs67.default.existsSync(sessionsBase)) return [];
|
|
56142
56414
|
const cutoff = days !== null ? (() => {
|
|
56143
56415
|
const d = /* @__PURE__ */ new Date();
|
|
56144
56416
|
d.setDate(d.getDate() - days);
|
|
@@ -56147,29 +56419,29 @@ function buildCodexSessions(days, allAuditEntries) {
|
|
|
56147
56419
|
})() : null;
|
|
56148
56420
|
const jsonlFiles = [];
|
|
56149
56421
|
try {
|
|
56150
|
-
for (const year of
|
|
56151
|
-
const yearPath =
|
|
56422
|
+
for (const year of import_fs67.default.readdirSync(sessionsBase)) {
|
|
56423
|
+
const yearPath = import_path63.default.join(sessionsBase, year);
|
|
56152
56424
|
try {
|
|
56153
|
-
if (!
|
|
56425
|
+
if (!import_fs67.default.statSync(yearPath).isDirectory()) continue;
|
|
56154
56426
|
} catch {
|
|
56155
56427
|
continue;
|
|
56156
56428
|
}
|
|
56157
|
-
for (const month of
|
|
56158
|
-
const monthPath =
|
|
56429
|
+
for (const month of import_fs67.default.readdirSync(yearPath)) {
|
|
56430
|
+
const monthPath = import_path63.default.join(yearPath, month);
|
|
56159
56431
|
try {
|
|
56160
|
-
if (!
|
|
56432
|
+
if (!import_fs67.default.statSync(monthPath).isDirectory()) continue;
|
|
56161
56433
|
} catch {
|
|
56162
56434
|
continue;
|
|
56163
56435
|
}
|
|
56164
|
-
for (const day of
|
|
56165
|
-
const dayPath =
|
|
56436
|
+
for (const day of import_fs67.default.readdirSync(monthPath)) {
|
|
56437
|
+
const dayPath = import_path63.default.join(monthPath, day);
|
|
56166
56438
|
try {
|
|
56167
|
-
if (!
|
|
56439
|
+
if (!import_fs67.default.statSync(dayPath).isDirectory()) continue;
|
|
56168
56440
|
} catch {
|
|
56169
56441
|
continue;
|
|
56170
56442
|
}
|
|
56171
|
-
for (const file of
|
|
56172
|
-
if (file.endsWith(".jsonl")) jsonlFiles.push(
|
|
56443
|
+
for (const file of import_fs67.default.readdirSync(dayPath)) {
|
|
56444
|
+
if (file.endsWith(".jsonl")) jsonlFiles.push(import_path63.default.join(dayPath, file));
|
|
56173
56445
|
}
|
|
56174
56446
|
}
|
|
56175
56447
|
}
|
|
@@ -56181,7 +56453,7 @@ function buildCodexSessions(days, allAuditEntries) {
|
|
|
56181
56453
|
for (const filePath of jsonlFiles) {
|
|
56182
56454
|
let lines;
|
|
56183
56455
|
try {
|
|
56184
|
-
lines =
|
|
56456
|
+
lines = import_fs67.default.readFileSync(filePath, "utf-8").split("\n");
|
|
56185
56457
|
} catch {
|
|
56186
56458
|
continue;
|
|
56187
56459
|
}
|
|
@@ -56267,10 +56539,10 @@ function buildCodexSessions(days, allAuditEntries) {
|
|
|
56267
56539
|
return summaries;
|
|
56268
56540
|
}
|
|
56269
56541
|
function buildSessions(days, historyPath) {
|
|
56270
|
-
const hPath = historyPath ??
|
|
56542
|
+
const hPath = historyPath ?? import_path63.default.join(import_os55.default.homedir(), ".claude", "history.jsonl");
|
|
56271
56543
|
let historyRaw = "";
|
|
56272
56544
|
try {
|
|
56273
|
-
historyRaw =
|
|
56545
|
+
historyRaw = import_fs67.default.readFileSync(hPath, "utf-8");
|
|
56274
56546
|
} catch {
|
|
56275
56547
|
}
|
|
56276
56548
|
const cutoff = days !== null ? (() => {
|
|
@@ -56294,7 +56566,7 @@ function buildSessions(days, historyPath) {
|
|
|
56294
56566
|
const jsonlFile = sessionJsonlPath(entry.project, entry.sessionId);
|
|
56295
56567
|
let sessionLines = [];
|
|
56296
56568
|
try {
|
|
56297
|
-
sessionLines =
|
|
56569
|
+
sessionLines = import_fs67.default.readFileSync(jsonlFile, "utf-8").split("\n");
|
|
56298
56570
|
} catch {
|
|
56299
56571
|
}
|
|
56300
56572
|
const { toolCalls, costUSD, hasSnapshot, modifiedFiles } = parseSessionLines(sessionLines);
|
|
@@ -56688,12 +56960,12 @@ function registerSessionTaintCommand(program2) {
|
|
|
56688
56960
|
|
|
56689
56961
|
// src/cli/commands/skill-pin.ts
|
|
56690
56962
|
var import_chalk36 = __toESM(require("chalk"));
|
|
56691
|
-
var
|
|
56963
|
+
var import_fs68 = __toESM(require("fs"));
|
|
56692
56964
|
var import_os56 = __toESM(require("os"));
|
|
56693
|
-
var
|
|
56965
|
+
var import_path64 = __toESM(require("path"));
|
|
56694
56966
|
function wipeSkillSessions() {
|
|
56695
56967
|
try {
|
|
56696
|
-
|
|
56968
|
+
import_fs68.default.rmSync(import_path64.default.join(import_os56.default.homedir(), ".node9", "skill-sessions"), {
|
|
56697
56969
|
recursive: true,
|
|
56698
56970
|
force: true
|
|
56699
56971
|
});
|
|
@@ -56775,15 +57047,15 @@ function registerSkillPinCommand(program2) {
|
|
|
56775
57047
|
}
|
|
56776
57048
|
|
|
56777
57049
|
// src/cli/commands/decisions.ts
|
|
56778
|
-
var
|
|
57050
|
+
var import_fs69 = __toESM(require("fs"));
|
|
56779
57051
|
var import_os57 = __toESM(require("os"));
|
|
56780
|
-
var
|
|
57052
|
+
var import_path65 = __toESM(require("path"));
|
|
56781
57053
|
var import_chalk37 = __toESM(require("chalk"));
|
|
56782
|
-
var DECISIONS_FILE2 =
|
|
57054
|
+
var DECISIONS_FILE2 = import_path65.default.join(import_os57.default.homedir(), ".node9", "decisions.json");
|
|
56783
57055
|
function readDecisions() {
|
|
56784
57056
|
try {
|
|
56785
|
-
if (!
|
|
56786
|
-
const raw =
|
|
57057
|
+
if (!import_fs69.default.existsSync(DECISIONS_FILE2)) return {};
|
|
57058
|
+
const raw = import_fs69.default.readFileSync(DECISIONS_FILE2, "utf-8");
|
|
56787
57059
|
const parsed = JSON.parse(raw);
|
|
56788
57060
|
const out = {};
|
|
56789
57061
|
for (const [k, v] of Object.entries(parsed)) {
|
|
@@ -56795,11 +57067,11 @@ function readDecisions() {
|
|
|
56795
57067
|
}
|
|
56796
57068
|
}
|
|
56797
57069
|
function writeDecisions(d) {
|
|
56798
|
-
const dir =
|
|
56799
|
-
if (!
|
|
57070
|
+
const dir = import_path65.default.dirname(DECISIONS_FILE2);
|
|
57071
|
+
if (!import_fs69.default.existsSync(dir)) import_fs69.default.mkdirSync(dir, { recursive: true });
|
|
56800
57072
|
const tmp = `${DECISIONS_FILE2}.${process.pid}.tmp`;
|
|
56801
|
-
|
|
56802
|
-
|
|
57073
|
+
import_fs69.default.writeFileSync(tmp, JSON.stringify(d, null, 2));
|
|
57074
|
+
import_fs69.default.renameSync(tmp, DECISIONS_FILE2);
|
|
56803
57075
|
}
|
|
56804
57076
|
function registerDecisionsCommand(program2) {
|
|
56805
57077
|
const cmd = program2.command("decisions").description('Manage persistent "Always Allow" / "Always Deny" tool decisions');
|
|
@@ -56856,18 +57128,18 @@ Persistent decisions (${entries.length})
|
|
|
56856
57128
|
|
|
56857
57129
|
// src/cli/commands/dlp.ts
|
|
56858
57130
|
var import_chalk38 = __toESM(require("chalk"));
|
|
56859
|
-
var
|
|
56860
|
-
var
|
|
57131
|
+
var import_fs70 = __toESM(require("fs"));
|
|
57132
|
+
var import_path66 = __toESM(require("path"));
|
|
56861
57133
|
var import_os58 = __toESM(require("os"));
|
|
56862
|
-
var AUDIT_LOG =
|
|
56863
|
-
var RESOLVED_FILE =
|
|
57134
|
+
var AUDIT_LOG = import_path66.default.join(import_os58.default.homedir(), ".node9", "audit.log");
|
|
57135
|
+
var RESOLVED_FILE = import_path66.default.join(import_os58.default.homedir(), ".node9", "dlp-resolved.json");
|
|
56864
57136
|
var ANSI_RE = /\x1b(?:\[[0-9;?]*[a-zA-Z]|\][^\x07\x1b]*(?:\x07|\x1b\\)|[@-_])/g;
|
|
56865
57137
|
function stripAnsi(s) {
|
|
56866
57138
|
return s.replace(ANSI_RE, "");
|
|
56867
57139
|
}
|
|
56868
57140
|
function loadResolved() {
|
|
56869
57141
|
try {
|
|
56870
|
-
const raw = JSON.parse(
|
|
57142
|
+
const raw = JSON.parse(import_fs70.default.readFileSync(RESOLVED_FILE, "utf-8"));
|
|
56871
57143
|
return new Set(raw);
|
|
56872
57144
|
} catch {
|
|
56873
57145
|
return /* @__PURE__ */ new Set();
|
|
@@ -56875,13 +57147,13 @@ function loadResolved() {
|
|
|
56875
57147
|
}
|
|
56876
57148
|
function saveResolved(resolved) {
|
|
56877
57149
|
try {
|
|
56878
|
-
|
|
57150
|
+
import_fs70.default.writeFileSync(RESOLVED_FILE, JSON.stringify([...resolved], null, 2), { mode: 384 });
|
|
56879
57151
|
} catch {
|
|
56880
57152
|
}
|
|
56881
57153
|
}
|
|
56882
57154
|
function loadDlpFindings() {
|
|
56883
|
-
if (!
|
|
56884
|
-
return
|
|
57155
|
+
if (!import_fs70.default.existsSync(AUDIT_LOG)) return [];
|
|
57156
|
+
return import_fs70.default.readFileSync(AUDIT_LOG, "utf-8").split("\n").flatMap((line) => {
|
|
56885
57157
|
if (!line.trim()) return [];
|
|
56886
57158
|
try {
|
|
56887
57159
|
const e = JSON.parse(line);
|
|
@@ -56979,15 +57251,15 @@ function registerDlpCommand(program2) {
|
|
|
56979
57251
|
|
|
56980
57252
|
// src/cli/commands/mask.ts
|
|
56981
57253
|
var import_chalk39 = __toESM(require("chalk"));
|
|
56982
|
-
var
|
|
56983
|
-
var
|
|
57254
|
+
var import_fs71 = __toESM(require("fs"));
|
|
57255
|
+
var import_path67 = __toESM(require("path"));
|
|
56984
57256
|
var import_os59 = __toESM(require("os"));
|
|
56985
57257
|
init_dlp();
|
|
56986
57258
|
function findJsonlFiles(dir) {
|
|
56987
57259
|
const results = [];
|
|
56988
|
-
if (!
|
|
56989
|
-
for (const entry of
|
|
56990
|
-
const full =
|
|
57260
|
+
if (!import_fs71.default.existsSync(dir)) return results;
|
|
57261
|
+
for (const entry of import_fs71.default.readdirSync(dir, { withFileTypes: true })) {
|
|
57262
|
+
const full = import_path67.default.join(dir, entry.name);
|
|
56991
57263
|
if (entry.isDirectory()) results.push(...findJsonlFiles(full));
|
|
56992
57264
|
else if (entry.isFile() && entry.name.endsWith(".jsonl")) results.push(full);
|
|
56993
57265
|
}
|
|
@@ -57030,7 +57302,7 @@ function redactJson(obj) {
|
|
|
57030
57302
|
function processFile(filePath, dryRun) {
|
|
57031
57303
|
let raw;
|
|
57032
57304
|
try {
|
|
57033
|
-
raw =
|
|
57305
|
+
raw = import_fs71.default.readFileSync(filePath, "utf-8");
|
|
57034
57306
|
} catch {
|
|
57035
57307
|
return { redactedLines: 0, patterns: [] };
|
|
57036
57308
|
}
|
|
@@ -57062,14 +57334,14 @@ function processFile(filePath, dryRun) {
|
|
|
57062
57334
|
}
|
|
57063
57335
|
}
|
|
57064
57336
|
if (!dryRun && redactedLines > 0) {
|
|
57065
|
-
|
|
57337
|
+
import_fs71.default.writeFileSync(filePath, newLines.join("\n"), "utf-8");
|
|
57066
57338
|
}
|
|
57067
57339
|
return { redactedLines, patterns };
|
|
57068
57340
|
}
|
|
57069
57341
|
function processJsonFile(filePath, dryRun) {
|
|
57070
57342
|
let raw;
|
|
57071
57343
|
try {
|
|
57072
|
-
raw =
|
|
57344
|
+
raw = import_fs71.default.readFileSync(filePath, "utf-8");
|
|
57073
57345
|
} catch {
|
|
57074
57346
|
return { redactedLines: 0, patterns: [] };
|
|
57075
57347
|
}
|
|
@@ -57082,15 +57354,15 @@ function processJsonFile(filePath, dryRun) {
|
|
|
57082
57354
|
const { value, modified, found } = redactJson(parsed);
|
|
57083
57355
|
if (!modified) return { redactedLines: 0, patterns: [] };
|
|
57084
57356
|
if (!dryRun) {
|
|
57085
|
-
|
|
57357
|
+
import_fs71.default.writeFileSync(filePath, JSON.stringify(value, null, 2), "utf-8");
|
|
57086
57358
|
}
|
|
57087
57359
|
return { redactedLines: 1, patterns: found };
|
|
57088
57360
|
}
|
|
57089
57361
|
function findJsonFiles(dir) {
|
|
57090
57362
|
const results = [];
|
|
57091
|
-
if (!
|
|
57092
|
-
for (const entry of
|
|
57093
|
-
const full =
|
|
57363
|
+
if (!import_fs71.default.existsSync(dir)) return results;
|
|
57364
|
+
for (const entry of import_fs71.default.readdirSync(dir, { withFileTypes: true })) {
|
|
57365
|
+
const full = import_path67.default.join(dir, entry.name);
|
|
57094
57366
|
if (entry.isDirectory()) results.push(...findJsonFiles(full));
|
|
57095
57367
|
else if (entry.isFile() && entry.name.endsWith(".json")) results.push(full);
|
|
57096
57368
|
}
|
|
@@ -57100,8 +57372,8 @@ function registerMaskCommand(program2) {
|
|
|
57100
57372
|
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) => {
|
|
57101
57373
|
const dryRun = !!options.dryRun;
|
|
57102
57374
|
const home = import_os59.default.homedir();
|
|
57103
|
-
const claudeDir =
|
|
57104
|
-
const geminiDir =
|
|
57375
|
+
const claudeDir = import_path67.default.join(home, ".claude", "projects");
|
|
57376
|
+
const geminiDir = import_path67.default.join(home, ".gemini", "tmp");
|
|
57105
57377
|
const allFiles = [
|
|
57106
57378
|
...findJsonlFiles(claudeDir).map((p) => ({ path: p, type: "jsonl" })),
|
|
57107
57379
|
...findJsonFiles(geminiDir).map((p) => ({ path: p, type: "json" }))
|
|
@@ -57109,7 +57381,7 @@ function registerMaskCommand(program2) {
|
|
|
57109
57381
|
const cutoff = options.all ? null : new Date(Date.now() - 30 * 24 * 60 * 60 * 1e3);
|
|
57110
57382
|
const filtered = cutoff ? allFiles.filter((f) => {
|
|
57111
57383
|
try {
|
|
57112
|
-
return
|
|
57384
|
+
return import_fs71.default.statSync(f.path).mtime >= cutoff;
|
|
57113
57385
|
} catch {
|
|
57114
57386
|
return false;
|
|
57115
57387
|
}
|
|
@@ -57165,7 +57437,7 @@ function registerMaskCommand(program2) {
|
|
|
57165
57437
|
// src/cli.ts
|
|
57166
57438
|
init_blast();
|
|
57167
57439
|
var { version } = JSON.parse(
|
|
57168
|
-
|
|
57440
|
+
import_fs74.default.readFileSync(import_path70.default.join(__dirname, "../package.json"), "utf-8")
|
|
57169
57441
|
);
|
|
57170
57442
|
var program = new import_commander.Command();
|
|
57171
57443
|
program.name("node9").description("The Sudo Command for AI Agents").version(version);
|
|
@@ -57344,15 +57616,15 @@ program.command("uninstall").description("Remove all Node9 hooks and optionally
|
|
|
57344
57616
|
} catch {
|
|
57345
57617
|
}
|
|
57346
57618
|
if (options.purge) {
|
|
57347
|
-
const node9Dir =
|
|
57348
|
-
if (
|
|
57619
|
+
const node9Dir = import_path70.default.join(import_os62.default.homedir(), ".node9");
|
|
57620
|
+
if (import_fs74.default.existsSync(node9Dir)) {
|
|
57349
57621
|
const confirmed = await (0, import_prompts2.confirm)({
|
|
57350
57622
|
message: `Permanently delete ${node9Dir} (config, audit log, credentials)?`,
|
|
57351
57623
|
default: false
|
|
57352
57624
|
});
|
|
57353
57625
|
if (confirmed) {
|
|
57354
|
-
|
|
57355
|
-
if (
|
|
57626
|
+
import_fs74.default.rmSync(node9Dir, { recursive: true });
|
|
57627
|
+
if (import_fs74.default.existsSync(node9Dir)) {
|
|
57356
57628
|
console.error(
|
|
57357
57629
|
import_chalk41.default.red("\n \u26A0\uFE0F ~/.node9/ could not be fully deleted \u2014 remove it manually.")
|
|
57358
57630
|
);
|
|
@@ -57477,7 +57749,7 @@ program.command("tail").description("Stream live agent activity to the terminal"
|
|
|
57477
57749
|
});
|
|
57478
57750
|
program.command("monitor").description("Live interactive dashboard \u2014 activity feed, approvals, security signals").action(async () => {
|
|
57479
57751
|
try {
|
|
57480
|
-
const dashboardPath =
|
|
57752
|
+
const dashboardPath = import_path70.default.join(__dirname, "dashboard.mjs");
|
|
57481
57753
|
const dynamicImport = new Function("id", "return import(id)");
|
|
57482
57754
|
const mod = await dynamicImport(`file://${dashboardPath}`);
|
|
57483
57755
|
await mod.startMonitor();
|
|
@@ -57515,14 +57787,14 @@ Claude Code spawns this command every ~300ms and writes a JSON payload to stdin.
|
|
|
57515
57787
|
Run "node9 addto claude" to register it as the statusLine.`
|
|
57516
57788
|
).argument("[subcommand]", 'Optional: "debug on" / "debug off" to toggle stdin logging').argument("[state]", 'on|off \u2014 used with "debug" subcommand').action(async (subcommand, state) => {
|
|
57517
57789
|
if (subcommand === "debug") {
|
|
57518
|
-
const flagFile =
|
|
57790
|
+
const flagFile = import_path70.default.join(import_os62.default.homedir(), ".node9", "hud-debug");
|
|
57519
57791
|
if (state === "on") {
|
|
57520
|
-
|
|
57521
|
-
|
|
57792
|
+
import_fs74.default.mkdirSync(import_path70.default.dirname(flagFile), { recursive: true });
|
|
57793
|
+
import_fs74.default.writeFileSync(flagFile, "");
|
|
57522
57794
|
console.log("HUD debug logging enabled \u2192 ~/.node9/hud-debug.log");
|
|
57523
57795
|
console.log("Tail it with: tail -f ~/.node9/hud-debug.log");
|
|
57524
57796
|
} else if (state === "off") {
|
|
57525
|
-
if (
|
|
57797
|
+
if (import_fs74.default.existsSync(flagFile)) import_fs74.default.unlinkSync(flagFile);
|
|
57526
57798
|
console.log("HUD debug logging disabled.");
|
|
57527
57799
|
} else {
|
|
57528
57800
|
console.error("Usage: node9 hud debug on|off");
|
|
@@ -57645,9 +57917,9 @@ if (process.argv[2] !== "daemon") {
|
|
|
57645
57917
|
const isCheckHook = process.argv[2] === "check";
|
|
57646
57918
|
if (isCheckHook) {
|
|
57647
57919
|
if (process.env.NODE9_DEBUG === "1" || getConfig().settings.enableHookLogDebug) {
|
|
57648
|
-
const logPath =
|
|
57920
|
+
const logPath = import_path70.default.join(import_os62.default.homedir(), ".node9", "hook-debug.log");
|
|
57649
57921
|
const msg = reason instanceof Error ? reason.message : String(reason);
|
|
57650
|
-
|
|
57922
|
+
import_fs74.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] UNHANDLED: ${msg}
|
|
57651
57923
|
`);
|
|
57652
57924
|
}
|
|
57653
57925
|
process.exit(0);
|