@node9/proxy 1.61.1 → 1.62.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +935 -621
- package/dist/cli.mjs +929 -615
- 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 path71 = issue.path.length > 0 ? issue.path.join(".") : "root";
|
|
247
|
+
return ` \u2022 ${path71}: ${issue.message}`;
|
|
248
248
|
});
|
|
249
249
|
return {
|
|
250
250
|
sanitized,
|
|
@@ -1454,9 +1454,9 @@ function matchesPattern(text, patterns) {
|
|
|
1454
1454
|
const withoutDotSlash = text.replace(/^\.\//, "");
|
|
1455
1455
|
return isMatch(withoutDotSlash) || isMatch(`./${withoutDotSlash}`);
|
|
1456
1456
|
}
|
|
1457
|
-
function getNestedValue(obj,
|
|
1457
|
+
function getNestedValue(obj, path71) {
|
|
1458
1458
|
if (!obj || typeof obj !== "object") return null;
|
|
1459
|
-
const segments =
|
|
1459
|
+
const segments = path71.split(".");
|
|
1460
1460
|
for (const seg of segments) {
|
|
1461
1461
|
if (FORBIDDEN_PATH_SEGMENTS.has(seg)) return null;
|
|
1462
1462
|
}
|
|
@@ -4842,10 +4842,10 @@ function getConfig(cwd) {
|
|
|
4842
4842
|
}
|
|
4843
4843
|
if (Array.isArray(mc.jailPaths)) {
|
|
4844
4844
|
for (const jp of mc.jailPaths) {
|
|
4845
|
-
const
|
|
4846
|
-
if (!
|
|
4845
|
+
const path71 = typeof jp?.path === "string" ? jp.path.trim() : "";
|
|
4846
|
+
if (!path71) continue;
|
|
4847
4847
|
const verdict = jp?.verdict === "review" ? "review" : "block";
|
|
4848
|
-
for (const r of pathRules(
|
|
4848
|
+
for (const r of pathRules(path71, verdict, "org-managed jail")) {
|
|
4849
4849
|
mergedPolicy.smartRules.push({ ...r, name: `org:${r.name}` });
|
|
4850
4850
|
}
|
|
4851
4851
|
}
|
|
@@ -17965,6 +17965,66 @@ function pickSyncIntervalMs(cloudHours, localSettings) {
|
|
|
17965
17965
|
function effectiveSyncIntervalMs() {
|
|
17966
17966
|
return pickSyncIntervalMs(readCachedSyncIntervalHours(), getConfig().settings);
|
|
17967
17967
|
}
|
|
17968
|
+
function readSyncHealth() {
|
|
17969
|
+
try {
|
|
17970
|
+
const raw = JSON.parse(import_fs35.default.readFileSync(syncHealthFile(), "utf-8"));
|
|
17971
|
+
return {
|
|
17972
|
+
lastCheckedAt: typeof raw.lastCheckedAt === "string" ? raw.lastCheckedAt : void 0,
|
|
17973
|
+
lastChangedAt: typeof raw.lastChangedAt === "string" ? raw.lastChangedAt : void 0,
|
|
17974
|
+
lastError: typeof raw.lastError === "string" ? raw.lastError : void 0,
|
|
17975
|
+
lastErrorAt: typeof raw.lastErrorAt === "string" ? raw.lastErrorAt : void 0,
|
|
17976
|
+
consecutiveFailures: typeof raw.consecutiveFailures === "number" && raw.consecutiveFailures >= 0 ? raw.consecutiveFailures : 0
|
|
17977
|
+
};
|
|
17978
|
+
} catch {
|
|
17979
|
+
return { consecutiveFailures: 0 };
|
|
17980
|
+
}
|
|
17981
|
+
}
|
|
17982
|
+
function writeSyncHealth(h) {
|
|
17983
|
+
try {
|
|
17984
|
+
const file = syncHealthFile();
|
|
17985
|
+
const dir = import_path34.default.dirname(file);
|
|
17986
|
+
if (!import_fs35.default.existsSync(dir)) import_fs35.default.mkdirSync(dir, { recursive: true });
|
|
17987
|
+
const tmp = `${file}.${process.pid}.tmp`;
|
|
17988
|
+
import_fs35.default.writeFileSync(tmp, JSON.stringify(h, null, 2) + "\n", "utf-8");
|
|
17989
|
+
import_fs35.default.renameSync(tmp, file);
|
|
17990
|
+
} catch {
|
|
17991
|
+
}
|
|
17992
|
+
}
|
|
17993
|
+
function readCacheFetchedAt() {
|
|
17994
|
+
try {
|
|
17995
|
+
const raw = JSON.parse(import_fs35.default.readFileSync(rulesCacheFile(), "utf-8"));
|
|
17996
|
+
return typeof raw.fetchedAt === "string" ? raw.fetchedAt : void 0;
|
|
17997
|
+
} catch {
|
|
17998
|
+
return void 0;
|
|
17999
|
+
}
|
|
18000
|
+
}
|
|
18001
|
+
function recordSyncHealth(result) {
|
|
18002
|
+
const h = readSyncHealth();
|
|
18003
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
18004
|
+
if (result.ok) {
|
|
18005
|
+
h.lastCheckedAt = now;
|
|
18006
|
+
if (result.changed) h.lastChangedAt = now;
|
|
18007
|
+
h.consecutiveFailures = 0;
|
|
18008
|
+
h.lastError = void 0;
|
|
18009
|
+
h.lastErrorAt = void 0;
|
|
18010
|
+
} else {
|
|
18011
|
+
h.consecutiveFailures += 1;
|
|
18012
|
+
h.lastError = result.error;
|
|
18013
|
+
h.lastErrorAt = now;
|
|
18014
|
+
}
|
|
18015
|
+
writeSyncHealth(h);
|
|
18016
|
+
}
|
|
18017
|
+
function stalenessThresholdMs(intervalMs) {
|
|
18018
|
+
return Math.min(STALE_MAX_MS, Math.max(STALE_MIN_MS, intervalMs * STALE_FACTOR));
|
|
18019
|
+
}
|
|
18020
|
+
function isPolicyStale(nowMs = Date.now(), health) {
|
|
18021
|
+
const h = health ?? readSyncHealth();
|
|
18022
|
+
const lastKnownGood = h.lastCheckedAt ?? readCacheFetchedAt();
|
|
18023
|
+
if (!lastKnownGood) return false;
|
|
18024
|
+
const last = Date.parse(lastKnownGood);
|
|
18025
|
+
if (Number.isNaN(last)) return false;
|
|
18026
|
+
return nowMs - last > stalenessThresholdMs(effectiveSyncIntervalMs());
|
|
18027
|
+
}
|
|
17968
18028
|
function fetchCloudPolicy(apiKey, apiUrl, ifNoneMatch) {
|
|
17969
18029
|
const parsed = new URL(apiUrl);
|
|
17970
18030
|
const headers = {
|
|
@@ -18129,6 +18189,7 @@ async function syncOnce() {
|
|
|
18129
18189
|
try {
|
|
18130
18190
|
const result = await fetchCloudPolicy(creds.apiKey, creds.apiUrl, readCachedEtag());
|
|
18131
18191
|
if (result.kind === "unchanged") {
|
|
18192
|
+
recordSyncHealth({ ok: true });
|
|
18132
18193
|
} else {
|
|
18133
18194
|
const cache = {
|
|
18134
18195
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -18142,8 +18203,19 @@ async function syncOnce() {
|
|
|
18142
18203
|
managedConfig: extractManagedConfig(result.body)
|
|
18143
18204
|
};
|
|
18144
18205
|
writeCache2(cache);
|
|
18206
|
+
recordSyncHealth({ ok: true, changed: true });
|
|
18207
|
+
}
|
|
18208
|
+
} catch (err2) {
|
|
18209
|
+
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
18210
|
+
recordSyncHealth({ ok: false, error: msg });
|
|
18211
|
+
try {
|
|
18212
|
+
appendToLog(HOOK_DEBUG_LOG, {
|
|
18213
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
18214
|
+
kind: "policy-sync-error",
|
|
18215
|
+
error: msg
|
|
18216
|
+
});
|
|
18217
|
+
} catch {
|
|
18145
18218
|
}
|
|
18146
|
-
} catch {
|
|
18147
18219
|
}
|
|
18148
18220
|
if (process.env.NODE9_BLAST_DISABLE !== "1") {
|
|
18149
18221
|
void pushBlastSnapshot(creds);
|
|
@@ -18319,6 +18391,7 @@ async function runCloudSync() {
|
|
|
18319
18391
|
const result = await fetchCloudPolicy(creds.apiKey, creds.apiUrl, readCachedEtag());
|
|
18320
18392
|
if (result.kind === "unchanged") {
|
|
18321
18393
|
const status = getCloudSyncStatus();
|
|
18394
|
+
recordSyncHealth({ ok: true });
|
|
18322
18395
|
maybePushBlast();
|
|
18323
18396
|
return status.cached ? { ok: true, rules: status.rules, fetchedAt: status.fetchedAt, unchanged: true } : { ok: true, rules: 0, fetchedAt: (/* @__PURE__ */ new Date()).toISOString(), unchanged: true };
|
|
18324
18397
|
}
|
|
@@ -18334,11 +18407,14 @@ async function runCloudSync() {
|
|
|
18334
18407
|
managedConfig: extractManagedConfig(result.body)
|
|
18335
18408
|
};
|
|
18336
18409
|
writeCache2(cache);
|
|
18410
|
+
recordSyncHealth({ ok: true, changed: true });
|
|
18337
18411
|
maybePushBlast();
|
|
18338
18412
|
return { ok: true, rules: cache.rules.length, fetchedAt: cache.fetchedAt };
|
|
18339
18413
|
} catch (err2) {
|
|
18414
|
+
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
18415
|
+
recordSyncHealth({ ok: false, error: msg });
|
|
18340
18416
|
maybePushBlast();
|
|
18341
|
-
return { ok: false, reason:
|
|
18417
|
+
return { ok: false, reason: msg };
|
|
18342
18418
|
}
|
|
18343
18419
|
}
|
|
18344
18420
|
function getCloudSyncStatus() {
|
|
@@ -18395,7 +18471,7 @@ function startForensicBroadcast() {
|
|
|
18395
18471
|
const recurring = setInterval(() => void tick(), FORENSIC_BROADCAST_INTERVAL_MS);
|
|
18396
18472
|
recurring.unref();
|
|
18397
18473
|
}
|
|
18398
|
-
var import_fs35, import_https4, import_os32, import_path34, FINDING_TO_SIGNAL3, rulesCacheFile, DEFAULT_API_URL2, DEFAULT_INTERVAL_HOURS, MIN_INTERVAL_SECONDS, MAX_INTERVAL_SECONDS, FORENSIC_BROADCAST_INTERVAL_MS, FORENSIC_INITIAL_DELAY_MS, forensicBroadcastOffsets;
|
|
18474
|
+
var import_fs35, import_https4, import_os32, import_path34, FINDING_TO_SIGNAL3, rulesCacheFile, 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;
|
|
18399
18475
|
var init_sync = __esm({
|
|
18400
18476
|
"src/daemon/sync.ts"() {
|
|
18401
18477
|
"use strict";
|
|
@@ -18433,6 +18509,10 @@ var init_sync = __esm({
|
|
|
18433
18509
|
DEFAULT_INTERVAL_HOURS = 5;
|
|
18434
18510
|
MIN_INTERVAL_SECONDS = 15;
|
|
18435
18511
|
MAX_INTERVAL_SECONDS = 24 * 60 * 60;
|
|
18512
|
+
syncHealthFile = () => import_path34.default.join(import_os32.default.homedir(), ".node9", "sync-health.json");
|
|
18513
|
+
STALE_MIN_MS = 3 * 60 * 60 * 1e3;
|
|
18514
|
+
STALE_MAX_MS = 24 * 60 * 60 * 1e3;
|
|
18515
|
+
STALE_FACTOR = 3;
|
|
18436
18516
|
FORENSIC_BROADCAST_INTERVAL_MS = 3e4;
|
|
18437
18517
|
FORENSIC_INITIAL_DELAY_MS = 5e3;
|
|
18438
18518
|
forensicBroadcastOffsets = /* @__PURE__ */ new Map();
|
|
@@ -19047,16 +19127,61 @@ var init_hook_heal = __esm({
|
|
|
19047
19127
|
}
|
|
19048
19128
|
});
|
|
19049
19129
|
|
|
19130
|
+
// src/daemon/startup-log.ts
|
|
19131
|
+
function openStartupLogFd() {
|
|
19132
|
+
try {
|
|
19133
|
+
const file = DAEMON_STARTUP_LOG();
|
|
19134
|
+
const dir = import_path38.default.dirname(file);
|
|
19135
|
+
if (!import_fs39.default.existsSync(dir)) import_fs39.default.mkdirSync(dir, { recursive: true });
|
|
19136
|
+
try {
|
|
19137
|
+
if (import_fs39.default.statSync(file).size > MAX_STARTUP_LOG_BYTES) import_fs39.default.truncateSync(file);
|
|
19138
|
+
} catch {
|
|
19139
|
+
}
|
|
19140
|
+
return import_fs39.default.openSync(file, "a");
|
|
19141
|
+
} catch {
|
|
19142
|
+
return void 0;
|
|
19143
|
+
}
|
|
19144
|
+
}
|
|
19145
|
+
function logDaemonStartup(kind, detail) {
|
|
19146
|
+
try {
|
|
19147
|
+
const file = DAEMON_STARTUP_LOG();
|
|
19148
|
+
const dir = import_path38.default.dirname(file);
|
|
19149
|
+
if (!import_fs39.default.existsSync(dir)) import_fs39.default.mkdirSync(dir, { recursive: true });
|
|
19150
|
+
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] daemon-startup:${kind}${detail ? ` ${detail}` : ""}
|
|
19151
|
+
`;
|
|
19152
|
+
import_fs39.default.appendFileSync(file, line, "utf-8");
|
|
19153
|
+
} catch {
|
|
19154
|
+
}
|
|
19155
|
+
}
|
|
19156
|
+
var import_fs39, import_path38, import_os36, DAEMON_STARTUP_LOG, MAX_STARTUP_LOG_BYTES;
|
|
19157
|
+
var init_startup_log = __esm({
|
|
19158
|
+
"src/daemon/startup-log.ts"() {
|
|
19159
|
+
"use strict";
|
|
19160
|
+
import_fs39 = __toESM(require("fs"));
|
|
19161
|
+
import_path38 = __toESM(require("path"));
|
|
19162
|
+
import_os36 = __toESM(require("os"));
|
|
19163
|
+
DAEMON_STARTUP_LOG = () => import_path38.default.join(import_os36.default.homedir(), ".node9", "daemon-startup.log");
|
|
19164
|
+
MAX_STARTUP_LOG_BYTES = 256 * 1024;
|
|
19165
|
+
}
|
|
19166
|
+
});
|
|
19167
|
+
|
|
19050
19168
|
// src/daemon/server.ts
|
|
19051
19169
|
function startDaemon() {
|
|
19052
|
-
|
|
19053
|
-
|
|
19054
|
-
|
|
19055
|
-
|
|
19056
|
-
|
|
19057
|
-
|
|
19058
|
-
|
|
19059
|
-
|
|
19170
|
+
try {
|
|
19171
|
+
startCostSync();
|
|
19172
|
+
startCloudSync();
|
|
19173
|
+
startForensicBroadcast();
|
|
19174
|
+
startAuditShipper();
|
|
19175
|
+
startDlpScanner();
|
|
19176
|
+
startMcpReconciler();
|
|
19177
|
+
startHookHeal();
|
|
19178
|
+
loadInsightCounts();
|
|
19179
|
+
} catch (err2) {
|
|
19180
|
+
const stack = err2 instanceof Error ? err2.stack ?? err2.message : String(err2);
|
|
19181
|
+
console.error("\n\u{1F6D1} Node9 daemon startup failed:\n" + stack);
|
|
19182
|
+
logDaemonStartup("startup-throw", err2 instanceof Error ? err2.message : String(err2));
|
|
19183
|
+
process.exit(1);
|
|
19184
|
+
}
|
|
19060
19185
|
const internalToken = (0, import_crypto11.randomUUID)();
|
|
19061
19186
|
const validToken = (req) => req.headers["x-node9-internal"] === internalToken || req.headers["x-node9-token"] === internalToken;
|
|
19062
19187
|
const IDLE_TIMEOUT_MS = 12 * 60 * 60 * 1e3;
|
|
@@ -19068,7 +19193,7 @@ function startDaemon() {
|
|
|
19068
19193
|
idleTimer = setTimeout(() => {
|
|
19069
19194
|
if (autoStarted) {
|
|
19070
19195
|
try {
|
|
19071
|
-
|
|
19196
|
+
import_fs40.default.unlinkSync(DAEMON_PID_FILE);
|
|
19072
19197
|
} catch {
|
|
19073
19198
|
}
|
|
19074
19199
|
}
|
|
@@ -19213,7 +19338,7 @@ data: ${JSON.stringify(item.data)}
|
|
|
19213
19338
|
mcpServer: entry.mcpServer
|
|
19214
19339
|
});
|
|
19215
19340
|
}
|
|
19216
|
-
const projectCwd = typeof cwd === "string" &&
|
|
19341
|
+
const projectCwd = typeof cwd === "string" && import_path39.default.isAbsolute(cwd) ? cwd : void 0;
|
|
19217
19342
|
const projectConfig = getConfig(projectCwd);
|
|
19218
19343
|
const browserEnabled = projectConfig.settings.approvers?.browser !== false;
|
|
19219
19344
|
const terminalEnabled = projectConfig.settings.approvers?.terminal !== false;
|
|
@@ -19505,8 +19630,8 @@ data: ${JSON.stringify(item.data)}
|
|
|
19505
19630
|
if (!validToken(req)) return res.writeHead(403).end();
|
|
19506
19631
|
const periodParam = reqUrl.searchParams.get("period") || "7d";
|
|
19507
19632
|
const period = ["today", "7d", "30d", "month"].includes(periodParam) ? periodParam : "7d";
|
|
19508
|
-
const logPath =
|
|
19509
|
-
if (!
|
|
19633
|
+
const logPath = import_path39.default.join(import_os37.default.homedir(), ".node9", "audit.log");
|
|
19634
|
+
if (!import_fs40.default.existsSync(logPath)) {
|
|
19510
19635
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
19511
19636
|
return res.end(
|
|
19512
19637
|
JSON.stringify({
|
|
@@ -19519,7 +19644,7 @@ data: ${JSON.stringify(item.data)}
|
|
|
19519
19644
|
);
|
|
19520
19645
|
}
|
|
19521
19646
|
try {
|
|
19522
|
-
const raw =
|
|
19647
|
+
const raw = import_fs40.default.readFileSync(logPath, "utf-8");
|
|
19523
19648
|
const allEntries = raw.split("\n").flatMap((line) => {
|
|
19524
19649
|
if (!line.trim()) return [];
|
|
19525
19650
|
try {
|
|
@@ -19902,14 +20027,15 @@ data: ${JSON.stringify(item.data)}
|
|
|
19902
20027
|
server.on("error", (e) => {
|
|
19903
20028
|
if (e.code === "EADDRINUSE") {
|
|
19904
20029
|
try {
|
|
19905
|
-
if (
|
|
19906
|
-
const { pid } = JSON.parse(
|
|
20030
|
+
if (import_fs40.default.existsSync(DAEMON_PID_FILE)) {
|
|
20031
|
+
const { pid } = JSON.parse(import_fs40.default.readFileSync(DAEMON_PID_FILE, "utf-8"));
|
|
19907
20032
|
process.kill(pid, 0);
|
|
20033
|
+
logDaemonStartup("port-in-use", `another daemon (pid ${pid}) owns :${DAEMON_PORT}`);
|
|
19908
20034
|
return process.exit(0);
|
|
19909
20035
|
}
|
|
19910
20036
|
} catch {
|
|
19911
20037
|
try {
|
|
19912
|
-
|
|
20038
|
+
import_fs40.default.unlinkSync(DAEMON_PID_FILE);
|
|
19913
20039
|
} catch {
|
|
19914
20040
|
}
|
|
19915
20041
|
server.listen(DAEMON_PORT, DAEMON_HOST);
|
|
@@ -19958,6 +20084,7 @@ data: ${JSON.stringify(item.data)}
|
|
|
19958
20084
|
});
|
|
19959
20085
|
return;
|
|
19960
20086
|
}
|
|
20087
|
+
logDaemonStartup("bind-failed", e.message);
|
|
19961
20088
|
console.error(import_chalk6.default.red("\n\u{1F6D1} Node9 Daemon Error:"), e.message);
|
|
19962
20089
|
process.exit(1);
|
|
19963
20090
|
});
|
|
@@ -19981,14 +20108,14 @@ data: ${JSON.stringify(item.data)}
|
|
|
19981
20108
|
}
|
|
19982
20109
|
startActivitySocket();
|
|
19983
20110
|
}
|
|
19984
|
-
var import_http3,
|
|
20111
|
+
var import_http3, import_fs40, import_path39, import_os37, import_crypto11, import_child_process2, import_chalk6;
|
|
19985
20112
|
var init_server = __esm({
|
|
19986
20113
|
"src/daemon/server.ts"() {
|
|
19987
20114
|
"use strict";
|
|
19988
20115
|
import_http3 = __toESM(require("http"));
|
|
19989
|
-
|
|
19990
|
-
|
|
19991
|
-
|
|
20116
|
+
import_fs40 = __toESM(require("fs"));
|
|
20117
|
+
import_path39 = __toESM(require("path"));
|
|
20118
|
+
import_os37 = __toESM(require("os"));
|
|
19992
20119
|
import_crypto11 = require("crypto");
|
|
19993
20120
|
import_child_process2 = require("child_process");
|
|
19994
20121
|
import_chalk6 = __toESM(require("chalk"));
|
|
@@ -20003,6 +20130,7 @@ var init_server = __esm({
|
|
|
20003
20130
|
init_dlp_scanner();
|
|
20004
20131
|
init_mcp_reconciler();
|
|
20005
20132
|
init_hook_heal();
|
|
20133
|
+
init_startup_log();
|
|
20006
20134
|
init_mcp_tools();
|
|
20007
20135
|
}
|
|
20008
20136
|
});
|
|
@@ -20011,8 +20139,8 @@ var init_server = __esm({
|
|
|
20011
20139
|
function resolveNode9Binary() {
|
|
20012
20140
|
try {
|
|
20013
20141
|
const script = process.argv[1];
|
|
20014
|
-
if (typeof script === "string" &&
|
|
20015
|
-
return
|
|
20142
|
+
if (typeof script === "string" && import_path40.default.isAbsolute(script) && import_fs41.default.existsSync(script)) {
|
|
20143
|
+
return import_fs41.default.realpathSync(script);
|
|
20016
20144
|
}
|
|
20017
20145
|
} catch {
|
|
20018
20146
|
}
|
|
@@ -20030,11 +20158,11 @@ function xmlEscape(s) {
|
|
|
20030
20158
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
20031
20159
|
}
|
|
20032
20160
|
function launchdPlist(binaryPath) {
|
|
20033
|
-
const logDir =
|
|
20161
|
+
const logDir = import_path40.default.join(import_os38.default.homedir(), ".node9");
|
|
20034
20162
|
const nodePath = xmlEscape(process.execPath);
|
|
20035
20163
|
const scriptPath = xmlEscape(binaryPath);
|
|
20036
|
-
const outLog = xmlEscape(
|
|
20037
|
-
const errLog = xmlEscape(
|
|
20164
|
+
const outLog = xmlEscape(import_path40.default.join(logDir, "daemon.log"));
|
|
20165
|
+
const errLog = xmlEscape(import_path40.default.join(logDir, "daemon-error.log"));
|
|
20038
20166
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
20039
20167
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
20040
20168
|
<plist version="1.0">
|
|
@@ -20067,9 +20195,9 @@ function launchdPlist(binaryPath) {
|
|
|
20067
20195
|
`;
|
|
20068
20196
|
}
|
|
20069
20197
|
function installLaunchd(binaryPath) {
|
|
20070
|
-
const dir =
|
|
20071
|
-
if (!
|
|
20072
|
-
|
|
20198
|
+
const dir = import_path40.default.dirname(LAUNCHD_PLIST);
|
|
20199
|
+
if (!import_fs41.default.existsSync(dir)) import_fs41.default.mkdirSync(dir, { recursive: true });
|
|
20200
|
+
import_fs41.default.writeFileSync(LAUNCHD_PLIST, launchdPlist(binaryPath), "utf-8");
|
|
20073
20201
|
(0, import_child_process3.spawnSync)("launchctl", ["unload", LAUNCHD_PLIST], { encoding: "utf8" });
|
|
20074
20202
|
const r = (0, import_child_process3.spawnSync)("launchctl", ["load", "-w", LAUNCHD_PLIST], {
|
|
20075
20203
|
encoding: "utf8",
|
|
@@ -20080,13 +20208,13 @@ function installLaunchd(binaryPath) {
|
|
|
20080
20208
|
}
|
|
20081
20209
|
}
|
|
20082
20210
|
function uninstallLaunchd() {
|
|
20083
|
-
if (
|
|
20211
|
+
if (import_fs41.default.existsSync(LAUNCHD_PLIST)) {
|
|
20084
20212
|
(0, import_child_process3.spawnSync)("launchctl", ["unload", "-w", LAUNCHD_PLIST], { encoding: "utf8", timeout: 5e3 });
|
|
20085
|
-
|
|
20213
|
+
import_fs41.default.unlinkSync(LAUNCHD_PLIST);
|
|
20086
20214
|
}
|
|
20087
20215
|
}
|
|
20088
20216
|
function isLaunchdInstalled() {
|
|
20089
|
-
return
|
|
20217
|
+
return import_fs41.default.existsSync(LAUNCHD_PLIST);
|
|
20090
20218
|
}
|
|
20091
20219
|
function systemdUnit(binaryPath) {
|
|
20092
20220
|
return `[Unit]
|
|
@@ -20105,12 +20233,12 @@ WantedBy=default.target
|
|
|
20105
20233
|
`;
|
|
20106
20234
|
}
|
|
20107
20235
|
function installSystemd(binaryPath) {
|
|
20108
|
-
if (!
|
|
20109
|
-
|
|
20236
|
+
if (!import_fs41.default.existsSync(SYSTEMD_UNIT_DIR)) {
|
|
20237
|
+
import_fs41.default.mkdirSync(SYSTEMD_UNIT_DIR, { recursive: true });
|
|
20110
20238
|
}
|
|
20111
|
-
|
|
20239
|
+
import_fs41.default.writeFileSync(SYSTEMD_UNIT, systemdUnit(binaryPath), "utf-8");
|
|
20112
20240
|
try {
|
|
20113
|
-
(0, import_child_process3.execFileSync)("loginctl", ["enable-linger",
|
|
20241
|
+
(0, import_child_process3.execFileSync)("loginctl", ["enable-linger", import_os38.default.userInfo().username], { timeout: 3e3 });
|
|
20114
20242
|
} catch {
|
|
20115
20243
|
}
|
|
20116
20244
|
const reload = (0, import_child_process3.spawnSync)("systemctl", ["--user", "daemon-reload"], {
|
|
@@ -20130,23 +20258,23 @@ function installSystemd(binaryPath) {
|
|
|
20130
20258
|
}
|
|
20131
20259
|
}
|
|
20132
20260
|
function uninstallSystemd() {
|
|
20133
|
-
if (
|
|
20261
|
+
if (import_fs41.default.existsSync(SYSTEMD_UNIT)) {
|
|
20134
20262
|
(0, import_child_process3.spawnSync)("systemctl", ["--user", "disable", "--now", "node9-daemon"], {
|
|
20135
20263
|
encoding: "utf8",
|
|
20136
20264
|
timeout: 5e3
|
|
20137
20265
|
});
|
|
20138
20266
|
(0, import_child_process3.spawnSync)("systemctl", ["--user", "daemon-reload"], { encoding: "utf8", timeout: 5e3 });
|
|
20139
|
-
|
|
20267
|
+
import_fs41.default.unlinkSync(SYSTEMD_UNIT);
|
|
20140
20268
|
}
|
|
20141
20269
|
}
|
|
20142
20270
|
function isSystemdInstalled() {
|
|
20143
|
-
return
|
|
20271
|
+
return import_fs41.default.existsSync(SYSTEMD_UNIT);
|
|
20144
20272
|
}
|
|
20145
20273
|
function stopRunningDaemon() {
|
|
20146
|
-
const pidFile =
|
|
20147
|
-
if (!
|
|
20274
|
+
const pidFile = import_path40.default.join(import_os38.default.homedir(), ".node9", "daemon.pid");
|
|
20275
|
+
if (!import_fs41.default.existsSync(pidFile)) return;
|
|
20148
20276
|
try {
|
|
20149
|
-
const data = JSON.parse(
|
|
20277
|
+
const data = JSON.parse(import_fs41.default.readFileSync(pidFile, "utf-8"));
|
|
20150
20278
|
const pid = data.pid;
|
|
20151
20279
|
const MAX_PID2 = 4194304;
|
|
20152
20280
|
if (typeof pid === "number" && Number.isInteger(pid) && pid > 0 && pid <= MAX_PID2) {
|
|
@@ -20166,7 +20294,7 @@ function stopRunningDaemon() {
|
|
|
20166
20294
|
}
|
|
20167
20295
|
}
|
|
20168
20296
|
try {
|
|
20169
|
-
|
|
20297
|
+
import_fs41.default.unlinkSync(pidFile);
|
|
20170
20298
|
} catch {
|
|
20171
20299
|
}
|
|
20172
20300
|
} catch {
|
|
@@ -20236,26 +20364,95 @@ function isDaemonServiceInstalled() {
|
|
|
20236
20364
|
if (process.platform === "linux") return isSystemdInstalled();
|
|
20237
20365
|
return false;
|
|
20238
20366
|
}
|
|
20239
|
-
|
|
20367
|
+
function autostartRepairDecision(opts) {
|
|
20368
|
+
if (!opts.autoStartDaemon) return "skip";
|
|
20369
|
+
if (process.platform !== "linux" && process.platform !== "darwin") return "unsupported";
|
|
20370
|
+
if (!opts.installed) return "skip";
|
|
20371
|
+
return opts.enabled ? "ok" : "repair";
|
|
20372
|
+
}
|
|
20373
|
+
function enableDaemonServiceQuiet() {
|
|
20374
|
+
try {
|
|
20375
|
+
if (process.platform === "linux") {
|
|
20376
|
+
const r = (0, import_child_process3.spawnSync)("systemctl", ["--user", "enable", "node9-daemon"], {
|
|
20377
|
+
encoding: "utf8",
|
|
20378
|
+
timeout: 3e3
|
|
20379
|
+
});
|
|
20380
|
+
return r.status === 0;
|
|
20381
|
+
}
|
|
20382
|
+
return process.platform === "darwin";
|
|
20383
|
+
} catch {
|
|
20384
|
+
return false;
|
|
20385
|
+
}
|
|
20386
|
+
}
|
|
20387
|
+
function ensureAutostartHealthy(autoStartDaemon) {
|
|
20388
|
+
const decision = autostartRepairDecision({
|
|
20389
|
+
installed: isDaemonServiceInstalled(),
|
|
20390
|
+
enabled: isDaemonServiceEnabled(),
|
|
20391
|
+
autoStartDaemon
|
|
20392
|
+
});
|
|
20393
|
+
if (decision === "repair") return enableDaemonServiceQuiet() ? "repaired" : "skipped";
|
|
20394
|
+
return decision === "ok" ? "ok" : decision === "unsupported" ? "unsupported" : "skipped";
|
|
20395
|
+
}
|
|
20396
|
+
function autostartAdvice(opts) {
|
|
20397
|
+
const installable = process.platform === "linux" || process.platform === "darwin";
|
|
20398
|
+
if (!opts.cloudEnabled || !installable) return null;
|
|
20399
|
+
const installHint = process.platform === "linux" ? "Run: systemctl --user enable --now node9-daemon (or: node9 daemon install)" : "Run: node9 daemon install";
|
|
20400
|
+
if (opts.installed && !opts.enabled) {
|
|
20401
|
+
return {
|
|
20402
|
+
level: "warn",
|
|
20403
|
+
message: "Daemon autostart is INSTALLED but DISABLED \u2014 it will NOT survive a reboot, so cloud policy can silently go stale.",
|
|
20404
|
+
hint: installHint
|
|
20405
|
+
};
|
|
20406
|
+
}
|
|
20407
|
+
if (!opts.installed) {
|
|
20408
|
+
return {
|
|
20409
|
+
level: "warn",
|
|
20410
|
+
message: "No daemon autostart installed \u2014 the daemon only runs when an agent happens to spawn it; cloud policy may lag.",
|
|
20411
|
+
hint: installHint
|
|
20412
|
+
};
|
|
20413
|
+
}
|
|
20414
|
+
return null;
|
|
20415
|
+
}
|
|
20416
|
+
function isDaemonServiceEnabled() {
|
|
20417
|
+
try {
|
|
20418
|
+
if (process.platform === "linux") {
|
|
20419
|
+
const r = (0, import_child_process3.spawnSync)("systemctl", ["--user", "is-enabled", "node9-daemon"], {
|
|
20420
|
+
encoding: "utf8",
|
|
20421
|
+
timeout: 3e3
|
|
20422
|
+
});
|
|
20423
|
+
return r.status === 0 && (r.stdout ?? "").trim() === "enabled";
|
|
20424
|
+
}
|
|
20425
|
+
if (process.platform === "darwin") {
|
|
20426
|
+
const r = (0, import_child_process3.spawnSync)("launchctl", ["list", LAUNCHD_LABEL], {
|
|
20427
|
+
encoding: "utf8",
|
|
20428
|
+
timeout: 3e3
|
|
20429
|
+
});
|
|
20430
|
+
return r.status === 0;
|
|
20431
|
+
}
|
|
20432
|
+
} catch {
|
|
20433
|
+
}
|
|
20434
|
+
return false;
|
|
20435
|
+
}
|
|
20436
|
+
var import_fs41, import_path40, import_os38, import_child_process3, LAUNCHD_LABEL, LAUNCHD_PLIST, SYSTEMD_UNIT_DIR, SYSTEMD_UNIT;
|
|
20240
20437
|
var init_service = __esm({
|
|
20241
20438
|
"src/daemon/service.ts"() {
|
|
20242
20439
|
"use strict";
|
|
20243
|
-
|
|
20244
|
-
|
|
20245
|
-
|
|
20440
|
+
import_fs41 = __toESM(require("fs"));
|
|
20441
|
+
import_path40 = __toESM(require("path"));
|
|
20442
|
+
import_os38 = __toESM(require("os"));
|
|
20246
20443
|
import_child_process3 = require("child_process");
|
|
20247
20444
|
LAUNCHD_LABEL = "ai.node9.daemon";
|
|
20248
|
-
LAUNCHD_PLIST =
|
|
20249
|
-
SYSTEMD_UNIT_DIR =
|
|
20250
|
-
SYSTEMD_UNIT =
|
|
20445
|
+
LAUNCHD_PLIST = import_path40.default.join(import_os38.default.homedir(), "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`);
|
|
20446
|
+
SYSTEMD_UNIT_DIR = import_path40.default.join(import_os38.default.homedir(), ".config", "systemd", "user");
|
|
20447
|
+
SYSTEMD_UNIT = import_path40.default.join(SYSTEMD_UNIT_DIR, "node9-daemon.service");
|
|
20251
20448
|
}
|
|
20252
20449
|
});
|
|
20253
20450
|
|
|
20254
20451
|
// src/daemon/index.ts
|
|
20255
20452
|
function stopDaemon() {
|
|
20256
|
-
if (!
|
|
20453
|
+
if (!import_fs42.default.existsSync(DAEMON_PID_FILE)) return console.log(import_chalk7.default.yellow("Not running."));
|
|
20257
20454
|
try {
|
|
20258
|
-
const data = JSON.parse(
|
|
20455
|
+
const data = JSON.parse(import_fs42.default.readFileSync(DAEMON_PID_FILE, "utf-8"));
|
|
20259
20456
|
const pid = data.pid;
|
|
20260
20457
|
if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0 || pid > MAX_PID) {
|
|
20261
20458
|
console.log(import_chalk7.default.gray("Cleaned up invalid PID file."));
|
|
@@ -20267,7 +20464,7 @@ function stopDaemon() {
|
|
|
20267
20464
|
console.log(import_chalk7.default.gray("Cleaned up stale PID file."));
|
|
20268
20465
|
} finally {
|
|
20269
20466
|
try {
|
|
20270
|
-
|
|
20467
|
+
import_fs42.default.unlinkSync(DAEMON_PID_FILE);
|
|
20271
20468
|
} catch {
|
|
20272
20469
|
}
|
|
20273
20470
|
}
|
|
@@ -20276,9 +20473,9 @@ function daemonStatus() {
|
|
|
20276
20473
|
const serviceInstalled = isDaemonServiceInstalled();
|
|
20277
20474
|
const serviceLabel = serviceInstalled ? import_chalk7.default.green("installed (starts on login)") : import_chalk7.default.yellow("not installed \u2014 run: node9 daemon install");
|
|
20278
20475
|
let processStatus;
|
|
20279
|
-
if (
|
|
20476
|
+
if (import_fs42.default.existsSync(DAEMON_PID_FILE)) {
|
|
20280
20477
|
try {
|
|
20281
|
-
const data = JSON.parse(
|
|
20478
|
+
const data = JSON.parse(import_fs42.default.readFileSync(DAEMON_PID_FILE, "utf-8"));
|
|
20282
20479
|
const pid = data.pid;
|
|
20283
20480
|
const port = data.port;
|
|
20284
20481
|
if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0 || pid > MAX_PID) {
|
|
@@ -20300,11 +20497,11 @@ function daemonStatus() {
|
|
|
20300
20497
|
console.log(` Service : ${serviceLabel}
|
|
20301
20498
|
`);
|
|
20302
20499
|
}
|
|
20303
|
-
var
|
|
20500
|
+
var import_fs42, import_chalk7, MAX_PID;
|
|
20304
20501
|
var init_daemon2 = __esm({
|
|
20305
20502
|
"src/daemon/index.ts"() {
|
|
20306
20503
|
"use strict";
|
|
20307
|
-
|
|
20504
|
+
import_fs42 = __toESM(require("fs"));
|
|
20308
20505
|
import_chalk7 = __toESM(require("chalk"));
|
|
20309
20506
|
init_server();
|
|
20310
20507
|
init_state2();
|
|
@@ -21423,14 +21620,14 @@ var require_util = __commonJS({
|
|
|
21423
21620
|
}
|
|
21424
21621
|
const port = url.port != null ? url.port : url.protocol === "https:" ? 443 : 80;
|
|
21425
21622
|
let origin = url.origin != null ? url.origin : `${url.protocol || ""}//${url.hostname || ""}:${port}`;
|
|
21426
|
-
let
|
|
21623
|
+
let path71 = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`;
|
|
21427
21624
|
if (origin[origin.length - 1] === "/") {
|
|
21428
21625
|
origin = origin.slice(0, origin.length - 1);
|
|
21429
21626
|
}
|
|
21430
|
-
if (
|
|
21431
|
-
|
|
21627
|
+
if (path71 && path71[0] !== "/") {
|
|
21628
|
+
path71 = `/${path71}`;
|
|
21432
21629
|
}
|
|
21433
|
-
return new URL(`${origin}${
|
|
21630
|
+
return new URL(`${origin}${path71}`);
|
|
21434
21631
|
}
|
|
21435
21632
|
if (!isHttpOrHttpsPrefixed(url.origin || url.protocol)) {
|
|
21436
21633
|
throw new InvalidArgumentError("Invalid URL protocol: the URL must start with `http:` or `https:`.");
|
|
@@ -22251,9 +22448,9 @@ var require_diagnostics = __commonJS({
|
|
|
22251
22448
|
"undici:client:sendHeaders",
|
|
22252
22449
|
(evt) => {
|
|
22253
22450
|
const {
|
|
22254
|
-
request: { method, path:
|
|
22451
|
+
request: { method, path: path71, origin }
|
|
22255
22452
|
} = evt;
|
|
22256
|
-
debugLog("sending request to %s %s%s", method, origin,
|
|
22453
|
+
debugLog("sending request to %s %s%s", method, origin, path71);
|
|
22257
22454
|
}
|
|
22258
22455
|
);
|
|
22259
22456
|
}
|
|
@@ -22271,14 +22468,14 @@ var require_diagnostics = __commonJS({
|
|
|
22271
22468
|
"undici:request:headers",
|
|
22272
22469
|
(evt) => {
|
|
22273
22470
|
const {
|
|
22274
|
-
request: { method, path:
|
|
22471
|
+
request: { method, path: path71, origin },
|
|
22275
22472
|
response: { statusCode }
|
|
22276
22473
|
} = evt;
|
|
22277
22474
|
debugLog(
|
|
22278
22475
|
"received response to %s %s%s - HTTP %d",
|
|
22279
22476
|
method,
|
|
22280
22477
|
origin,
|
|
22281
|
-
|
|
22478
|
+
path71,
|
|
22282
22479
|
statusCode
|
|
22283
22480
|
);
|
|
22284
22481
|
}
|
|
@@ -22287,23 +22484,23 @@ var require_diagnostics = __commonJS({
|
|
|
22287
22484
|
"undici:request:trailers",
|
|
22288
22485
|
(evt) => {
|
|
22289
22486
|
const {
|
|
22290
|
-
request: { method, path:
|
|
22487
|
+
request: { method, path: path71, origin }
|
|
22291
22488
|
} = evt;
|
|
22292
|
-
debugLog("trailers received from %s %s%s", method, origin,
|
|
22489
|
+
debugLog("trailers received from %s %s%s", method, origin, path71);
|
|
22293
22490
|
}
|
|
22294
22491
|
);
|
|
22295
22492
|
diagnosticsChannel.subscribe(
|
|
22296
22493
|
"undici:request:error",
|
|
22297
22494
|
(evt) => {
|
|
22298
22495
|
const {
|
|
22299
|
-
request: { method, path:
|
|
22496
|
+
request: { method, path: path71, origin },
|
|
22300
22497
|
error
|
|
22301
22498
|
} = evt;
|
|
22302
22499
|
debugLog(
|
|
22303
22500
|
"request to %s %s%s errored - %s",
|
|
22304
22501
|
method,
|
|
22305
22502
|
origin,
|
|
22306
|
-
|
|
22503
|
+
path71,
|
|
22307
22504
|
error.message
|
|
22308
22505
|
);
|
|
22309
22506
|
}
|
|
@@ -22406,7 +22603,7 @@ var require_request = __commonJS({
|
|
|
22406
22603
|
var kHandler = /* @__PURE__ */ Symbol("handler");
|
|
22407
22604
|
var Request = class {
|
|
22408
22605
|
constructor(origin, {
|
|
22409
|
-
path:
|
|
22606
|
+
path: path71,
|
|
22410
22607
|
method,
|
|
22411
22608
|
body,
|
|
22412
22609
|
headers,
|
|
@@ -22423,11 +22620,11 @@ var require_request = __commonJS({
|
|
|
22423
22620
|
maxRedirections,
|
|
22424
22621
|
typeOfService
|
|
22425
22622
|
}, handler) {
|
|
22426
|
-
if (typeof
|
|
22623
|
+
if (typeof path71 !== "string") {
|
|
22427
22624
|
throw new InvalidArgumentError("path must be a string");
|
|
22428
|
-
} else if (
|
|
22625
|
+
} else if (path71[0] !== "/" && !(path71.startsWith("http://") || path71.startsWith("https://")) && method !== "CONNECT") {
|
|
22429
22626
|
throw new InvalidArgumentError("path must be an absolute URL or start with a slash");
|
|
22430
|
-
} else if (invalidPathRegex.test(
|
|
22627
|
+
} else if (invalidPathRegex.test(path71)) {
|
|
22431
22628
|
throw new InvalidArgumentError("invalid request path");
|
|
22432
22629
|
}
|
|
22433
22630
|
if (typeof method !== "string") {
|
|
@@ -22502,7 +22699,7 @@ var require_request = __commonJS({
|
|
|
22502
22699
|
this.completed = false;
|
|
22503
22700
|
this.aborted = false;
|
|
22504
22701
|
this.upgrade = upgrade || null;
|
|
22505
|
-
this.path = query ? serializePathWithQuery(
|
|
22702
|
+
this.path = query ? serializePathWithQuery(path71, query) : path71;
|
|
22506
22703
|
this.origin = origin;
|
|
22507
22704
|
this.protocol = getProtocolFromUrlString(origin);
|
|
22508
22705
|
this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent;
|
|
@@ -27541,7 +27738,7 @@ var require_client_h1 = __commonJS({
|
|
|
27541
27738
|
return method !== "GET" && method !== "HEAD" && method !== "OPTIONS" && method !== "TRACE" && method !== "CONNECT";
|
|
27542
27739
|
}
|
|
27543
27740
|
function writeH1(client, request2) {
|
|
27544
|
-
const { method, path:
|
|
27741
|
+
const { method, path: path71, host, upgrade, blocking, reset } = request2;
|
|
27545
27742
|
let { body, headers, contentLength } = request2;
|
|
27546
27743
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH" || method === "QUERY" || method === "PROPFIND" || method === "PROPPATCH";
|
|
27547
27744
|
if (util.isFormDataLike(body)) {
|
|
@@ -27610,7 +27807,7 @@ var require_client_h1 = __commonJS({
|
|
|
27610
27807
|
if (socket.setTypeOfService) {
|
|
27611
27808
|
socket.setTypeOfService(request2.typeOfService);
|
|
27612
27809
|
}
|
|
27613
|
-
let header = `${method} ${
|
|
27810
|
+
let header = `${method} ${path71} HTTP/1.1\r
|
|
27614
27811
|
`;
|
|
27615
27812
|
if (typeof host === "string") {
|
|
27616
27813
|
header += `host: ${host}\r
|
|
@@ -28263,7 +28460,7 @@ var require_client_h2 = __commonJS({
|
|
|
28263
28460
|
function writeH2(client, request2) {
|
|
28264
28461
|
const requestTimeout = request2.bodyTimeout ?? client[kBodyTimeout];
|
|
28265
28462
|
const session = client[kHTTP2Session];
|
|
28266
|
-
const { method, path:
|
|
28463
|
+
const { method, path: path71, host, upgrade, expectContinue, signal, protocol, headers: reqHeaders } = request2;
|
|
28267
28464
|
let { body } = request2;
|
|
28268
28465
|
if (upgrade != null && upgrade !== "websocket") {
|
|
28269
28466
|
util.errorRequest(client, request2, new InvalidArgumentError(`Custom upgrade "${upgrade}" not supported over HTTP/2`));
|
|
@@ -28331,7 +28528,7 @@ var require_client_h2 = __commonJS({
|
|
|
28331
28528
|
}
|
|
28332
28529
|
headers[HTTP2_HEADER_METHOD] = "CONNECT";
|
|
28333
28530
|
headers[HTTP2_HEADER_PROTOCOL] = "websocket";
|
|
28334
|
-
headers[HTTP2_HEADER_PATH] =
|
|
28531
|
+
headers[HTTP2_HEADER_PATH] = path71;
|
|
28335
28532
|
if (protocol === "ws:" || protocol === "wss:") {
|
|
28336
28533
|
headers[HTTP2_HEADER_SCHEME] = protocol === "ws:" ? "http" : "https";
|
|
28337
28534
|
} else {
|
|
@@ -28372,7 +28569,7 @@ var require_client_h2 = __commonJS({
|
|
|
28372
28569
|
stream.setTimeout(requestTimeout);
|
|
28373
28570
|
return true;
|
|
28374
28571
|
}
|
|
28375
|
-
headers[HTTP2_HEADER_PATH] =
|
|
28572
|
+
headers[HTTP2_HEADER_PATH] = path71;
|
|
28376
28573
|
headers[HTTP2_HEADER_SCHEME] = protocol === "http:" ? "http" : "https";
|
|
28377
28574
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
|
|
28378
28575
|
if (body && typeof body.read === "function") {
|
|
@@ -30674,10 +30871,10 @@ var require_proxy_agent = __commonJS({
|
|
|
30674
30871
|
};
|
|
30675
30872
|
const {
|
|
30676
30873
|
origin,
|
|
30677
|
-
path:
|
|
30874
|
+
path: path71 = "/",
|
|
30678
30875
|
headers = {}
|
|
30679
30876
|
} = opts;
|
|
30680
|
-
opts.path = origin +
|
|
30877
|
+
opts.path = origin + path71;
|
|
30681
30878
|
if (!("host" in headers) && !("Host" in headers)) {
|
|
30682
30879
|
const { host } = new URL(origin);
|
|
30683
30880
|
headers.host = host;
|
|
@@ -32740,20 +32937,20 @@ var require_mock_utils = __commonJS({
|
|
|
32740
32937
|
}
|
|
32741
32938
|
return normalizedQp;
|
|
32742
32939
|
}
|
|
32743
|
-
function safeUrl(
|
|
32744
|
-
if (typeof
|
|
32745
|
-
return
|
|
32940
|
+
function safeUrl(path71) {
|
|
32941
|
+
if (typeof path71 !== "string") {
|
|
32942
|
+
return path71;
|
|
32746
32943
|
}
|
|
32747
|
-
const pathSegments =
|
|
32944
|
+
const pathSegments = path71.split("?", 3);
|
|
32748
32945
|
if (pathSegments.length !== 2) {
|
|
32749
|
-
return
|
|
32946
|
+
return path71;
|
|
32750
32947
|
}
|
|
32751
32948
|
const qp = new URLSearchParams(pathSegments.pop());
|
|
32752
32949
|
qp.sort();
|
|
32753
32950
|
return [...pathSegments, qp.toString()].join("?");
|
|
32754
32951
|
}
|
|
32755
|
-
function matchKey(mockDispatch2, { path:
|
|
32756
|
-
const pathMatch = matchValue(mockDispatch2.path,
|
|
32952
|
+
function matchKey(mockDispatch2, { path: path71, method, body, headers }) {
|
|
32953
|
+
const pathMatch = matchValue(mockDispatch2.path, path71);
|
|
32757
32954
|
const methodMatch = matchValue(mockDispatch2.method, method);
|
|
32758
32955
|
const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body) : true;
|
|
32759
32956
|
const headersMatch = matchHeaders(mockDispatch2, headers);
|
|
@@ -32778,8 +32975,8 @@ var require_mock_utils = __commonJS({
|
|
|
32778
32975
|
const basePath = key.query ? serializePathWithQuery(key.path, key.query) : key.path;
|
|
32779
32976
|
const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath;
|
|
32780
32977
|
const resolvedPathWithoutTrailingSlash = removeTrailingSlash(resolvedPath);
|
|
32781
|
-
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path:
|
|
32782
|
-
return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(
|
|
32978
|
+
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path71, ignoreTrailingSlash }) => {
|
|
32979
|
+
return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(path71)), resolvedPathWithoutTrailingSlash) : matchValue(safeUrl(path71), resolvedPath);
|
|
32783
32980
|
});
|
|
32784
32981
|
if (matchedMockDispatches.length === 0) {
|
|
32785
32982
|
throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`);
|
|
@@ -32818,19 +33015,19 @@ var require_mock_utils = __commonJS({
|
|
|
32818
33015
|
mockDispatches.splice(index, 1);
|
|
32819
33016
|
}
|
|
32820
33017
|
}
|
|
32821
|
-
function removeTrailingSlash(
|
|
32822
|
-
while (
|
|
32823
|
-
|
|
33018
|
+
function removeTrailingSlash(path71) {
|
|
33019
|
+
while (path71.endsWith("/")) {
|
|
33020
|
+
path71 = path71.slice(0, -1);
|
|
32824
33021
|
}
|
|
32825
|
-
if (
|
|
32826
|
-
|
|
33022
|
+
if (path71.length === 0) {
|
|
33023
|
+
path71 = "/";
|
|
32827
33024
|
}
|
|
32828
|
-
return
|
|
33025
|
+
return path71;
|
|
32829
33026
|
}
|
|
32830
33027
|
function buildKey(opts) {
|
|
32831
|
-
const { path:
|
|
33028
|
+
const { path: path71, method, body, headers, query } = opts;
|
|
32832
33029
|
return {
|
|
32833
|
-
path:
|
|
33030
|
+
path: path71,
|
|
32834
33031
|
method,
|
|
32835
33032
|
body,
|
|
32836
33033
|
headers,
|
|
@@ -33520,10 +33717,10 @@ var require_pending_interceptors_formatter = __commonJS({
|
|
|
33520
33717
|
}
|
|
33521
33718
|
format(pendingInterceptors) {
|
|
33522
33719
|
const withPrettyHeaders = pendingInterceptors.map(
|
|
33523
|
-
({ method, path:
|
|
33720
|
+
({ method, path: path71, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
|
|
33524
33721
|
Method: method,
|
|
33525
33722
|
Origin: origin,
|
|
33526
|
-
Path:
|
|
33723
|
+
Path: path71,
|
|
33527
33724
|
"Status code": statusCode,
|
|
33528
33725
|
Persistent: persist ? PERSISTENT : NOT_PERSISTENT,
|
|
33529
33726
|
Invocations: timesInvoked,
|
|
@@ -33605,9 +33802,9 @@ var require_mock_agent = __commonJS({
|
|
|
33605
33802
|
const acceptNonStandardSearchParameters = this[kMockAgentAcceptsNonStandardSearchParameters];
|
|
33606
33803
|
const dispatchOpts = { ...opts };
|
|
33607
33804
|
if (acceptNonStandardSearchParameters && dispatchOpts.path) {
|
|
33608
|
-
const [
|
|
33805
|
+
const [path71, searchParams] = dispatchOpts.path.split("?");
|
|
33609
33806
|
const normalizedSearchParams = normalizeSearchParams(searchParams, acceptNonStandardSearchParameters);
|
|
33610
|
-
dispatchOpts.path = `${
|
|
33807
|
+
dispatchOpts.path = `${path71}?${normalizedSearchParams}`;
|
|
33611
33808
|
}
|
|
33612
33809
|
return this[kAgent].dispatch(dispatchOpts, handler);
|
|
33613
33810
|
}
|
|
@@ -34008,12 +34205,12 @@ var require_snapshot_recorder = __commonJS({
|
|
|
34008
34205
|
* @return {Promise<void>} - Resolves when snapshots are loaded
|
|
34009
34206
|
*/
|
|
34010
34207
|
async loadSnapshots(filePath) {
|
|
34011
|
-
const
|
|
34012
|
-
if (!
|
|
34208
|
+
const path71 = filePath || this.#snapshotPath;
|
|
34209
|
+
if (!path71) {
|
|
34013
34210
|
throw new InvalidArgumentError("Snapshot path is required");
|
|
34014
34211
|
}
|
|
34015
34212
|
try {
|
|
34016
|
-
const data = await readFile(resolve2(
|
|
34213
|
+
const data = await readFile(resolve2(path71), "utf8");
|
|
34017
34214
|
const parsed = JSON.parse(data);
|
|
34018
34215
|
if (Array.isArray(parsed)) {
|
|
34019
34216
|
this.#snapshots.clear();
|
|
@@ -34027,7 +34224,7 @@ var require_snapshot_recorder = __commonJS({
|
|
|
34027
34224
|
if (error.code === "ENOENT") {
|
|
34028
34225
|
this.#snapshots.clear();
|
|
34029
34226
|
} else {
|
|
34030
|
-
throw new UndiciError(`Failed to load snapshots from ${
|
|
34227
|
+
throw new UndiciError(`Failed to load snapshots from ${path71}`, { cause: error });
|
|
34031
34228
|
}
|
|
34032
34229
|
}
|
|
34033
34230
|
}
|
|
@@ -34038,11 +34235,11 @@ var require_snapshot_recorder = __commonJS({
|
|
|
34038
34235
|
* @returns {Promise<void>} - Resolves when snapshots are saved
|
|
34039
34236
|
*/
|
|
34040
34237
|
async saveSnapshots(filePath) {
|
|
34041
|
-
const
|
|
34042
|
-
if (!
|
|
34238
|
+
const path71 = filePath || this.#snapshotPath;
|
|
34239
|
+
if (!path71) {
|
|
34043
34240
|
throw new InvalidArgumentError("Snapshot path is required");
|
|
34044
34241
|
}
|
|
34045
|
-
const resolvedPath = resolve2(
|
|
34242
|
+
const resolvedPath = resolve2(path71);
|
|
34046
34243
|
await mkdir(dirname2(resolvedPath), { recursive: true });
|
|
34047
34244
|
const data = Array.from(this.#snapshots.entries()).map(([hash, snapshot]) => ({
|
|
34048
34245
|
hash,
|
|
@@ -34667,15 +34864,15 @@ var require_redirect_handler = __commonJS({
|
|
|
34667
34864
|
return;
|
|
34668
34865
|
}
|
|
34669
34866
|
const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin)));
|
|
34670
|
-
const
|
|
34671
|
-
const redirectUrlString = `${origin}${
|
|
34867
|
+
const path71 = search ? `${pathname}${search}` : pathname;
|
|
34868
|
+
const redirectUrlString = `${origin}${path71}`;
|
|
34672
34869
|
for (const historyUrl of this.history) {
|
|
34673
34870
|
if (historyUrl.toString() === redirectUrlString) {
|
|
34674
34871
|
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.`);
|
|
34675
34872
|
}
|
|
34676
34873
|
}
|
|
34677
34874
|
this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin);
|
|
34678
|
-
this.opts.path =
|
|
34875
|
+
this.opts.path = path71;
|
|
34679
34876
|
this.opts.origin = origin;
|
|
34680
34877
|
this.opts.query = null;
|
|
34681
34878
|
}
|
|
@@ -40882,11 +41079,11 @@ var require_fetch = __commonJS({
|
|
|
40882
41079
|
function dispatch({ body }) {
|
|
40883
41080
|
const url = requestCurrentURL(request2);
|
|
40884
41081
|
const agent = fetchParams.controller.dispatcher;
|
|
40885
|
-
const
|
|
41082
|
+
const path71 = url.pathname + url.search;
|
|
40886
41083
|
const hasTrailingQuestionMark = url.search.length === 0 && url.href[url.href.length - url.hash.length - 1] === "?";
|
|
40887
41084
|
return new Promise((resolve2, reject) => agent.dispatch(
|
|
40888
41085
|
{
|
|
40889
|
-
path: hasTrailingQuestionMark ? `${
|
|
41086
|
+
path: hasTrailingQuestionMark ? `${path71}?` : path71,
|
|
40890
41087
|
origin: url.origin,
|
|
40891
41088
|
method: request2.method,
|
|
40892
41089
|
body: agent.isMockActive ? request2.body && (request2.body.source || request2.body.stream) : body,
|
|
@@ -41817,9 +42014,9 @@ var require_util4 = __commonJS({
|
|
|
41817
42014
|
}
|
|
41818
42015
|
}
|
|
41819
42016
|
}
|
|
41820
|
-
function validateCookiePath(
|
|
41821
|
-
for (let i = 0; i <
|
|
41822
|
-
const code =
|
|
42017
|
+
function validateCookiePath(path71) {
|
|
42018
|
+
for (let i = 0; i < path71.length; ++i) {
|
|
42019
|
+
const code = path71.charCodeAt(i);
|
|
41823
42020
|
if (code < 32 || // exclude CTLs (0-31)
|
|
41824
42021
|
code === 127 || // DEL
|
|
41825
42022
|
code === 59) {
|
|
@@ -44989,11 +45186,11 @@ var require_undici = __commonJS({
|
|
|
44989
45186
|
if (typeof opts.path !== "string") {
|
|
44990
45187
|
throw new InvalidArgumentError("invalid opts.path");
|
|
44991
45188
|
}
|
|
44992
|
-
let
|
|
45189
|
+
let path71 = opts.path;
|
|
44993
45190
|
if (!opts.path.startsWith("/")) {
|
|
44994
|
-
|
|
45191
|
+
path71 = `/${path71}`;
|
|
44995
45192
|
}
|
|
44996
|
-
url = new URL(util.parseOrigin(url).origin +
|
|
45193
|
+
url = new URL(util.parseOrigin(url).origin + path71);
|
|
44997
45194
|
} else {
|
|
44998
45195
|
if (!opts) {
|
|
44999
45196
|
opts = typeof url === "object" ? url : {};
|
|
@@ -45131,20 +45328,20 @@ function getModelContextLimit(model) {
|
|
|
45131
45328
|
return 2e5;
|
|
45132
45329
|
}
|
|
45133
45330
|
function readSessionUsage() {
|
|
45134
|
-
const projectsDir =
|
|
45135
|
-
if (!
|
|
45331
|
+
const projectsDir = import_path67.default.join(import_os60.default.homedir(), ".claude", "projects");
|
|
45332
|
+
if (!import_fs70.default.existsSync(projectsDir)) return null;
|
|
45136
45333
|
let latestFile = null;
|
|
45137
45334
|
let latestMtime = 0;
|
|
45138
45335
|
try {
|
|
45139
|
-
for (const dir of
|
|
45140
|
-
const dirPath =
|
|
45336
|
+
for (const dir of import_fs70.default.readdirSync(projectsDir)) {
|
|
45337
|
+
const dirPath = import_path67.default.join(projectsDir, dir);
|
|
45141
45338
|
try {
|
|
45142
|
-
if (!
|
|
45143
|
-
for (const file of
|
|
45339
|
+
if (!import_fs70.default.statSync(dirPath).isDirectory()) continue;
|
|
45340
|
+
for (const file of import_fs70.default.readdirSync(dirPath)) {
|
|
45144
45341
|
if (!file.endsWith(".jsonl") || file.startsWith("agent-")) continue;
|
|
45145
|
-
const filePath =
|
|
45342
|
+
const filePath = import_path67.default.join(dirPath, file);
|
|
45146
45343
|
try {
|
|
45147
|
-
const mtime =
|
|
45344
|
+
const mtime = import_fs70.default.statSync(filePath).mtimeMs;
|
|
45148
45345
|
if (mtime > latestMtime) {
|
|
45149
45346
|
latestMtime = mtime;
|
|
45150
45347
|
latestFile = filePath;
|
|
@@ -45159,7 +45356,7 @@ function readSessionUsage() {
|
|
|
45159
45356
|
}
|
|
45160
45357
|
if (!latestFile) return null;
|
|
45161
45358
|
try {
|
|
45162
|
-
const lines =
|
|
45359
|
+
const lines = import_fs70.default.readFileSync(latestFile, "utf-8").split("\n");
|
|
45163
45360
|
let lastModel = "";
|
|
45164
45361
|
let lastInput = 0;
|
|
45165
45362
|
let lastOutput = 0;
|
|
@@ -45220,7 +45417,7 @@ function formatBase(activity) {
|
|
|
45220
45417
|
const time = new Date(activity.ts).toLocaleTimeString([], { hour12: false });
|
|
45221
45418
|
const icon = getIcon(activity.tool);
|
|
45222
45419
|
const toolName = activity.tool.slice(0, 16).padEnd(16);
|
|
45223
|
-
const argsStr = JSON.stringify(activity.args ?? {}).replace(/\s+/g, " ").replaceAll(
|
|
45420
|
+
const argsStr = JSON.stringify(activity.args ?? {}).replace(/\s+/g, " ").replaceAll(import_os60.default.homedir(), "~");
|
|
45224
45421
|
const argsPreview = argsStr.length > 70 ? argsStr.slice(0, 70) + "\u2026" : argsStr;
|
|
45225
45422
|
return `${import_chalk40.default.gray(time)} ${icon} ${agentLabel(activity.agent, activity.mcpServer, activity.sessionId)}${import_chalk40.default.white.bold(toolName)} ${import_chalk40.default.dim(argsPreview)}`;
|
|
45226
45423
|
}
|
|
@@ -45259,9 +45456,9 @@ function renderPending(activity) {
|
|
|
45259
45456
|
}
|
|
45260
45457
|
async function ensureDaemon() {
|
|
45261
45458
|
let pidPort = null;
|
|
45262
|
-
if (
|
|
45459
|
+
if (import_fs70.default.existsSync(PID_FILE)) {
|
|
45263
45460
|
try {
|
|
45264
|
-
const { port } = JSON.parse(
|
|
45461
|
+
const { port } = JSON.parse(import_fs70.default.readFileSync(PID_FILE, "utf-8"));
|
|
45265
45462
|
pidPort = port;
|
|
45266
45463
|
} catch {
|
|
45267
45464
|
console.error(import_chalk40.default.dim("\u26A0\uFE0F Could not read PID file; falling back to default port."));
|
|
@@ -45417,9 +45614,9 @@ function buildRecoveryCardLines(req) {
|
|
|
45417
45614
|
];
|
|
45418
45615
|
}
|
|
45419
45616
|
function readApproversFromDisk() {
|
|
45420
|
-
const configPath =
|
|
45617
|
+
const configPath = import_path67.default.join(import_os60.default.homedir(), ".node9", "config.json");
|
|
45421
45618
|
try {
|
|
45422
|
-
const raw = JSON.parse(
|
|
45619
|
+
const raw = JSON.parse(import_fs70.default.readFileSync(configPath, "utf-8"));
|
|
45423
45620
|
const settings = raw.settings ?? {};
|
|
45424
45621
|
return settings.approvers ?? {};
|
|
45425
45622
|
} catch {
|
|
@@ -45435,15 +45632,15 @@ function approverStatusLine() {
|
|
|
45435
45632
|
return `${fmt("native", "native")} ${fmt("cloud", "cloud")} ${fmt("terminal", "terminal")}`;
|
|
45436
45633
|
}
|
|
45437
45634
|
function toggleApprover(channel) {
|
|
45438
|
-
const configPath =
|
|
45635
|
+
const configPath = import_path67.default.join(import_os60.default.homedir(), ".node9", "config.json");
|
|
45439
45636
|
try {
|
|
45440
|
-
const raw = JSON.parse(
|
|
45637
|
+
const raw = JSON.parse(import_fs70.default.readFileSync(configPath, "utf-8"));
|
|
45441
45638
|
const settings = raw.settings ?? {};
|
|
45442
45639
|
const approvers = settings.approvers ?? {};
|
|
45443
45640
|
approvers[channel] = approvers[channel] === false;
|
|
45444
45641
|
settings.approvers = approvers;
|
|
45445
45642
|
raw.settings = settings;
|
|
45446
|
-
|
|
45643
|
+
import_fs70.default.writeFileSync(configPath, JSON.stringify(raw, null, 2) + "\n");
|
|
45447
45644
|
} catch (err2) {
|
|
45448
45645
|
process.stderr.write(`[node9] toggleApprover failed: ${String(err2)}
|
|
45449
45646
|
`);
|
|
@@ -45615,8 +45812,8 @@ async function startTail(options = {}) {
|
|
|
45615
45812
|
}
|
|
45616
45813
|
postDecisionHttp(req2.id, httpDecision, authToken, port, httpOpts).catch((err2) => {
|
|
45617
45814
|
try {
|
|
45618
|
-
|
|
45619
|
-
|
|
45815
|
+
import_fs70.default.appendFileSync(
|
|
45816
|
+
import_path67.default.join(import_os60.default.homedir(), ".node9", "hook-debug.log"),
|
|
45620
45817
|
`[tail] POST /decision failed: ${String(err2)}
|
|
45621
45818
|
`
|
|
45622
45819
|
);
|
|
@@ -45680,9 +45877,9 @@ async function startTail(options = {}) {
|
|
|
45680
45877
|
};
|
|
45681
45878
|
process.stdin.on("keypress", onKeypress);
|
|
45682
45879
|
}
|
|
45683
|
-
const auditLog =
|
|
45880
|
+
const auditLog = import_path67.default.join(import_os60.default.homedir(), ".node9", "audit.log");
|
|
45684
45881
|
try {
|
|
45685
|
-
const unackedDlp =
|
|
45882
|
+
const unackedDlp = import_fs70.default.readFileSync(auditLog, "utf-8").split("\n").filter((l) => l.includes('"response-dlp"')).length;
|
|
45686
45883
|
if (unackedDlp > 0) {
|
|
45687
45884
|
console.log("");
|
|
45688
45885
|
console.log(
|
|
@@ -45722,7 +45919,7 @@ async function startTail(options = {}) {
|
|
|
45722
45919
|
if (stallWarned) return;
|
|
45723
45920
|
if (Date.now() - lastActivityFromDaemon < STALL_THRESHOLD_MS) return;
|
|
45724
45921
|
try {
|
|
45725
|
-
const auditMtime =
|
|
45922
|
+
const auditMtime = import_fs70.default.statSync(auditLog).mtimeMs;
|
|
45726
45923
|
if (Date.now() - auditMtime >= STALL_THRESHOLD_MS) return;
|
|
45727
45924
|
console.log("");
|
|
45728
45925
|
console.log(
|
|
@@ -45907,20 +46104,20 @@ async function startTail(options = {}) {
|
|
|
45907
46104
|
process.exit(1);
|
|
45908
46105
|
});
|
|
45909
46106
|
}
|
|
45910
|
-
var import_http5, import_chalk40,
|
|
46107
|
+
var import_http5, import_chalk40, import_fs70, import_os60, import_path67, 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;
|
|
45911
46108
|
var init_tail = __esm({
|
|
45912
46109
|
"src/tui/tail.ts"() {
|
|
45913
46110
|
"use strict";
|
|
45914
46111
|
import_http5 = __toESM(require("http"));
|
|
45915
46112
|
import_chalk40 = __toESM(require("chalk"));
|
|
45916
|
-
|
|
45917
|
-
|
|
45918
|
-
|
|
46113
|
+
import_fs70 = __toESM(require("fs"));
|
|
46114
|
+
import_os60 = __toESM(require("os"));
|
|
46115
|
+
import_path67 = __toESM(require("path"));
|
|
45919
46116
|
import_readline6 = __toESM(require("readline"));
|
|
45920
46117
|
import_child_process14 = require("child_process");
|
|
45921
46118
|
init_daemon2();
|
|
45922
46119
|
init_daemon();
|
|
45923
|
-
PID_FILE =
|
|
46120
|
+
PID_FILE = import_path67.default.join(import_os60.default.homedir(), ".node9", "daemon.pid");
|
|
45924
46121
|
ICONS = {
|
|
45925
46122
|
bash: "\u{1F4BB}",
|
|
45926
46123
|
shell: "\u{1F4BB}",
|
|
@@ -46042,9 +46239,9 @@ function formatTimeLeft(resetsAt) {
|
|
|
46042
46239
|
return ` (${m}m left)`;
|
|
46043
46240
|
}
|
|
46044
46241
|
function safeReadJson(filePath) {
|
|
46045
|
-
if (!
|
|
46242
|
+
if (!import_fs71.default.existsSync(filePath)) return null;
|
|
46046
46243
|
try {
|
|
46047
|
-
return JSON.parse(
|
|
46244
|
+
return JSON.parse(import_fs71.default.readFileSync(filePath, "utf-8"));
|
|
46048
46245
|
} catch {
|
|
46049
46246
|
return null;
|
|
46050
46247
|
}
|
|
@@ -46065,12 +46262,12 @@ function countHooksInFile(filePath) {
|
|
|
46065
46262
|
return Object.keys(cfg.hooks).length;
|
|
46066
46263
|
}
|
|
46067
46264
|
function countRulesInDir(rulesDir) {
|
|
46068
|
-
if (!
|
|
46265
|
+
if (!import_fs71.default.existsSync(rulesDir)) return 0;
|
|
46069
46266
|
let count = 0;
|
|
46070
46267
|
try {
|
|
46071
|
-
for (const entry of
|
|
46268
|
+
for (const entry of import_fs71.default.readdirSync(rulesDir, { withFileTypes: true })) {
|
|
46072
46269
|
if (entry.isDirectory()) {
|
|
46073
|
-
count += countRulesInDir(
|
|
46270
|
+
count += countRulesInDir(import_path68.default.join(rulesDir, entry.name));
|
|
46074
46271
|
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
46075
46272
|
count++;
|
|
46076
46273
|
}
|
|
@@ -46081,46 +46278,46 @@ function countRulesInDir(rulesDir) {
|
|
|
46081
46278
|
}
|
|
46082
46279
|
function isSamePath(a, b) {
|
|
46083
46280
|
try {
|
|
46084
|
-
return
|
|
46281
|
+
return import_path68.default.resolve(a) === import_path68.default.resolve(b);
|
|
46085
46282
|
} catch {
|
|
46086
46283
|
return false;
|
|
46087
46284
|
}
|
|
46088
46285
|
}
|
|
46089
46286
|
function countConfigs(cwd) {
|
|
46090
|
-
const homeDir2 =
|
|
46091
|
-
const claudeDir =
|
|
46287
|
+
const homeDir2 = import_os61.default.homedir();
|
|
46288
|
+
const claudeDir = import_path68.default.join(homeDir2, ".claude");
|
|
46092
46289
|
let claudeMdCount = 0;
|
|
46093
46290
|
let rulesCount = 0;
|
|
46094
46291
|
let hooksCount = 0;
|
|
46095
46292
|
const userMcpServers = /* @__PURE__ */ new Set();
|
|
46096
46293
|
const projectMcpServers = /* @__PURE__ */ new Set();
|
|
46097
|
-
if (
|
|
46098
|
-
rulesCount += countRulesInDir(
|
|
46099
|
-
const userSettings =
|
|
46294
|
+
if (import_fs71.default.existsSync(import_path68.default.join(claudeDir, "CLAUDE.md"))) claudeMdCount++;
|
|
46295
|
+
rulesCount += countRulesInDir(import_path68.default.join(claudeDir, "rules"));
|
|
46296
|
+
const userSettings = import_path68.default.join(claudeDir, "settings.json");
|
|
46100
46297
|
for (const name of getMcpServerNames(userSettings)) userMcpServers.add(name);
|
|
46101
46298
|
hooksCount += countHooksInFile(userSettings);
|
|
46102
|
-
const userClaudeJson =
|
|
46299
|
+
const userClaudeJson = import_path68.default.join(homeDir2, ".claude.json");
|
|
46103
46300
|
for (const name of getMcpServerNames(userClaudeJson)) userMcpServers.add(name);
|
|
46104
46301
|
for (const name of getDisabledMcpServers(userClaudeJson, "disabledMcpServers")) {
|
|
46105
46302
|
userMcpServers.delete(name);
|
|
46106
46303
|
}
|
|
46107
46304
|
if (cwd) {
|
|
46108
|
-
if (
|
|
46109
|
-
if (
|
|
46110
|
-
const projectClaudeDir =
|
|
46305
|
+
if (import_fs71.default.existsSync(import_path68.default.join(cwd, "CLAUDE.md"))) claudeMdCount++;
|
|
46306
|
+
if (import_fs71.default.existsSync(import_path68.default.join(cwd, "CLAUDE.local.md"))) claudeMdCount++;
|
|
46307
|
+
const projectClaudeDir = import_path68.default.join(cwd, ".claude");
|
|
46111
46308
|
const overlapsUserScope = isSamePath(projectClaudeDir, claudeDir);
|
|
46112
46309
|
if (!overlapsUserScope) {
|
|
46113
|
-
if (
|
|
46114
|
-
rulesCount += countRulesInDir(
|
|
46115
|
-
const projSettings =
|
|
46310
|
+
if (import_fs71.default.existsSync(import_path68.default.join(projectClaudeDir, "CLAUDE.md"))) claudeMdCount++;
|
|
46311
|
+
rulesCount += countRulesInDir(import_path68.default.join(projectClaudeDir, "rules"));
|
|
46312
|
+
const projSettings = import_path68.default.join(projectClaudeDir, "settings.json");
|
|
46116
46313
|
for (const name of getMcpServerNames(projSettings)) projectMcpServers.add(name);
|
|
46117
46314
|
hooksCount += countHooksInFile(projSettings);
|
|
46118
46315
|
}
|
|
46119
|
-
if (
|
|
46120
|
-
const localSettings =
|
|
46316
|
+
if (import_fs71.default.existsSync(import_path68.default.join(projectClaudeDir, "CLAUDE.local.md"))) claudeMdCount++;
|
|
46317
|
+
const localSettings = import_path68.default.join(projectClaudeDir, "settings.local.json");
|
|
46121
46318
|
for (const name of getMcpServerNames(localSettings)) projectMcpServers.add(name);
|
|
46122
46319
|
hooksCount += countHooksInFile(localSettings);
|
|
46123
|
-
const mcpJsonServers = getMcpServerNames(
|
|
46320
|
+
const mcpJsonServers = getMcpServerNames(import_path68.default.join(cwd, ".mcp.json"));
|
|
46124
46321
|
const disabledMcpJson = getDisabledMcpServers(localSettings, "disabledMcpjsonServers");
|
|
46125
46322
|
for (const name of disabledMcpJson) mcpJsonServers.delete(name);
|
|
46126
46323
|
for (const name of mcpJsonServers) projectMcpServers.add(name);
|
|
@@ -46153,12 +46350,12 @@ function readActiveShieldsHud() {
|
|
|
46153
46350
|
return shieldsCache.value;
|
|
46154
46351
|
}
|
|
46155
46352
|
try {
|
|
46156
|
-
const shieldsPath =
|
|
46157
|
-
if (!
|
|
46353
|
+
const shieldsPath = import_path68.default.join(import_os61.default.homedir(), ".node9", "shields.json");
|
|
46354
|
+
if (!import_fs71.default.existsSync(shieldsPath)) {
|
|
46158
46355
|
shieldsCache = { value: [], ts: now };
|
|
46159
46356
|
return [];
|
|
46160
46357
|
}
|
|
46161
|
-
const parsed = JSON.parse(
|
|
46358
|
+
const parsed = JSON.parse(import_fs71.default.readFileSync(shieldsPath, "utf-8"));
|
|
46162
46359
|
if (!Array.isArray(parsed.active)) {
|
|
46163
46360
|
shieldsCache = { value: [], ts: now };
|
|
46164
46361
|
return [];
|
|
@@ -46260,17 +46457,17 @@ function renderContextLine(stdin) {
|
|
|
46260
46457
|
async function main() {
|
|
46261
46458
|
try {
|
|
46262
46459
|
const [stdin, daemonStatus2] = await Promise.all([readStdin(), queryDaemon()]);
|
|
46263
|
-
if (
|
|
46460
|
+
if (import_fs71.default.existsSync(import_path68.default.join(import_os61.default.homedir(), ".node9", "hud-debug"))) {
|
|
46264
46461
|
try {
|
|
46265
|
-
const logPath =
|
|
46462
|
+
const logPath = import_path68.default.join(import_os61.default.homedir(), ".node9", "hud-debug.log");
|
|
46266
46463
|
const MAX_LOG_SIZE = 10 * 1024 * 1024;
|
|
46267
46464
|
let size = 0;
|
|
46268
46465
|
try {
|
|
46269
|
-
size =
|
|
46466
|
+
size = import_fs71.default.statSync(logPath).size;
|
|
46270
46467
|
} catch {
|
|
46271
46468
|
}
|
|
46272
46469
|
if (size < MAX_LOG_SIZE) {
|
|
46273
|
-
|
|
46470
|
+
import_fs71.default.appendFileSync(
|
|
46274
46471
|
logPath,
|
|
46275
46472
|
JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), stdin }) + "\n"
|
|
46276
46473
|
);
|
|
@@ -46291,11 +46488,11 @@ async function main() {
|
|
|
46291
46488
|
try {
|
|
46292
46489
|
const cwd = stdin.cwd ?? process.cwd();
|
|
46293
46490
|
for (const configPath of [
|
|
46294
|
-
|
|
46295
|
-
|
|
46491
|
+
import_path68.default.join(cwd, "node9.config.json"),
|
|
46492
|
+
import_path68.default.join(import_os61.default.homedir(), ".node9", "config.json")
|
|
46296
46493
|
]) {
|
|
46297
|
-
if (!
|
|
46298
|
-
const cfg = JSON.parse(
|
|
46494
|
+
if (!import_fs71.default.existsSync(configPath)) continue;
|
|
46495
|
+
const cfg = JSON.parse(import_fs71.default.readFileSync(configPath, "utf-8"));
|
|
46299
46496
|
const hud = cfg.settings?.hud;
|
|
46300
46497
|
if (hud && "showEnvironmentCounts" in hud) return hud.showEnvironmentCounts !== false;
|
|
46301
46498
|
}
|
|
@@ -46313,13 +46510,13 @@ async function main() {
|
|
|
46313
46510
|
renderOffline();
|
|
46314
46511
|
}
|
|
46315
46512
|
}
|
|
46316
|
-
var
|
|
46513
|
+
var import_fs71, import_path68, 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;
|
|
46317
46514
|
var init_hud = __esm({
|
|
46318
46515
|
"src/cli/hud.ts"() {
|
|
46319
46516
|
"use strict";
|
|
46320
|
-
|
|
46321
|
-
|
|
46322
|
-
|
|
46517
|
+
import_fs71 = __toESM(require("fs"));
|
|
46518
|
+
import_path68 = __toESM(require("path"));
|
|
46519
|
+
import_os61 = __toESM(require("os"));
|
|
46323
46520
|
import_http6 = __toESM(require("http"));
|
|
46324
46521
|
init_daemon();
|
|
46325
46522
|
RESET3 = "\x1B[0m";
|
|
@@ -46441,9 +46638,9 @@ function writeCredentialsAndConfig(apiKey, opts = {}) {
|
|
|
46441
46638
|
// src/cli.ts
|
|
46442
46639
|
init_daemon2();
|
|
46443
46640
|
var import_chalk41 = __toESM(require("chalk"));
|
|
46444
|
-
var
|
|
46445
|
-
var
|
|
46446
|
-
var
|
|
46641
|
+
var import_fs72 = __toESM(require("fs"));
|
|
46642
|
+
var import_path69 = __toESM(require("path"));
|
|
46643
|
+
var import_os62 = __toESM(require("os"));
|
|
46447
46644
|
var import_child_process15 = require("child_process");
|
|
46448
46645
|
var import_prompts2 = require("@inquirer/prompts");
|
|
46449
46646
|
|
|
@@ -46630,26 +46827,48 @@ async function runProxy(targetCommand) {
|
|
|
46630
46827
|
|
|
46631
46828
|
// src/cli/daemon-starter.ts
|
|
46632
46829
|
var import_child_process5 = require("child_process");
|
|
46633
|
-
var
|
|
46634
|
-
var
|
|
46830
|
+
var import_path41 = __toESM(require("path"));
|
|
46831
|
+
var import_fs43 = __toESM(require("fs"));
|
|
46832
|
+
var import_os39 = __toESM(require("os"));
|
|
46635
46833
|
init_daemon();
|
|
46834
|
+
init_startup_log();
|
|
46636
46835
|
function isTestingMode() {
|
|
46637
46836
|
return /^(1|true|yes)$/i.test(process.env.NODE9_TESTING ?? "");
|
|
46638
46837
|
}
|
|
46838
|
+
var SKIP_STAMP = () => import_path41.default.join(import_os39.default.homedir(), ".node9", ".autostart-skip-stamp");
|
|
46839
|
+
var SKIP_THROTTLE_MS = 60 * 60 * 1e3;
|
|
46840
|
+
function logAutostartSkipThrottled(reason) {
|
|
46841
|
+
try {
|
|
46842
|
+
const stamp = SKIP_STAMP();
|
|
46843
|
+
try {
|
|
46844
|
+
if (Date.now() - import_fs43.default.statSync(stamp).mtimeMs < SKIP_THROTTLE_MS) return;
|
|
46845
|
+
} catch {
|
|
46846
|
+
}
|
|
46847
|
+
import_fs43.default.writeFileSync(stamp, "", "utf-8");
|
|
46848
|
+
import_fs43.default.appendFileSync(
|
|
46849
|
+
import_path41.default.join(import_os39.default.homedir(), ".node9", "hook-debug.log"),
|
|
46850
|
+
`[${(/* @__PURE__ */ new Date()).toISOString()}] daemon-autostart-skip: ${reason}
|
|
46851
|
+
`,
|
|
46852
|
+
"utf-8"
|
|
46853
|
+
);
|
|
46854
|
+
} catch {
|
|
46855
|
+
}
|
|
46856
|
+
}
|
|
46639
46857
|
async function autoStartDaemonAndWait() {
|
|
46640
46858
|
if (isTestingMode()) return false;
|
|
46641
|
-
if (!
|
|
46859
|
+
if (!import_path41.default.isAbsolute(process.argv[1])) return false;
|
|
46642
46860
|
let resolvedArgv1;
|
|
46643
46861
|
try {
|
|
46644
|
-
resolvedArgv1 =
|
|
46862
|
+
resolvedArgv1 = import_fs43.default.realpathSync(process.argv[1]);
|
|
46645
46863
|
} catch {
|
|
46646
46864
|
return false;
|
|
46647
46865
|
}
|
|
46648
46866
|
if (!resolvedArgv1.endsWith(".js")) return false;
|
|
46867
|
+
const startupFd = openStartupLogFd();
|
|
46649
46868
|
try {
|
|
46650
46869
|
const child = (0, import_child_process5.spawn)(process.execPath, [resolvedArgv1, "daemon"], {
|
|
46651
46870
|
detached: true,
|
|
46652
|
-
stdio: "ignore",
|
|
46871
|
+
stdio: ["ignore", "ignore", startupFd ?? "ignore"],
|
|
46653
46872
|
env: {
|
|
46654
46873
|
...process.env,
|
|
46655
46874
|
NODE9_AUTO_STARTED: "1"
|
|
@@ -46662,30 +46881,41 @@ async function autoStartDaemonAndWait() {
|
|
|
46662
46881
|
if (await isDaemonReachable()) return true;
|
|
46663
46882
|
}
|
|
46664
46883
|
} catch {
|
|
46884
|
+
} finally {
|
|
46885
|
+
if (startupFd !== void 0) {
|
|
46886
|
+
try {
|
|
46887
|
+
import_fs43.default.closeSync(startupFd);
|
|
46888
|
+
} catch {
|
|
46889
|
+
}
|
|
46890
|
+
}
|
|
46665
46891
|
}
|
|
46666
46892
|
return false;
|
|
46667
46893
|
}
|
|
46668
46894
|
|
|
46895
|
+
// src/cli.ts
|
|
46896
|
+
init_service();
|
|
46897
|
+
|
|
46669
46898
|
// src/cli/commands/check.ts
|
|
46670
46899
|
var import_chalk9 = __toESM(require("chalk"));
|
|
46671
|
-
var
|
|
46900
|
+
var import_fs47 = __toESM(require("fs"));
|
|
46672
46901
|
var import_child_process7 = require("child_process");
|
|
46673
|
-
var
|
|
46674
|
-
var
|
|
46902
|
+
var import_path45 = __toESM(require("path"));
|
|
46903
|
+
var import_os43 = __toESM(require("os"));
|
|
46675
46904
|
init_orchestrator();
|
|
46676
46905
|
init_state();
|
|
46677
46906
|
init_daemon();
|
|
46907
|
+
init_startup_log();
|
|
46678
46908
|
init_config();
|
|
46679
46909
|
init_policy();
|
|
46680
46910
|
|
|
46681
46911
|
// src/undo.ts
|
|
46682
46912
|
var import_child_process6 = require("child_process");
|
|
46683
46913
|
var import_crypto12 = __toESM(require("crypto"));
|
|
46684
|
-
var
|
|
46914
|
+
var import_fs44 = __toESM(require("fs"));
|
|
46685
46915
|
var import_net3 = __toESM(require("net"));
|
|
46686
|
-
var
|
|
46687
|
-
var
|
|
46688
|
-
var ACTIVITY_SOCKET_PATH3 = process.platform === "win32" ? "\\\\.\\pipe\\node9-activity" :
|
|
46916
|
+
var import_path42 = __toESM(require("path"));
|
|
46917
|
+
var import_os40 = __toESM(require("os"));
|
|
46918
|
+
var ACTIVITY_SOCKET_PATH3 = process.platform === "win32" ? "\\\\.\\pipe\\node9-activity" : import_path42.default.join(import_os40.default.tmpdir(), "node9-activity.sock");
|
|
46689
46919
|
function notifySnapshotTaken(hash, tool, argsSummary, fileCount) {
|
|
46690
46920
|
try {
|
|
46691
46921
|
const payload = JSON.stringify({
|
|
@@ -46705,22 +46935,22 @@ function notifySnapshotTaken(hash, tool, argsSummary, fileCount) {
|
|
|
46705
46935
|
} catch {
|
|
46706
46936
|
}
|
|
46707
46937
|
}
|
|
46708
|
-
var SNAPSHOT_STACK_PATH =
|
|
46709
|
-
var UNDO_LATEST_PATH =
|
|
46938
|
+
var SNAPSHOT_STACK_PATH = import_path42.default.join(import_os40.default.homedir(), ".node9", "snapshots.json");
|
|
46939
|
+
var UNDO_LATEST_PATH = import_path42.default.join(import_os40.default.homedir(), ".node9", "undo_latest.txt");
|
|
46710
46940
|
var MAX_SNAPSHOTS = 10;
|
|
46711
46941
|
var GIT_TIMEOUT = 15e3;
|
|
46712
46942
|
function readStack() {
|
|
46713
46943
|
try {
|
|
46714
|
-
if (
|
|
46715
|
-
return JSON.parse(
|
|
46944
|
+
if (import_fs44.default.existsSync(SNAPSHOT_STACK_PATH))
|
|
46945
|
+
return JSON.parse(import_fs44.default.readFileSync(SNAPSHOT_STACK_PATH, "utf-8"));
|
|
46716
46946
|
} catch {
|
|
46717
46947
|
}
|
|
46718
46948
|
return [];
|
|
46719
46949
|
}
|
|
46720
46950
|
function writeStack(stack) {
|
|
46721
|
-
const dir =
|
|
46722
|
-
if (!
|
|
46723
|
-
|
|
46951
|
+
const dir = import_path42.default.dirname(SNAPSHOT_STACK_PATH);
|
|
46952
|
+
if (!import_fs44.default.existsSync(dir)) import_fs44.default.mkdirSync(dir, { recursive: true });
|
|
46953
|
+
import_fs44.default.writeFileSync(SNAPSHOT_STACK_PATH, JSON.stringify(stack, null, 2));
|
|
46724
46954
|
}
|
|
46725
46955
|
function extractFilePath(args) {
|
|
46726
46956
|
if (!args || typeof args !== "object") return null;
|
|
@@ -46740,12 +46970,12 @@ function buildArgsSummary(tool, args) {
|
|
|
46740
46970
|
return "";
|
|
46741
46971
|
}
|
|
46742
46972
|
function findProjectRoot(filePath) {
|
|
46743
|
-
let dir =
|
|
46973
|
+
let dir = import_path42.default.dirname(filePath);
|
|
46744
46974
|
while (true) {
|
|
46745
|
-
if (
|
|
46975
|
+
if (import_fs44.default.existsSync(import_path42.default.join(dir, ".git")) || import_fs44.default.existsSync(import_path42.default.join(dir, "package.json"))) {
|
|
46746
46976
|
return dir;
|
|
46747
46977
|
}
|
|
46748
|
-
const parent =
|
|
46978
|
+
const parent = import_path42.default.dirname(dir);
|
|
46749
46979
|
if (parent === dir) return process.cwd();
|
|
46750
46980
|
dir = parent;
|
|
46751
46981
|
}
|
|
@@ -46753,7 +46983,7 @@ function findProjectRoot(filePath) {
|
|
|
46753
46983
|
function normalizeCwdForHash(cwd) {
|
|
46754
46984
|
let normalized;
|
|
46755
46985
|
try {
|
|
46756
|
-
normalized =
|
|
46986
|
+
normalized = import_fs44.default.realpathSync(cwd);
|
|
46757
46987
|
} catch {
|
|
46758
46988
|
normalized = cwd;
|
|
46759
46989
|
}
|
|
@@ -46763,16 +46993,16 @@ function normalizeCwdForHash(cwd) {
|
|
|
46763
46993
|
}
|
|
46764
46994
|
function getShadowRepoDir(cwd) {
|
|
46765
46995
|
const hash = import_crypto12.default.createHash("sha256").update(normalizeCwdForHash(cwd)).digest("hex").slice(0, 16);
|
|
46766
|
-
return
|
|
46996
|
+
return import_path42.default.join(import_os40.default.homedir(), ".node9", "snapshots", hash);
|
|
46767
46997
|
}
|
|
46768
46998
|
function cleanOrphanedIndexFiles(shadowDir) {
|
|
46769
46999
|
try {
|
|
46770
47000
|
const cutoff = Date.now() - 6e4;
|
|
46771
|
-
for (const f of
|
|
47001
|
+
for (const f of import_fs44.default.readdirSync(shadowDir)) {
|
|
46772
47002
|
if (f.startsWith("index_")) {
|
|
46773
|
-
const fp =
|
|
47003
|
+
const fp = import_path42.default.join(shadowDir, f);
|
|
46774
47004
|
try {
|
|
46775
|
-
if (
|
|
47005
|
+
if (import_fs44.default.statSync(fp).mtimeMs < cutoff) import_fs44.default.unlinkSync(fp);
|
|
46776
47006
|
} catch {
|
|
46777
47007
|
}
|
|
46778
47008
|
}
|
|
@@ -46784,7 +47014,7 @@ function writeShadowExcludes(shadowDir, ignorePaths) {
|
|
|
46784
47014
|
const hardcoded = [".git", ".node9"];
|
|
46785
47015
|
const lines = [...hardcoded, ...ignorePaths].join("\n");
|
|
46786
47016
|
try {
|
|
46787
|
-
|
|
47017
|
+
import_fs44.default.writeFileSync(import_path42.default.join(shadowDir, "info", "exclude"), lines + "\n", "utf8");
|
|
46788
47018
|
} catch {
|
|
46789
47019
|
}
|
|
46790
47020
|
}
|
|
@@ -46797,25 +47027,25 @@ function ensureShadowRepo(shadowDir, cwd) {
|
|
|
46797
47027
|
timeout: 3e3
|
|
46798
47028
|
});
|
|
46799
47029
|
if (check.status === 0) {
|
|
46800
|
-
const ptPath =
|
|
47030
|
+
const ptPath = import_path42.default.join(shadowDir, "project-path.txt");
|
|
46801
47031
|
try {
|
|
46802
|
-
const stored =
|
|
47032
|
+
const stored = import_fs44.default.readFileSync(ptPath, "utf8").trim();
|
|
46803
47033
|
if (stored === normalizedCwd) return true;
|
|
46804
47034
|
if (process.env.NODE9_DEBUG === "1")
|
|
46805
47035
|
console.error(
|
|
46806
47036
|
`[Node9] Shadow repo path mismatch: stored="${stored}" expected="${normalizedCwd}" \u2014 reinitializing`
|
|
46807
47037
|
);
|
|
46808
|
-
|
|
47038
|
+
import_fs44.default.rmSync(shadowDir, { recursive: true, force: true });
|
|
46809
47039
|
} catch {
|
|
46810
47040
|
try {
|
|
46811
|
-
|
|
47041
|
+
import_fs44.default.writeFileSync(ptPath, normalizedCwd, "utf8");
|
|
46812
47042
|
} catch {
|
|
46813
47043
|
}
|
|
46814
47044
|
return true;
|
|
46815
47045
|
}
|
|
46816
47046
|
}
|
|
46817
47047
|
try {
|
|
46818
|
-
|
|
47048
|
+
import_fs44.default.mkdirSync(shadowDir, { recursive: true });
|
|
46819
47049
|
} catch {
|
|
46820
47050
|
}
|
|
46821
47051
|
const init = (0, import_child_process6.spawnSync)("git", ["init", "--bare", shadowDir], { timeout: 5e3 });
|
|
@@ -46824,7 +47054,7 @@ function ensureShadowRepo(shadowDir, cwd) {
|
|
|
46824
47054
|
if (process.env.NODE9_DEBUG === "1") console.error("[Node9] git init --bare failed:", reason);
|
|
46825
47055
|
return false;
|
|
46826
47056
|
}
|
|
46827
|
-
const configFile =
|
|
47057
|
+
const configFile = import_path42.default.join(shadowDir, "config");
|
|
46828
47058
|
(0, import_child_process6.spawnSync)("git", ["config", "--file", configFile, "core.untrackedCache", "true"], {
|
|
46829
47059
|
timeout: 3e3
|
|
46830
47060
|
});
|
|
@@ -46832,7 +47062,7 @@ function ensureShadowRepo(shadowDir, cwd) {
|
|
|
46832
47062
|
timeout: 3e3
|
|
46833
47063
|
});
|
|
46834
47064
|
try {
|
|
46835
|
-
|
|
47065
|
+
import_fs44.default.writeFileSync(import_path42.default.join(shadowDir, "project-path.txt"), normalizedCwd, "utf8");
|
|
46836
47066
|
} catch {
|
|
46837
47067
|
}
|
|
46838
47068
|
return true;
|
|
@@ -46855,12 +47085,12 @@ async function createShadowSnapshot(tool = "unknown", args = {}, ignorePaths = [
|
|
|
46855
47085
|
let indexFile = null;
|
|
46856
47086
|
try {
|
|
46857
47087
|
const rawFilePath = extractFilePath(args);
|
|
46858
|
-
const absFilePath = rawFilePath &&
|
|
47088
|
+
const absFilePath = rawFilePath && import_path42.default.isAbsolute(rawFilePath) ? rawFilePath : null;
|
|
46859
47089
|
const cwd = absFilePath ? findProjectRoot(absFilePath) : process.cwd();
|
|
46860
47090
|
const shadowDir = getShadowRepoDir(cwd);
|
|
46861
47091
|
if (!ensureShadowRepo(shadowDir, cwd)) return null;
|
|
46862
47092
|
writeShadowExcludes(shadowDir, ignorePaths);
|
|
46863
|
-
indexFile =
|
|
47093
|
+
indexFile = import_path42.default.join(shadowDir, `index_${process.pid}_${Date.now()}`);
|
|
46864
47094
|
const shadowEnv = {
|
|
46865
47095
|
...process.env,
|
|
46866
47096
|
GIT_DIR: shadowDir,
|
|
@@ -46932,7 +47162,7 @@ async function createShadowSnapshot(tool = "unknown", args = {}, ignorePaths = [
|
|
|
46932
47162
|
writeStack(stack);
|
|
46933
47163
|
const entry = stack[stack.length - 1];
|
|
46934
47164
|
notifySnapshotTaken(commitHash.slice(0, 7), tool, entry.argsSummary, capturedFiles.length);
|
|
46935
|
-
|
|
47165
|
+
import_fs44.default.writeFileSync(UNDO_LATEST_PATH, commitHash);
|
|
46936
47166
|
if (shouldGc) {
|
|
46937
47167
|
(0, import_child_process6.spawn)("git", ["gc", "--auto"], { env: shadowEnv, detached: true, stdio: "ignore" }).unref();
|
|
46938
47168
|
}
|
|
@@ -46943,7 +47173,7 @@ async function createShadowSnapshot(tool = "unknown", args = {}, ignorePaths = [
|
|
|
46943
47173
|
} finally {
|
|
46944
47174
|
if (indexFile) {
|
|
46945
47175
|
try {
|
|
46946
|
-
|
|
47176
|
+
import_fs44.default.unlinkSync(indexFile);
|
|
46947
47177
|
} catch {
|
|
46948
47178
|
}
|
|
46949
47179
|
}
|
|
@@ -47019,9 +47249,9 @@ function applyUndo(hash, cwd) {
|
|
|
47019
47249
|
timeout: GIT_TIMEOUT
|
|
47020
47250
|
}).stdout?.toString().trim().split("\n").filter(Boolean) ?? [];
|
|
47021
47251
|
for (const file of [...tracked, ...untracked]) {
|
|
47022
|
-
const fullPath =
|
|
47023
|
-
if (!snapshotFiles.has(file) &&
|
|
47024
|
-
|
|
47252
|
+
const fullPath = import_path42.default.join(dir, file);
|
|
47253
|
+
if (!snapshotFiles.has(file) && import_fs44.default.existsSync(fullPath)) {
|
|
47254
|
+
import_fs44.default.unlinkSync(fullPath);
|
|
47025
47255
|
}
|
|
47026
47256
|
}
|
|
47027
47257
|
return true;
|
|
@@ -47031,12 +47261,12 @@ function applyUndo(hash, cwd) {
|
|
|
47031
47261
|
}
|
|
47032
47262
|
|
|
47033
47263
|
// src/skill-pin.ts
|
|
47034
|
-
var
|
|
47035
|
-
var
|
|
47036
|
-
var
|
|
47264
|
+
var import_fs45 = __toESM(require("fs"));
|
|
47265
|
+
var import_path43 = __toESM(require("path"));
|
|
47266
|
+
var import_os41 = __toESM(require("os"));
|
|
47037
47267
|
var import_crypto13 = __toESM(require("crypto"));
|
|
47038
47268
|
function getPinsFilePath2() {
|
|
47039
|
-
return
|
|
47269
|
+
return import_path43.default.join(import_os41.default.homedir(), ".node9", "skill-pins.json");
|
|
47040
47270
|
}
|
|
47041
47271
|
var MAX_FILES = 5e3;
|
|
47042
47272
|
var MAX_TOTAL_BYTES = 50 * 1024 * 1024;
|
|
@@ -47050,18 +47280,18 @@ function walkDir(root) {
|
|
|
47050
47280
|
if (out.length >= MAX_FILES) return;
|
|
47051
47281
|
let entries;
|
|
47052
47282
|
try {
|
|
47053
|
-
entries =
|
|
47283
|
+
entries = import_fs45.default.readdirSync(dir, { withFileTypes: true });
|
|
47054
47284
|
} catch {
|
|
47055
47285
|
return;
|
|
47056
47286
|
}
|
|
47057
47287
|
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
47058
47288
|
for (const entry of entries) {
|
|
47059
47289
|
if (out.length >= MAX_FILES) return;
|
|
47060
|
-
const full =
|
|
47061
|
-
const rel = relDir ?
|
|
47290
|
+
const full = import_path43.default.join(dir, entry.name);
|
|
47291
|
+
const rel = relDir ? import_path43.default.posix.join(relDir, entry.name) : entry.name;
|
|
47062
47292
|
let lst;
|
|
47063
47293
|
try {
|
|
47064
|
-
lst =
|
|
47294
|
+
lst = import_fs45.default.lstatSync(full);
|
|
47065
47295
|
} catch {
|
|
47066
47296
|
continue;
|
|
47067
47297
|
}
|
|
@@ -47073,7 +47303,7 @@ function walkDir(root) {
|
|
|
47073
47303
|
if (!lst.isFile()) continue;
|
|
47074
47304
|
if (totalBytes + lst.size > MAX_TOTAL_BYTES) continue;
|
|
47075
47305
|
try {
|
|
47076
|
-
const buf =
|
|
47306
|
+
const buf = import_fs45.default.readFileSync(full);
|
|
47077
47307
|
totalBytes += buf.length;
|
|
47078
47308
|
out.push({ rel, hash: sha256Bytes(buf) });
|
|
47079
47309
|
} catch {
|
|
@@ -47087,14 +47317,14 @@ function walkDir(root) {
|
|
|
47087
47317
|
function hashSkillRoot(absPath) {
|
|
47088
47318
|
let lst;
|
|
47089
47319
|
try {
|
|
47090
|
-
lst =
|
|
47320
|
+
lst = import_fs45.default.lstatSync(absPath);
|
|
47091
47321
|
} catch {
|
|
47092
47322
|
return { exists: false, contentHash: "", fileCount: 0 };
|
|
47093
47323
|
}
|
|
47094
47324
|
if (lst.isSymbolicLink()) return { exists: false, contentHash: "", fileCount: 0 };
|
|
47095
47325
|
if (lst.isFile()) {
|
|
47096
47326
|
try {
|
|
47097
|
-
return { exists: true, contentHash: sha256Bytes(
|
|
47327
|
+
return { exists: true, contentHash: sha256Bytes(import_fs45.default.readFileSync(absPath)), fileCount: 1 };
|
|
47098
47328
|
} catch {
|
|
47099
47329
|
return { exists: false, contentHash: "", fileCount: 0 };
|
|
47100
47330
|
}
|
|
@@ -47112,7 +47342,7 @@ function getRootKey(absPath) {
|
|
|
47112
47342
|
function readSkillPinsSafe() {
|
|
47113
47343
|
const filePath = getPinsFilePath2();
|
|
47114
47344
|
try {
|
|
47115
|
-
const raw =
|
|
47345
|
+
const raw = import_fs45.default.readFileSync(filePath, "utf-8");
|
|
47116
47346
|
if (!raw.trim()) return { ok: false, reason: "corrupt", detail: "empty file" };
|
|
47117
47347
|
const parsed = JSON.parse(raw);
|
|
47118
47348
|
if (!parsed.roots || typeof parsed.roots !== "object" || Array.isArray(parsed.roots)) {
|
|
@@ -47132,10 +47362,10 @@ function readSkillPins() {
|
|
|
47132
47362
|
}
|
|
47133
47363
|
function writeSkillPins(data) {
|
|
47134
47364
|
const filePath = getPinsFilePath2();
|
|
47135
|
-
|
|
47365
|
+
import_fs45.default.mkdirSync(import_path43.default.dirname(filePath), { recursive: true });
|
|
47136
47366
|
const tmp = `${filePath}.${import_crypto13.default.randomBytes(6).toString("hex")}.tmp`;
|
|
47137
|
-
|
|
47138
|
-
|
|
47367
|
+
import_fs45.default.writeFileSync(tmp, JSON.stringify(data, null, 2), { mode: 384 });
|
|
47368
|
+
import_fs45.default.renameSync(tmp, filePath);
|
|
47139
47369
|
}
|
|
47140
47370
|
function removePin2(rootKey) {
|
|
47141
47371
|
const pins = readSkillPins();
|
|
@@ -47179,36 +47409,36 @@ function verifyAndPinRoots(roots) {
|
|
|
47179
47409
|
return { kind: "verified" };
|
|
47180
47410
|
}
|
|
47181
47411
|
function defaultSkillRoots(_cwd) {
|
|
47182
|
-
const marketplaces =
|
|
47412
|
+
const marketplaces = import_path43.default.join(import_os41.default.homedir(), ".claude", "plugins", "marketplaces");
|
|
47183
47413
|
const roots = [];
|
|
47184
47414
|
let registries;
|
|
47185
47415
|
try {
|
|
47186
|
-
registries =
|
|
47416
|
+
registries = import_fs45.default.readdirSync(marketplaces, { withFileTypes: true });
|
|
47187
47417
|
} catch {
|
|
47188
47418
|
return [];
|
|
47189
47419
|
}
|
|
47190
47420
|
for (const registry of registries) {
|
|
47191
47421
|
if (!registry.isDirectory()) continue;
|
|
47192
|
-
const pluginsDir =
|
|
47422
|
+
const pluginsDir = import_path43.default.join(marketplaces, registry.name, "plugins");
|
|
47193
47423
|
let plugins;
|
|
47194
47424
|
try {
|
|
47195
|
-
plugins =
|
|
47425
|
+
plugins = import_fs45.default.readdirSync(pluginsDir, { withFileTypes: true });
|
|
47196
47426
|
} catch {
|
|
47197
47427
|
continue;
|
|
47198
47428
|
}
|
|
47199
47429
|
for (const plugin of plugins) {
|
|
47200
47430
|
if (!plugin.isDirectory()) continue;
|
|
47201
|
-
roots.push(
|
|
47431
|
+
roots.push(import_path43.default.join(pluginsDir, plugin.name));
|
|
47202
47432
|
}
|
|
47203
47433
|
}
|
|
47204
47434
|
return roots;
|
|
47205
47435
|
}
|
|
47206
47436
|
function resolveUserSkillRoot(entry, cwd) {
|
|
47207
47437
|
if (!entry) return null;
|
|
47208
|
-
if (entry.startsWith("~/") || entry === "~") return
|
|
47209
|
-
if (
|
|
47210
|
-
if (!cwd || !
|
|
47211
|
-
return
|
|
47438
|
+
if (entry.startsWith("~/") || entry === "~") return import_path43.default.join(import_os41.default.homedir(), entry.slice(1));
|
|
47439
|
+
if (import_path43.default.isAbsolute(entry)) return entry;
|
|
47440
|
+
if (!cwd || !import_path43.default.isAbsolute(cwd)) return null;
|
|
47441
|
+
return import_path43.default.join(cwd, entry);
|
|
47212
47442
|
}
|
|
47213
47443
|
|
|
47214
47444
|
// src/cli/commands/check.ts
|
|
@@ -47216,12 +47446,12 @@ init_dlp();
|
|
|
47216
47446
|
init_audit();
|
|
47217
47447
|
|
|
47218
47448
|
// src/review-pending.ts
|
|
47219
|
-
var
|
|
47220
|
-
var
|
|
47221
|
-
var
|
|
47449
|
+
var import_fs46 = __toESM(require("fs"));
|
|
47450
|
+
var import_os42 = __toESM(require("os"));
|
|
47451
|
+
var import_path44 = __toESM(require("path"));
|
|
47222
47452
|
init_hasher();
|
|
47223
47453
|
function storePath() {
|
|
47224
|
-
return process.env.NODE9_PENDING_STORE ||
|
|
47454
|
+
return process.env.NODE9_PENDING_STORE || import_path44.default.join(import_os42.default.homedir(), ".node9", "pending-reviews.json");
|
|
47225
47455
|
}
|
|
47226
47456
|
var TTL_MS2 = 6 * 60 * 60 * 1e3;
|
|
47227
47457
|
var MAX_ENTRIES = 500;
|
|
@@ -47238,7 +47468,7 @@ function reviewCorrelationKey(payload) {
|
|
|
47238
47468
|
}
|
|
47239
47469
|
function read() {
|
|
47240
47470
|
try {
|
|
47241
|
-
const parsed = JSON.parse(
|
|
47471
|
+
const parsed = JSON.parse(import_fs46.default.readFileSync(storePath(), "utf-8"));
|
|
47242
47472
|
if (parsed && Array.isArray(parsed.entries)) return parsed;
|
|
47243
47473
|
} catch {
|
|
47244
47474
|
}
|
|
@@ -47247,11 +47477,11 @@ function read() {
|
|
|
47247
47477
|
function write(store) {
|
|
47248
47478
|
try {
|
|
47249
47479
|
const p = storePath();
|
|
47250
|
-
const dir =
|
|
47251
|
-
if (!
|
|
47480
|
+
const dir = import_path44.default.dirname(p);
|
|
47481
|
+
if (!import_fs46.default.existsSync(dir)) import_fs46.default.mkdirSync(dir, { recursive: true });
|
|
47252
47482
|
const tmp = `${p}.${process.pid}.tmp`;
|
|
47253
|
-
|
|
47254
|
-
|
|
47483
|
+
import_fs46.default.writeFileSync(tmp, JSON.stringify(store));
|
|
47484
|
+
import_fs46.default.renameSync(tmp, p);
|
|
47255
47485
|
} catch {
|
|
47256
47486
|
}
|
|
47257
47487
|
}
|
|
@@ -47364,9 +47594,9 @@ function registerCheckCommand(program2) {
|
|
|
47364
47594
|
} catch (err2) {
|
|
47365
47595
|
const tempConfig = getConfig();
|
|
47366
47596
|
if (process.env.NODE9_DEBUG === "1" || tempConfig.settings.enableHookLogDebug) {
|
|
47367
|
-
const logPath =
|
|
47597
|
+
const logPath = import_path45.default.join(import_os43.default.homedir(), ".node9", "hook-debug.log");
|
|
47368
47598
|
const errMsg = err2 instanceof Error ? err2.message : String(err2);
|
|
47369
|
-
|
|
47599
|
+
import_fs47.default.appendFileSync(
|
|
47370
47600
|
logPath,
|
|
47371
47601
|
`[${(/* @__PURE__ */ new Date()).toISOString()}] JSON_PARSE_ERROR: ${errMsg}
|
|
47372
47602
|
RAW: ${raw}
|
|
@@ -47379,14 +47609,14 @@ RAW: ${raw}
|
|
|
47379
47609
|
const prompt = typeof payload.prompt === "string" ? payload.prompt : "";
|
|
47380
47610
|
if (process.env.NODE9_DEBUG === "1") {
|
|
47381
47611
|
try {
|
|
47382
|
-
const logPath =
|
|
47383
|
-
if (!
|
|
47384
|
-
|
|
47612
|
+
const logPath = import_path45.default.join(import_os43.default.homedir(), ".node9", "hook-debug.log");
|
|
47613
|
+
if (!import_fs47.default.existsSync(import_path45.default.dirname(logPath)))
|
|
47614
|
+
import_fs47.default.mkdirSync(import_path45.default.dirname(logPath), { recursive: true });
|
|
47385
47615
|
const sanitized = JSON.stringify({
|
|
47386
47616
|
...payload,
|
|
47387
47617
|
prompt: `<redacted, ${prompt.length} bytes>`
|
|
47388
47618
|
});
|
|
47389
|
-
|
|
47619
|
+
import_fs47.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] STDIN: ${sanitized}
|
|
47390
47620
|
`);
|
|
47391
47621
|
} catch {
|
|
47392
47622
|
}
|
|
@@ -47407,8 +47637,8 @@ RAW: ${raw}
|
|
|
47407
47637
|
);
|
|
47408
47638
|
const reason = `\u{1F6A8} Node9 DLP: ${dlpMatch.patternName} detected in prompt (${dlpMatch.redactedSample}). Prompt was not submitted \u2014 remove the credential and try again.`;
|
|
47409
47639
|
try {
|
|
47410
|
-
const ttyFd =
|
|
47411
|
-
|
|
47640
|
+
const ttyFd = import_fs47.default.openSync("/dev/tty", "w");
|
|
47641
|
+
import_fs47.default.writeSync(
|
|
47412
47642
|
ttyFd,
|
|
47413
47643
|
import_chalk9.default.bgRed.white.bold(`
|
|
47414
47644
|
\u{1F6A8} NODE9 DLP \u2014 PROMPT BLOCKED
|
|
@@ -47418,7 +47648,7 @@ RAW: ${raw}
|
|
|
47418
47648
|
|
|
47419
47649
|
`)
|
|
47420
47650
|
);
|
|
47421
|
-
|
|
47651
|
+
import_fs47.default.closeSync(ttyFd);
|
|
47422
47652
|
} catch {
|
|
47423
47653
|
}
|
|
47424
47654
|
const isCodex = agent2 === "Codex";
|
|
@@ -47437,16 +47667,17 @@ RAW: ${raw}
|
|
|
47437
47667
|
process.exit(2);
|
|
47438
47668
|
}
|
|
47439
47669
|
const payloadCwd = typeof payload.cwd === "string" ? payload.cwd : Array.isArray(payload.workspacePaths) && typeof payload.workspacePaths[0] === "string" ? payload.workspacePaths[0] : void 0;
|
|
47440
|
-
const safeCwdForConfig = typeof payloadCwd === "string" &&
|
|
47670
|
+
const safeCwdForConfig = typeof payloadCwd === "string" && import_path45.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
|
|
47441
47671
|
const config = getConfig(safeCwdForConfig);
|
|
47442
|
-
|
|
47672
|
+
const daemonDown = !isDaemonRunning();
|
|
47673
|
+
if (config.settings.autoStartDaemon && daemonDown && !process.env.NODE9_NO_AUTO_DAEMON) {
|
|
47443
47674
|
try {
|
|
47444
47675
|
const scriptPath = process.argv[1];
|
|
47445
|
-
if (typeof scriptPath !== "string" || !
|
|
47676
|
+
if (typeof scriptPath !== "string" || !import_path45.default.isAbsolute(scriptPath))
|
|
47446
47677
|
throw new Error("node9: argv[1] is not an absolute path");
|
|
47447
|
-
const resolvedScript =
|
|
47448
|
-
const packageDist =
|
|
47449
|
-
if (!resolvedScript.startsWith(packageDist +
|
|
47678
|
+
const resolvedScript = import_fs47.default.realpathSync(scriptPath);
|
|
47679
|
+
const packageDist = import_fs47.default.realpathSync(import_path45.default.resolve(__dirname, "../.."));
|
|
47680
|
+
if (!resolvedScript.startsWith(packageDist + import_path45.default.sep) && resolvedScript !== packageDist)
|
|
47450
47681
|
throw new Error(
|
|
47451
47682
|
`node9: daemon spawn aborted \u2014 argv[1] (${resolvedScript}) is outside package dist (${packageDist})`
|
|
47452
47683
|
);
|
|
@@ -47461,17 +47692,27 @@ RAW: ${raw}
|
|
|
47461
47692
|
]) {
|
|
47462
47693
|
delete safeEnv[key];
|
|
47463
47694
|
}
|
|
47464
|
-
const
|
|
47465
|
-
|
|
47466
|
-
|
|
47467
|
-
|
|
47468
|
-
|
|
47469
|
-
|
|
47695
|
+
const startupFd = openStartupLogFd();
|
|
47696
|
+
try {
|
|
47697
|
+
const d = (0, import_child_process7.spawn)(process.execPath, [scriptPath, "daemon"], {
|
|
47698
|
+
detached: true,
|
|
47699
|
+
stdio: ["ignore", "ignore", startupFd ?? "ignore"],
|
|
47700
|
+
env: { ...safeEnv, NODE9_AUTO_STARTED: "1" }
|
|
47701
|
+
});
|
|
47702
|
+
d.unref();
|
|
47703
|
+
} finally {
|
|
47704
|
+
if (startupFd !== void 0) {
|
|
47705
|
+
try {
|
|
47706
|
+
import_fs47.default.closeSync(startupFd);
|
|
47707
|
+
} catch {
|
|
47708
|
+
}
|
|
47709
|
+
}
|
|
47710
|
+
}
|
|
47470
47711
|
} catch (spawnErr) {
|
|
47471
|
-
const logPath =
|
|
47712
|
+
const logPath = import_path45.default.join(import_os43.default.homedir(), ".node9", "hook-debug.log");
|
|
47472
47713
|
const msg = spawnErr instanceof Error ? spawnErr.message : String(spawnErr);
|
|
47473
47714
|
try {
|
|
47474
|
-
|
|
47715
|
+
import_fs47.default.appendFileSync(
|
|
47475
47716
|
logPath,
|
|
47476
47717
|
`[${(/* @__PURE__ */ new Date()).toISOString()}] daemon-autostart-failed: ${msg}
|
|
47477
47718
|
`
|
|
@@ -47479,12 +47720,16 @@ RAW: ${raw}
|
|
|
47479
47720
|
} catch {
|
|
47480
47721
|
}
|
|
47481
47722
|
}
|
|
47723
|
+
} else if (daemonDown && !isTestingMode()) {
|
|
47724
|
+
logAutostartSkipThrottled(
|
|
47725
|
+
!config.settings.autoStartDaemon ? "autoStartDaemon=false" : process.env.NODE9_NO_AUTO_DAEMON ? "NODE9_NO_AUTO_DAEMON" : "unknown"
|
|
47726
|
+
);
|
|
47482
47727
|
}
|
|
47483
47728
|
if (process.env.NODE9_DEBUG === "1" || config.settings.enableHookLogDebug) {
|
|
47484
|
-
const logPath =
|
|
47485
|
-
if (!
|
|
47486
|
-
|
|
47487
|
-
|
|
47729
|
+
const logPath = import_path45.default.join(import_os43.default.homedir(), ".node9", "hook-debug.log");
|
|
47730
|
+
if (!import_fs47.default.existsSync(import_path45.default.dirname(logPath)))
|
|
47731
|
+
import_fs47.default.mkdirSync(import_path45.default.dirname(logPath), { recursive: true });
|
|
47732
|
+
import_fs47.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] STDIN: ${raw}
|
|
47488
47733
|
`);
|
|
47489
47734
|
}
|
|
47490
47735
|
const rawToolName = sanitize2(extractToolName(payload));
|
|
@@ -47498,8 +47743,8 @@ RAW: ${raw}
|
|
|
47498
47743
|
const isHumanDecision = blockedByContext.toLowerCase().includes("user") || blockedByContext.toLowerCase().includes("daemon") || blockedByContext.toLowerCase().includes("decision");
|
|
47499
47744
|
let ttyFd = null;
|
|
47500
47745
|
try {
|
|
47501
|
-
ttyFd =
|
|
47502
|
-
const writeTty = (line) =>
|
|
47746
|
+
ttyFd = import_fs47.default.openSync("/dev/tty", "w");
|
|
47747
|
+
const writeTty = (line) => import_fs47.default.writeSync(ttyFd, line + "\n");
|
|
47503
47748
|
if (blockedByContext.includes("DLP") || blockedByContext.includes("Secret Detected") || blockedByContext.includes("Credential Review")) {
|
|
47504
47749
|
writeTty(import_chalk9.default.bgRed.white.bold(`
|
|
47505
47750
|
\u{1F6A8} NODE9 DLP ALERT \u2014 CREDENTIAL DETECTED `));
|
|
@@ -47518,7 +47763,7 @@ RAW: ${raw}
|
|
|
47518
47763
|
} finally {
|
|
47519
47764
|
if (ttyFd !== null)
|
|
47520
47765
|
try {
|
|
47521
|
-
|
|
47766
|
+
import_fs47.default.closeSync(ttyFd);
|
|
47522
47767
|
} catch {
|
|
47523
47768
|
}
|
|
47524
47769
|
}
|
|
@@ -47575,8 +47820,8 @@ RAW: ${raw}
|
|
|
47575
47820
|
} catch {
|
|
47576
47821
|
}
|
|
47577
47822
|
try {
|
|
47578
|
-
const ttyFd =
|
|
47579
|
-
|
|
47823
|
+
const ttyFd = import_fs47.default.openSync("/dev/tty", "w");
|
|
47824
|
+
import_fs47.default.writeSync(
|
|
47580
47825
|
ttyFd,
|
|
47581
47826
|
import_chalk9.default.yellow(
|
|
47582
47827
|
`
|
|
@@ -47584,7 +47829,7 @@ RAW: ${raw}
|
|
|
47584
47829
|
`
|
|
47585
47830
|
)
|
|
47586
47831
|
);
|
|
47587
|
-
|
|
47832
|
+
import_fs47.default.closeSync(ttyFd);
|
|
47588
47833
|
} catch {
|
|
47589
47834
|
}
|
|
47590
47835
|
if (agent === "GitHub Copilot") {
|
|
@@ -47616,17 +47861,17 @@ RAW: ${raw}
|
|
|
47616
47861
|
const safeSessionId = /^[A-Za-z0-9_\-]{1,128}$/.test(rawSessionId) ? rawSessionId : "";
|
|
47617
47862
|
if (skillPinCfg.enabled && safeSessionId) {
|
|
47618
47863
|
try {
|
|
47619
|
-
const sessionsDir =
|
|
47620
|
-
const flagPath =
|
|
47864
|
+
const sessionsDir = import_path45.default.join(import_os43.default.homedir(), ".node9", "skill-sessions");
|
|
47865
|
+
const flagPath = import_path45.default.join(sessionsDir, `${safeSessionId}.json`);
|
|
47621
47866
|
let flag = null;
|
|
47622
47867
|
try {
|
|
47623
|
-
flag = JSON.parse(
|
|
47868
|
+
flag = JSON.parse(import_fs47.default.readFileSync(flagPath, "utf-8"));
|
|
47624
47869
|
} catch {
|
|
47625
47870
|
}
|
|
47626
47871
|
const writeFlag = (data2) => {
|
|
47627
47872
|
try {
|
|
47628
|
-
|
|
47629
|
-
|
|
47873
|
+
import_fs47.default.mkdirSync(sessionsDir, { recursive: true });
|
|
47874
|
+
import_fs47.default.writeFileSync(
|
|
47630
47875
|
flagPath,
|
|
47631
47876
|
JSON.stringify({ ...data2, timestamp: (/* @__PURE__ */ new Date()).toISOString() }, null, 2),
|
|
47632
47877
|
{ mode: 384 }
|
|
@@ -47637,8 +47882,8 @@ RAW: ${raw}
|
|
|
47637
47882
|
const sendSkillWarn = (detail, recoveryCmd) => {
|
|
47638
47883
|
let ttyFd = null;
|
|
47639
47884
|
try {
|
|
47640
|
-
ttyFd =
|
|
47641
|
-
const w = (line) =>
|
|
47885
|
+
ttyFd = import_fs47.default.openSync("/dev/tty", "w");
|
|
47886
|
+
const w = (line) => import_fs47.default.writeSync(ttyFd, line + "\n");
|
|
47642
47887
|
w(import_chalk9.default.yellow(`
|
|
47643
47888
|
\u26A0\uFE0F Node9: installed skill drift detected`));
|
|
47644
47889
|
w(import_chalk9.default.gray(` ${detail}`));
|
|
@@ -47653,7 +47898,7 @@ RAW: ${raw}
|
|
|
47653
47898
|
} finally {
|
|
47654
47899
|
if (ttyFd !== null)
|
|
47655
47900
|
try {
|
|
47656
|
-
|
|
47901
|
+
import_fs47.default.closeSync(ttyFd);
|
|
47657
47902
|
} catch {
|
|
47658
47903
|
}
|
|
47659
47904
|
}
|
|
@@ -47669,7 +47914,7 @@ RAW: ${raw}
|
|
|
47669
47914
|
return;
|
|
47670
47915
|
}
|
|
47671
47916
|
if (!flag || flag.state !== "verified" && flag.state !== "warned") {
|
|
47672
|
-
const absoluteCwd = typeof payloadCwd === "string" &&
|
|
47917
|
+
const absoluteCwd = typeof payloadCwd === "string" && import_path45.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
|
|
47673
47918
|
const extraRoots = skillPinCfg.roots;
|
|
47674
47919
|
const resolvedExtra = extraRoots.map((r) => resolveUserSkillRoot(r, absoluteCwd)).filter((r) => typeof r === "string");
|
|
47675
47920
|
const roots = [...defaultSkillRoots(absoluteCwd), ...resolvedExtra];
|
|
@@ -47710,10 +47955,10 @@ RAW: ${raw}
|
|
|
47710
47955
|
}
|
|
47711
47956
|
try {
|
|
47712
47957
|
const cutoff = Date.now() - 7 * 24 * 60 * 60 * 1e3;
|
|
47713
|
-
for (const name of
|
|
47714
|
-
const p =
|
|
47958
|
+
for (const name of import_fs47.default.readdirSync(sessionsDir)) {
|
|
47959
|
+
const p = import_path45.default.join(sessionsDir, name);
|
|
47715
47960
|
try {
|
|
47716
|
-
if (
|
|
47961
|
+
if (import_fs47.default.statSync(p).mtimeMs < cutoff) import_fs47.default.unlinkSync(p);
|
|
47717
47962
|
} catch {
|
|
47718
47963
|
}
|
|
47719
47964
|
}
|
|
@@ -47723,9 +47968,9 @@ RAW: ${raw}
|
|
|
47723
47968
|
} catch (err2) {
|
|
47724
47969
|
if (process.env.NODE9_DEBUG === "1") {
|
|
47725
47970
|
try {
|
|
47726
|
-
const dbg =
|
|
47971
|
+
const dbg = import_path45.default.join(import_os43.default.homedir(), ".node9", "hook-debug.log");
|
|
47727
47972
|
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
47728
|
-
|
|
47973
|
+
import_fs47.default.appendFileSync(dbg, `[${(/* @__PURE__ */ new Date()).toISOString()}] SKILL_PIN_ERROR: ${msg}
|
|
47729
47974
|
`);
|
|
47730
47975
|
} catch {
|
|
47731
47976
|
}
|
|
@@ -47735,7 +47980,7 @@ RAW: ${raw}
|
|
|
47735
47980
|
if (shouldSnapshot(toolName, toolInput, config)) {
|
|
47736
47981
|
await createShadowSnapshot(toolName, toolInput, config.policy.snapshot.ignorePaths);
|
|
47737
47982
|
}
|
|
47738
|
-
const safeCwdForAuth = typeof payloadCwd === "string" &&
|
|
47983
|
+
const safeCwdForAuth = typeof payloadCwd === "string" && import_path45.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
|
|
47739
47984
|
const askMode = resolveAskMode(agent, opts, config);
|
|
47740
47985
|
const result = await authorizeHeadless(toolName, toolInput, meta, {
|
|
47741
47986
|
cwd: safeCwdForAuth,
|
|
@@ -47753,12 +47998,12 @@ RAW: ${raw}
|
|
|
47753
47998
|
}
|
|
47754
47999
|
if (result.noApprovalMechanism && !isDaemonRunning() && !process.env.NODE9_NO_AUTO_DAEMON && !process.stdout.isTTY && config.settings.autoStartDaemon) {
|
|
47755
48000
|
try {
|
|
47756
|
-
const tty =
|
|
47757
|
-
|
|
48001
|
+
const tty = import_fs47.default.openSync("/dev/tty", "w");
|
|
48002
|
+
import_fs47.default.writeSync(
|
|
47758
48003
|
tty,
|
|
47759
48004
|
import_chalk9.default.cyan("\n\u{1F6E1}\uFE0F Node9: Starting approval daemon automatically...\n")
|
|
47760
48005
|
);
|
|
47761
|
-
|
|
48006
|
+
import_fs47.default.closeSync(tty);
|
|
47762
48007
|
} catch {
|
|
47763
48008
|
}
|
|
47764
48009
|
const daemonReady = await autoStartDaemonAndWait();
|
|
@@ -47785,9 +48030,9 @@ RAW: ${raw}
|
|
|
47785
48030
|
});
|
|
47786
48031
|
} catch (err2) {
|
|
47787
48032
|
if (process.env.NODE9_DEBUG === "1") {
|
|
47788
|
-
const logPath =
|
|
48033
|
+
const logPath = import_path45.default.join(import_os43.default.homedir(), ".node9", "hook-debug.log");
|
|
47789
48034
|
const errMsg = err2 instanceof Error ? err2.message : String(err2);
|
|
47790
|
-
|
|
48035
|
+
import_fs47.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] ERROR: ${errMsg}
|
|
47791
48036
|
`);
|
|
47792
48037
|
}
|
|
47793
48038
|
process.exit(0);
|
|
@@ -47821,9 +48066,9 @@ RAW: ${raw}
|
|
|
47821
48066
|
}
|
|
47822
48067
|
|
|
47823
48068
|
// src/cli/commands/log.ts
|
|
47824
|
-
var
|
|
47825
|
-
var
|
|
47826
|
-
var
|
|
48069
|
+
var import_fs48 = __toESM(require("fs"));
|
|
48070
|
+
var import_path46 = __toESM(require("path"));
|
|
48071
|
+
var import_os44 = __toESM(require("os"));
|
|
47827
48072
|
init_audit();
|
|
47828
48073
|
init_config();
|
|
47829
48074
|
init_daemon();
|
|
@@ -47933,10 +48178,10 @@ function registerLogCommand(program2) {
|
|
|
47933
48178
|
if (rawToolName !== tool) entry.agentToolName = rawToolName;
|
|
47934
48179
|
const payloadSessionId = payload.session_id ?? payload.conversationId;
|
|
47935
48180
|
if (payloadSessionId) entry.sessionId = payloadSessionId;
|
|
47936
|
-
const logPath =
|
|
47937
|
-
if (!
|
|
47938
|
-
|
|
47939
|
-
|
|
48181
|
+
const logPath = import_path46.default.join(import_os44.default.homedir(), ".node9", "audit.log");
|
|
48182
|
+
if (!import_fs48.default.existsSync(import_path46.default.dirname(logPath)))
|
|
48183
|
+
import_fs48.default.mkdirSync(import_path46.default.dirname(logPath), { recursive: true });
|
|
48184
|
+
import_fs48.default.appendFileSync(logPath, JSON.stringify(entry) + "\n");
|
|
47940
48185
|
if ((tool === "Bash" || tool === "bash") && isDaemonRunning()) {
|
|
47941
48186
|
const command = typeof rawInput === "object" && rawInput !== null && "command" in rawInput && typeof rawInput.command === "string" ? rawInput.command : null;
|
|
47942
48187
|
if (command) {
|
|
@@ -47970,7 +48215,7 @@ function registerLogCommand(program2) {
|
|
|
47970
48215
|
}
|
|
47971
48216
|
}
|
|
47972
48217
|
const payloadCwd = typeof payload.cwd === "string" ? payload.cwd : Array.isArray(payload.workspacePaths) && typeof payload.workspacePaths[0] === "string" ? payload.workspacePaths[0] : void 0;
|
|
47973
|
-
const safeCwd = typeof payloadCwd === "string" &&
|
|
48218
|
+
const safeCwd = typeof payloadCwd === "string" && import_path46.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
|
|
47974
48219
|
const config = getConfig(safeCwd);
|
|
47975
48220
|
{
|
|
47976
48221
|
const toolOutput = payload.tool_response?.output;
|
|
@@ -48047,9 +48292,9 @@ function registerLogCommand(program2) {
|
|
|
48047
48292
|
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
48048
48293
|
process.stderr.write(`[Node9] audit log error: ${msg}
|
|
48049
48294
|
`);
|
|
48050
|
-
const debugPath =
|
|
48295
|
+
const debugPath = import_path46.default.join(import_os44.default.homedir(), ".node9", "hook-debug.log");
|
|
48051
48296
|
try {
|
|
48052
|
-
|
|
48297
|
+
import_fs48.default.appendFileSync(debugPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] LOG_ERROR: ${msg}
|
|
48053
48298
|
`);
|
|
48054
48299
|
} catch {
|
|
48055
48300
|
}
|
|
@@ -48074,15 +48319,15 @@ function registerLogCommand(program2) {
|
|
|
48074
48319
|
|
|
48075
48320
|
// src/cli/commands/shield.ts
|
|
48076
48321
|
var import_chalk10 = __toESM(require("chalk"));
|
|
48077
|
-
var
|
|
48078
|
-
var
|
|
48079
|
-
var
|
|
48322
|
+
var import_fs50 = __toESM(require("fs"));
|
|
48323
|
+
var import_path48 = __toESM(require("path"));
|
|
48324
|
+
var import_os45 = __toESM(require("os"));
|
|
48080
48325
|
init_shields();
|
|
48081
48326
|
init_build();
|
|
48082
48327
|
|
|
48083
48328
|
// src/shields/create.ts
|
|
48084
|
-
var
|
|
48085
|
-
var
|
|
48329
|
+
var import_fs49 = __toESM(require("fs"));
|
|
48330
|
+
var import_path47 = __toESM(require("path"));
|
|
48086
48331
|
init_dist();
|
|
48087
48332
|
init_shields();
|
|
48088
48333
|
init_audit();
|
|
@@ -48102,8 +48347,8 @@ function createShield(def, opts = {}) {
|
|
|
48102
48347
|
error: `"${name}" is a built-in shield \u2014 choose a different name (a user shield with this name would shadow the built-in).`
|
|
48103
48348
|
};
|
|
48104
48349
|
}
|
|
48105
|
-
const filePath =
|
|
48106
|
-
if (!opts.overwrite &&
|
|
48350
|
+
const filePath = import_path47.default.join(USER_SHIELDS_DIR_PATH, `${name}.json`);
|
|
48351
|
+
if (!opts.overwrite && import_fs49.default.existsSync(filePath)) {
|
|
48107
48352
|
return {
|
|
48108
48353
|
ok: false,
|
|
48109
48354
|
error: `Shield "${name}" already exists at ${filePath}. Pass --overwrite to replace it.`
|
|
@@ -48168,8 +48413,8 @@ var COMMUNITY_INDEX_URL = "https://raw.githubusercontent.com/node9ai/node9-proxy
|
|
|
48168
48413
|
function readCloudShields() {
|
|
48169
48414
|
const out = /* @__PURE__ */ new Set();
|
|
48170
48415
|
try {
|
|
48171
|
-
const file =
|
|
48172
|
-
const raw = JSON.parse(
|
|
48416
|
+
const file = import_path48.default.join(import_os45.default.homedir(), ".node9", "rules-cache.json");
|
|
48417
|
+
const raw = JSON.parse(import_fs50.default.readFileSync(file, "utf-8"));
|
|
48173
48418
|
for (const r of raw.rules ?? []) {
|
|
48174
48419
|
const rule = r;
|
|
48175
48420
|
const fromSource = rule.source?.startsWith("SHIELD:") ? rule.source.slice("SHIELD:".length).toLowerCase() : void 0;
|
|
@@ -48486,7 +48731,7 @@ function registerShieldCommand(program2) {
|
|
|
48486
48731
|
if (opts.fromFile) {
|
|
48487
48732
|
let raw;
|
|
48488
48733
|
try {
|
|
48489
|
-
raw = JSON.parse(
|
|
48734
|
+
raw = JSON.parse(import_fs50.default.readFileSync(opts.fromFile, "utf-8"));
|
|
48490
48735
|
} catch (err2) {
|
|
48491
48736
|
console.error(
|
|
48492
48737
|
import_chalk10.default.red(`
|
|
@@ -48606,16 +48851,33 @@ function registerConfigShowCommand(program2) {
|
|
|
48606
48851
|
|
|
48607
48852
|
// src/cli/commands/doctor.ts
|
|
48608
48853
|
var import_chalk11 = __toESM(require("chalk"));
|
|
48609
|
-
var
|
|
48610
|
-
var
|
|
48611
|
-
var
|
|
48854
|
+
var import_fs51 = __toESM(require("fs"));
|
|
48855
|
+
var import_path49 = __toESM(require("path"));
|
|
48856
|
+
var import_os46 = __toESM(require("os"));
|
|
48612
48857
|
var import_child_process8 = require("child_process");
|
|
48613
48858
|
init_daemon();
|
|
48614
48859
|
init_config();
|
|
48615
48860
|
init_agent_wiring();
|
|
48861
|
+
init_sync();
|
|
48862
|
+
init_service();
|
|
48863
|
+
|
|
48864
|
+
// src/lib/relative-time.ts
|
|
48865
|
+
function agoLabel(iso, now = Date.now()) {
|
|
48866
|
+
const ms = now - new Date(iso).getTime();
|
|
48867
|
+
if (!Number.isFinite(ms) || ms < 0) return "just now";
|
|
48868
|
+
const min = Math.floor(ms / 6e4);
|
|
48869
|
+
if (min < 1) return "just now";
|
|
48870
|
+
if (min < 60) return `${min} min ago`;
|
|
48871
|
+
const hr = Math.floor(min / 60);
|
|
48872
|
+
if (hr < 24) return `${hr} hour${hr === 1 ? "" : "s"} ago`;
|
|
48873
|
+
const d = Math.floor(hr / 24);
|
|
48874
|
+
return `${d} day${d === 1 ? "" : "s"} ago`;
|
|
48875
|
+
}
|
|
48876
|
+
|
|
48877
|
+
// src/cli/commands/doctor.ts
|
|
48616
48878
|
function registerDoctorCommand(program2, version2) {
|
|
48617
48879
|
program2.command("doctor").description("Check that Node9 is installed and configured correctly").action(async () => {
|
|
48618
|
-
const homeDir2 =
|
|
48880
|
+
const homeDir2 = import_os46.default.homedir();
|
|
48619
48881
|
let failures = 0;
|
|
48620
48882
|
function pass(msg) {
|
|
48621
48883
|
console.log(import_chalk11.default.green(" \u2705 ") + msg);
|
|
@@ -48661,10 +48923,10 @@ function registerDoctorCommand(program2, version2) {
|
|
|
48661
48923
|
);
|
|
48662
48924
|
}
|
|
48663
48925
|
section("Configuration");
|
|
48664
|
-
const globalConfigPath =
|
|
48665
|
-
if (
|
|
48926
|
+
const globalConfigPath = import_path49.default.join(homeDir2, ".node9", "config.json");
|
|
48927
|
+
if (import_fs51.default.existsSync(globalConfigPath)) {
|
|
48666
48928
|
try {
|
|
48667
|
-
JSON.parse(
|
|
48929
|
+
JSON.parse(import_fs51.default.readFileSync(globalConfigPath, "utf-8"));
|
|
48668
48930
|
pass("~/.node9/config.json found and valid");
|
|
48669
48931
|
} catch {
|
|
48670
48932
|
fail("~/.node9/config.json is invalid JSON", "Run: node9 init --force");
|
|
@@ -48672,10 +48934,10 @@ function registerDoctorCommand(program2, version2) {
|
|
|
48672
48934
|
} else {
|
|
48673
48935
|
warn("~/.node9/config.json not found (using defaults)", "Run: node9 init");
|
|
48674
48936
|
}
|
|
48675
|
-
const projectConfigPath =
|
|
48676
|
-
if (
|
|
48937
|
+
const projectConfigPath = import_path49.default.join(process.cwd(), "node9.config.json");
|
|
48938
|
+
if (import_fs51.default.existsSync(projectConfigPath)) {
|
|
48677
48939
|
try {
|
|
48678
|
-
JSON.parse(
|
|
48940
|
+
JSON.parse(import_fs51.default.readFileSync(projectConfigPath, "utf-8"));
|
|
48679
48941
|
pass("node9.config.json found and valid (project)");
|
|
48680
48942
|
} catch {
|
|
48681
48943
|
fail(
|
|
@@ -48684,8 +48946,8 @@ function registerDoctorCommand(program2, version2) {
|
|
|
48684
48946
|
);
|
|
48685
48947
|
}
|
|
48686
48948
|
}
|
|
48687
|
-
const credsPath =
|
|
48688
|
-
if (
|
|
48949
|
+
const credsPath = import_path49.default.join(homeDir2, ".node9", "credentials.json");
|
|
48950
|
+
if (import_fs51.default.existsSync(credsPath)) {
|
|
48689
48951
|
pass("Cloud credentials found (~/.node9/credentials.json)");
|
|
48690
48952
|
} else {
|
|
48691
48953
|
warn(
|
|
@@ -48725,11 +48987,31 @@ function registerDoctorCommand(program2, version2) {
|
|
|
48725
48987
|
"Run: node9 daemon --background"
|
|
48726
48988
|
);
|
|
48727
48989
|
}
|
|
48990
|
+
const autostart = autostartAdvice({
|
|
48991
|
+
installed: isDaemonServiceInstalled(),
|
|
48992
|
+
enabled: isDaemonServiceEnabled(),
|
|
48993
|
+
cloudEnabled: !!getConfig().settings.approvers?.cloud
|
|
48994
|
+
});
|
|
48995
|
+
if (autostart) warn(autostart.message, autostart.hint);
|
|
48996
|
+
if (import_fs51.default.existsSync(import_path49.default.join(import_os46.default.homedir(), ".node9", "credentials.json")) && getConfig().settings.approvers?.cloud) {
|
|
48997
|
+
section("Policy sync");
|
|
48998
|
+
const health = readSyncHealth();
|
|
48999
|
+
if (isPolicyStale(Date.now(), health)) {
|
|
49000
|
+
const when = health.lastCheckedAt ? `last reached the cloud ${agoLabel(health.lastCheckedAt)}` : "never reached the cloud";
|
|
49001
|
+
const fails = health.consecutiveFailures > 0 ? ` (${health.consecutiveFailures} consecutive failure${health.consecutiveFailures === 1 ? "" : "s"}${health.lastError ? `: ${health.lastError}` : ""})` : "";
|
|
49002
|
+
warn(
|
|
49003
|
+
`Cloud policy is STALE \u2014 ${when}${fails}. The cached policy is still enforced, but changes from the dashboard are not reaching this machine.`,
|
|
49004
|
+
"Run: node9 policy sync (and ensure the daemon autostarts: systemctl --user enable --now node9-daemon)"
|
|
49005
|
+
);
|
|
49006
|
+
} else if (health.lastCheckedAt) {
|
|
49007
|
+
pass(`Cloud policy fresh \u2014 last synced ${agoLabel(health.lastCheckedAt)}`);
|
|
49008
|
+
}
|
|
49009
|
+
}
|
|
48728
49010
|
section("Cloud audit shipping");
|
|
48729
49011
|
try {
|
|
48730
49012
|
const { shipLagBytes: shipLagBytes2, readWatermark: readWatermark2, AUDIT_SHIP_WATERMARK: AUDIT_SHIP_WATERMARK2 } = await Promise.resolve().then(() => (init_audit_shipper(), audit_shipper_exports));
|
|
48731
49013
|
const cfg = getConfig();
|
|
48732
|
-
const creds =
|
|
49014
|
+
const creds = import_fs51.default.existsSync(import_path49.default.join(import_os46.default.homedir(), ".node9", "credentials.json"));
|
|
48733
49015
|
if (!creds) {
|
|
48734
49016
|
warn("Not logged in \u2014 audit rows stay local", "Run: node9 login <api-key>");
|
|
48735
49017
|
} else if (!cfg.settings.approvers.cloud) {
|
|
@@ -48779,9 +49061,9 @@ function registerDoctorCommand(program2, version2) {
|
|
|
48779
49061
|
|
|
48780
49062
|
// src/cli/commands/audit.ts
|
|
48781
49063
|
var import_chalk12 = __toESM(require("chalk"));
|
|
48782
|
-
var
|
|
48783
|
-
var
|
|
48784
|
-
var
|
|
49064
|
+
var import_fs52 = __toESM(require("fs"));
|
|
49065
|
+
var import_path50 = __toESM(require("path"));
|
|
49066
|
+
var import_os47 = __toESM(require("os"));
|
|
48785
49067
|
function formatRelativeTime(timestamp) {
|
|
48786
49068
|
const diff = Date.now() - new Date(timestamp).getTime();
|
|
48787
49069
|
const sec = Math.floor(diff / 1e3);
|
|
@@ -48794,14 +49076,14 @@ function formatRelativeTime(timestamp) {
|
|
|
48794
49076
|
}
|
|
48795
49077
|
function registerAuditCommand(program2) {
|
|
48796
49078
|
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) => {
|
|
48797
|
-
const logPath =
|
|
48798
|
-
if (!
|
|
49079
|
+
const logPath = import_path50.default.join(import_os47.default.homedir(), ".node9", "audit.log");
|
|
49080
|
+
if (!import_fs52.default.existsSync(logPath)) {
|
|
48799
49081
|
console.log(
|
|
48800
49082
|
import_chalk12.default.yellow("No audit logs found. Run node9 with an agent to generate entries.")
|
|
48801
49083
|
);
|
|
48802
49084
|
return;
|
|
48803
49085
|
}
|
|
48804
|
-
const raw =
|
|
49086
|
+
const raw = import_fs52.default.readFileSync(logPath, "utf-8");
|
|
48805
49087
|
const lines = raw.split("\n").filter((l) => l.trim() !== "");
|
|
48806
49088
|
let entries = lines.flatMap((line) => {
|
|
48807
49089
|
try {
|
|
@@ -48857,9 +49139,9 @@ function registerAuditCommand(program2) {
|
|
|
48857
49139
|
var import_chalk13 = __toESM(require("chalk"));
|
|
48858
49140
|
|
|
48859
49141
|
// src/cli/aggregate/report-audit.ts
|
|
48860
|
-
var
|
|
48861
|
-
var
|
|
48862
|
-
var
|
|
49142
|
+
var import_fs53 = __toESM(require("fs"));
|
|
49143
|
+
var import_os48 = __toESM(require("os"));
|
|
49144
|
+
var import_path51 = __toESM(require("path"));
|
|
48863
49145
|
init_costSync();
|
|
48864
49146
|
init_litellm();
|
|
48865
49147
|
init_cost_codex();
|
|
@@ -48942,8 +49224,8 @@ function getDateRange(period, now) {
|
|
|
48942
49224
|
}
|
|
48943
49225
|
}
|
|
48944
49226
|
function parseAuditLog(logPath) {
|
|
48945
|
-
if (!
|
|
48946
|
-
const raw =
|
|
49227
|
+
if (!import_fs53.default.existsSync(logPath)) return [];
|
|
49228
|
+
const raw = import_fs53.default.readFileSync(logPath, "utf-8");
|
|
48947
49229
|
return raw.split("\n").flatMap((line) => {
|
|
48948
49230
|
if (!line.trim()) return [];
|
|
48949
49231
|
try {
|
|
@@ -48990,25 +49272,25 @@ function freezeClaudeCost(acc) {
|
|
|
48990
49272
|
};
|
|
48991
49273
|
}
|
|
48992
49274
|
function processClaudeCostProject(proj, projectsDir, start, end, acc) {
|
|
48993
|
-
const projPath =
|
|
49275
|
+
const projPath = import_path51.default.join(projectsDir, proj);
|
|
48994
49276
|
let files;
|
|
48995
49277
|
try {
|
|
48996
|
-
const stat =
|
|
49278
|
+
const stat = import_fs53.default.statSync(projPath);
|
|
48997
49279
|
if (!stat.isDirectory()) return;
|
|
48998
|
-
files =
|
|
49280
|
+
files = import_fs53.default.readdirSync(projPath).filter((f) => f.endsWith(".jsonl") && !f.startsWith("agent-"));
|
|
48999
49281
|
} catch {
|
|
49000
49282
|
return;
|
|
49001
49283
|
}
|
|
49002
49284
|
const startMs = start.getTime();
|
|
49003
49285
|
for (const file of files) {
|
|
49004
|
-
const filePath =
|
|
49286
|
+
const filePath = import_path51.default.join(projPath, file);
|
|
49005
49287
|
try {
|
|
49006
|
-
if (
|
|
49288
|
+
if (import_fs53.default.statSync(filePath).mtimeMs < startMs) continue;
|
|
49007
49289
|
} catch {
|
|
49008
49290
|
continue;
|
|
49009
49291
|
}
|
|
49010
49292
|
try {
|
|
49011
|
-
const raw =
|
|
49293
|
+
const raw = import_fs53.default.readFileSync(filePath, "utf-8");
|
|
49012
49294
|
for (const line of raw.split("\n")) {
|
|
49013
49295
|
if (!line.trim()) continue;
|
|
49014
49296
|
let entry;
|
|
@@ -49058,10 +49340,10 @@ function processClaudeCostProject(proj, projectsDir, start, end, acc) {
|
|
|
49058
49340
|
}
|
|
49059
49341
|
function loadClaudeCost(start, end, projectsDir) {
|
|
49060
49342
|
const acc = emptyClaudeCostAccumulator();
|
|
49061
|
-
if (!
|
|
49343
|
+
if (!import_fs53.default.existsSync(projectsDir)) return freezeClaudeCost(acc);
|
|
49062
49344
|
let dirs;
|
|
49063
49345
|
try {
|
|
49064
|
-
dirs =
|
|
49346
|
+
dirs = import_fs53.default.readdirSync(projectsDir);
|
|
49065
49347
|
} catch {
|
|
49066
49348
|
return freezeClaudeCost(acc);
|
|
49067
49349
|
}
|
|
@@ -49073,7 +49355,7 @@ function loadClaudeCost(start, end, projectsDir) {
|
|
|
49073
49355
|
function processCodexCostFile(filePath, start, end, acc) {
|
|
49074
49356
|
let lines;
|
|
49075
49357
|
try {
|
|
49076
|
-
lines =
|
|
49358
|
+
lines = import_fs53.default.readFileSync(filePath, "utf-8").split("\n");
|
|
49077
49359
|
} catch {
|
|
49078
49360
|
return;
|
|
49079
49361
|
}
|
|
@@ -49128,31 +49410,31 @@ function processCodexCostFile(filePath, start, end, acc) {
|
|
|
49128
49410
|
}
|
|
49129
49411
|
function listCodexSessionFiles2(sessionsBase) {
|
|
49130
49412
|
const jsonlFiles = [];
|
|
49131
|
-
if (!
|
|
49413
|
+
if (!import_fs53.default.existsSync(sessionsBase)) return jsonlFiles;
|
|
49132
49414
|
try {
|
|
49133
|
-
for (const year of
|
|
49134
|
-
const yearPath =
|
|
49415
|
+
for (const year of import_fs53.default.readdirSync(sessionsBase)) {
|
|
49416
|
+
const yearPath = import_path51.default.join(sessionsBase, year);
|
|
49135
49417
|
try {
|
|
49136
|
-
if (!
|
|
49418
|
+
if (!import_fs53.default.statSync(yearPath).isDirectory()) continue;
|
|
49137
49419
|
} catch {
|
|
49138
49420
|
continue;
|
|
49139
49421
|
}
|
|
49140
|
-
for (const month of
|
|
49141
|
-
const monthPath =
|
|
49422
|
+
for (const month of import_fs53.default.readdirSync(yearPath)) {
|
|
49423
|
+
const monthPath = import_path51.default.join(yearPath, month);
|
|
49142
49424
|
try {
|
|
49143
|
-
if (!
|
|
49425
|
+
if (!import_fs53.default.statSync(monthPath).isDirectory()) continue;
|
|
49144
49426
|
} catch {
|
|
49145
49427
|
continue;
|
|
49146
49428
|
}
|
|
49147
|
-
for (const day of
|
|
49148
|
-
const dayPath =
|
|
49429
|
+
for (const day of import_fs53.default.readdirSync(monthPath)) {
|
|
49430
|
+
const dayPath = import_path51.default.join(monthPath, day);
|
|
49149
49431
|
try {
|
|
49150
|
-
if (!
|
|
49432
|
+
if (!import_fs53.default.statSync(dayPath).isDirectory()) continue;
|
|
49151
49433
|
} catch {
|
|
49152
49434
|
continue;
|
|
49153
49435
|
}
|
|
49154
|
-
for (const file of
|
|
49155
|
-
if (file.endsWith(".jsonl")) jsonlFiles.push(
|
|
49436
|
+
for (const file of import_fs53.default.readdirSync(dayPath)) {
|
|
49437
|
+
if (file.endsWith(".jsonl")) jsonlFiles.push(import_path51.default.join(dayPath, file));
|
|
49156
49438
|
}
|
|
49157
49439
|
}
|
|
49158
49440
|
}
|
|
@@ -49217,13 +49499,13 @@ function freezeGeminiCost(acc) {
|
|
|
49217
49499
|
function processGeminiCostFile(filePath, projectKey, start, end, acc) {
|
|
49218
49500
|
const startMs = start.getTime();
|
|
49219
49501
|
try {
|
|
49220
|
-
if (
|
|
49502
|
+
if (import_fs53.default.statSync(filePath).mtimeMs < startMs) return;
|
|
49221
49503
|
} catch {
|
|
49222
49504
|
return;
|
|
49223
49505
|
}
|
|
49224
49506
|
let raw;
|
|
49225
49507
|
try {
|
|
49226
|
-
raw =
|
|
49508
|
+
raw = import_fs53.default.readFileSync(filePath, "utf-8");
|
|
49227
49509
|
} catch {
|
|
49228
49510
|
return;
|
|
49229
49511
|
}
|
|
@@ -49272,30 +49554,30 @@ function listGeminiSessionFiles2(geminiTmpDir2) {
|
|
|
49272
49554
|
const out = [];
|
|
49273
49555
|
let dirs;
|
|
49274
49556
|
try {
|
|
49275
|
-
if (!
|
|
49276
|
-
dirs =
|
|
49557
|
+
if (!import_fs53.default.statSync(geminiTmpDir2).isDirectory()) return out;
|
|
49558
|
+
dirs = import_fs53.default.readdirSync(geminiTmpDir2);
|
|
49277
49559
|
} catch {
|
|
49278
49560
|
return out;
|
|
49279
49561
|
}
|
|
49280
49562
|
for (const proj of dirs) {
|
|
49281
|
-
const chatsDir =
|
|
49563
|
+
const chatsDir = import_path51.default.join(geminiTmpDir2, proj, "chats");
|
|
49282
49564
|
let files;
|
|
49283
49565
|
try {
|
|
49284
|
-
if (!
|
|
49285
|
-
files =
|
|
49566
|
+
if (!import_fs53.default.statSync(chatsDir).isDirectory()) continue;
|
|
49567
|
+
files = import_fs53.default.readdirSync(chatsDir);
|
|
49286
49568
|
} catch {
|
|
49287
49569
|
continue;
|
|
49288
49570
|
}
|
|
49289
49571
|
for (const f of files) {
|
|
49290
49572
|
if (!f.endsWith(".jsonl")) continue;
|
|
49291
|
-
out.push({ projectKey: proj, file:
|
|
49573
|
+
out.push({ projectKey: proj, file: import_path51.default.join(chatsDir, f) });
|
|
49292
49574
|
}
|
|
49293
49575
|
}
|
|
49294
49576
|
return out;
|
|
49295
49577
|
}
|
|
49296
49578
|
function loadGeminiCost(start, end, geminiTmpDir2) {
|
|
49297
49579
|
const acc = emptyGeminiAccumulator();
|
|
49298
|
-
if (!
|
|
49580
|
+
if (!import_fs53.default.existsSync(geminiTmpDir2)) return freezeGeminiCost(acc);
|
|
49299
49581
|
for (const { projectKey, file } of listGeminiSessionFiles2(geminiTmpDir2)) {
|
|
49300
49582
|
processGeminiCostFile(file, projectKey, start, end, acc);
|
|
49301
49583
|
}
|
|
@@ -49313,11 +49595,11 @@ function dimensionOfBlock(checkedBy, ruleName) {
|
|
|
49313
49595
|
}
|
|
49314
49596
|
function aggregateReportFromAudit(period, opts = {}) {
|
|
49315
49597
|
const now = opts.now ?? /* @__PURE__ */ new Date();
|
|
49316
|
-
const auditLogPath = opts.auditLogPath ??
|
|
49317
|
-
const claudeProjectsDir = opts.claudeProjectsDir ??
|
|
49318
|
-
const codexSessionsDir2 = opts.codexSessionsDir ??
|
|
49319
|
-
const geminiTmpDir2 = opts.geminiTmpDir ??
|
|
49320
|
-
const hasAuditFile =
|
|
49598
|
+
const auditLogPath = opts.auditLogPath ?? import_path51.default.join(import_os48.default.homedir(), ".node9", "audit.log");
|
|
49599
|
+
const claudeProjectsDir = opts.claudeProjectsDir ?? import_path51.default.join(import_os48.default.homedir(), ".claude", "projects");
|
|
49600
|
+
const codexSessionsDir2 = opts.codexSessionsDir ?? import_path51.default.join(import_os48.default.homedir(), ".codex", "sessions");
|
|
49601
|
+
const geminiTmpDir2 = opts.geminiTmpDir ?? import_path51.default.join(import_os48.default.homedir(), ".gemini", "tmp");
|
|
49602
|
+
const hasAuditFile = import_fs53.default.existsSync(auditLogPath);
|
|
49321
49603
|
const allEntries = opts.preloadedAuditEntries ?? parseAuditLog(auditLogPath);
|
|
49322
49604
|
const unackedDlp = allEntries.filter((e) => e.source === "response-dlp");
|
|
49323
49605
|
const { start, end } = getDateRange(period, now);
|
|
@@ -50108,12 +50390,14 @@ function registerDaemonCommand(program2) {
|
|
|
50108
50390
|
|
|
50109
50391
|
// src/cli/commands/status.ts
|
|
50110
50392
|
var import_chalk15 = __toESM(require("chalk"));
|
|
50111
|
-
var
|
|
50112
|
-
var
|
|
50113
|
-
var
|
|
50393
|
+
var import_fs54 = __toESM(require("fs"));
|
|
50394
|
+
var import_path52 = __toESM(require("path"));
|
|
50395
|
+
var import_os49 = __toESM(require("os"));
|
|
50114
50396
|
init_core();
|
|
50115
50397
|
init_daemon();
|
|
50116
50398
|
init_agent_wiring();
|
|
50399
|
+
init_sync();
|
|
50400
|
+
init_service();
|
|
50117
50401
|
function printAgentSection(label2, hookPairs, wrapped) {
|
|
50118
50402
|
console.log(import_chalk15.default.bold(` ${label2}`));
|
|
50119
50403
|
for (const { name, present } of hookPairs) {
|
|
@@ -50142,6 +50426,15 @@ function registerStatusCommand(program2) {
|
|
|
50142
50426
|
console.log("");
|
|
50143
50427
|
if (creds && settings.approvers.cloud) {
|
|
50144
50428
|
console.log(import_chalk15.default.green(" \u25CF Agent mode") + import_chalk15.default.gray(" \u2014 cloud team policy enforced"));
|
|
50429
|
+
const health = readSyncHealth();
|
|
50430
|
+
if (isPolicyStale(Date.now(), health)) {
|
|
50431
|
+
const when = health.lastCheckedAt ? `last synced ${agoLabel(health.lastCheckedAt)}` : "never synced";
|
|
50432
|
+
const fails = health.consecutiveFailures > 0 ? ` \xB7 ${health.consecutiveFailures} failed attempt${health.consecutiveFailures === 1 ? "" : "s"}${health.lastError ? ` (${health.lastError})` : ""}` : "";
|
|
50433
|
+
console.log(import_chalk15.default.yellow(" \u26A0 Policy sync STALE") + import_chalk15.default.gray(` \u2014 ${when}${fails}`));
|
|
50434
|
+
console.log(import_chalk15.default.gray(" the cached policy is still enforced \u2014 run: node9 doctor"));
|
|
50435
|
+
} else if (health.lastCheckedAt) {
|
|
50436
|
+
console.log(import_chalk15.default.gray(` \u21B3 policy synced ${agoLabel(health.lastCheckedAt)}`));
|
|
50437
|
+
}
|
|
50145
50438
|
} else if (creds && !settings.approvers.cloud) {
|
|
50146
50439
|
console.log(
|
|
50147
50440
|
import_chalk15.default.blue(" \u25CF Privacy mode \u{1F6E1}\uFE0F") + import_chalk15.default.gray(" \u2014 all decisions stay on this machine")
|
|
@@ -50159,6 +50452,16 @@ function registerStatusCommand(program2) {
|
|
|
50159
50452
|
} else {
|
|
50160
50453
|
console.log(import_chalk15.default.gray(" \u25CB Daemon stopped"));
|
|
50161
50454
|
}
|
|
50455
|
+
const autostart = autostartAdvice({
|
|
50456
|
+
installed: isDaemonServiceInstalled(),
|
|
50457
|
+
enabled: isDaemonServiceEnabled(),
|
|
50458
|
+
cloudEnabled: !!(creds && settings.approvers.cloud)
|
|
50459
|
+
});
|
|
50460
|
+
if (autostart) {
|
|
50461
|
+
console.log(
|
|
50462
|
+
import_chalk15.default.yellow(" \u26A0 daemon autostart not active") + import_chalk15.default.gray(" \u2014 won't survive reboot; run: node9 doctor")
|
|
50463
|
+
);
|
|
50464
|
+
}
|
|
50162
50465
|
if (settings.enableUndo) {
|
|
50163
50466
|
console.log(
|
|
50164
50467
|
import_chalk15.default.magenta(" \u25CF Undo Engine") + import_chalk15.default.gray(` \u2192 Auto-snapshotting Git repos on AI change`)
|
|
@@ -50167,20 +50470,20 @@ function registerStatusCommand(program2) {
|
|
|
50167
50470
|
console.log("");
|
|
50168
50471
|
const modeLabel = settings.mode === "audit" ? import_chalk15.default.blue("audit") : settings.mode === "strict" ? import_chalk15.default.red("strict") : import_chalk15.default.white("standard");
|
|
50169
50472
|
console.log(` Mode: ${modeLabel}`);
|
|
50170
|
-
const projectConfig =
|
|
50171
|
-
const globalConfig =
|
|
50473
|
+
const projectConfig = import_path52.default.join(process.cwd(), "node9.config.json");
|
|
50474
|
+
const globalConfig = import_path52.default.join(import_os49.default.homedir(), ".node9", "config.json");
|
|
50172
50475
|
console.log(
|
|
50173
|
-
` Local: ${
|
|
50476
|
+
` Local: ${import_fs54.default.existsSync(projectConfig) ? import_chalk15.default.green("Active (node9.config.json)") : import_chalk15.default.gray("Not present")}`
|
|
50174
50477
|
);
|
|
50175
50478
|
console.log(
|
|
50176
|
-
` Global: ${
|
|
50479
|
+
` Global: ${import_fs54.default.existsSync(globalConfig) ? import_chalk15.default.green("Active (~/.node9/config.json)") : import_chalk15.default.gray("Not present")}`
|
|
50177
50480
|
);
|
|
50178
50481
|
if (mergedConfig.policy.sandboxPaths.length > 0) {
|
|
50179
50482
|
console.log(
|
|
50180
50483
|
` Sandbox: ${import_chalk15.default.green(`${mergedConfig.policy.sandboxPaths.length} safe zones active`)}`
|
|
50181
50484
|
);
|
|
50182
50485
|
}
|
|
50183
|
-
const wiring = getAgentWiring(
|
|
50486
|
+
const wiring = getAgentWiring(import_os49.default.homedir()).filter((a) => a.present);
|
|
50184
50487
|
if (wiring.length > 0) {
|
|
50185
50488
|
console.log("");
|
|
50186
50489
|
console.log(import_chalk15.default.bold(" Agent Wiring:"));
|
|
@@ -50215,14 +50518,15 @@ function registerStatusCommand(program2) {
|
|
|
50215
50518
|
|
|
50216
50519
|
// src/cli/commands/init.ts
|
|
50217
50520
|
var import_chalk16 = __toESM(require("chalk"));
|
|
50218
|
-
var
|
|
50219
|
-
var
|
|
50220
|
-
var
|
|
50521
|
+
var import_fs55 = __toESM(require("fs"));
|
|
50522
|
+
var import_path53 = __toESM(require("path"));
|
|
50523
|
+
var import_os50 = __toESM(require("os"));
|
|
50221
50524
|
var import_https6 = __toESM(require("https"));
|
|
50222
50525
|
init_core();
|
|
50223
50526
|
init_setup();
|
|
50224
50527
|
init_shields();
|
|
50225
50528
|
init_service();
|
|
50529
|
+
init_core();
|
|
50226
50530
|
var DEFAULT_SHIELDS = ["bash-safe", "filesystem", "project-jail"];
|
|
50227
50531
|
function buildTelemetryPayload(agents, firstInstall) {
|
|
50228
50532
|
return {
|
|
@@ -50307,16 +50611,16 @@ function registerInitCommand(program2) {
|
|
|
50307
50611
|
}
|
|
50308
50612
|
console.log("");
|
|
50309
50613
|
}
|
|
50310
|
-
const configPath =
|
|
50311
|
-
const isFirstInstall = !
|
|
50312
|
-
if (
|
|
50614
|
+
const configPath = import_path53.default.join(import_os50.default.homedir(), ".node9", "config.json");
|
|
50615
|
+
const isFirstInstall = !import_fs55.default.existsSync(configPath);
|
|
50616
|
+
if (import_fs55.default.existsSync(configPath) && !options.force) {
|
|
50313
50617
|
try {
|
|
50314
|
-
const existing = JSON.parse(
|
|
50618
|
+
const existing = JSON.parse(import_fs55.default.readFileSync(configPath, "utf-8"));
|
|
50315
50619
|
const settings = existing.settings ?? {};
|
|
50316
50620
|
if (settings.mode !== chosenMode) {
|
|
50317
50621
|
settings.mode = chosenMode;
|
|
50318
50622
|
existing.settings = settings;
|
|
50319
|
-
|
|
50623
|
+
import_fs55.default.writeFileSync(configPath, JSON.stringify(existing, null, 2) + "\n");
|
|
50320
50624
|
console.log(import_chalk16.default.green(`\u2705 Mode updated: ${chosenMode}`));
|
|
50321
50625
|
} else {
|
|
50322
50626
|
console.log(import_chalk16.default.blue(`\u2139\uFE0F Config already exists: ${configPath}`));
|
|
@@ -50329,9 +50633,9 @@ function registerInitCommand(program2) {
|
|
|
50329
50633
|
...DEFAULT_CONFIG,
|
|
50330
50634
|
settings: { ...DEFAULT_CONFIG.settings, mode: chosenMode }
|
|
50331
50635
|
};
|
|
50332
|
-
const dir =
|
|
50333
|
-
if (!
|
|
50334
|
-
|
|
50636
|
+
const dir = import_path53.default.dirname(configPath);
|
|
50637
|
+
if (!import_fs55.default.existsSync(dir)) import_fs55.default.mkdirSync(dir, { recursive: true });
|
|
50638
|
+
import_fs55.default.writeFileSync(configPath, JSON.stringify(configToSave, null, 2) + "\n");
|
|
50335
50639
|
console.log(import_chalk16.default.green(`\u2705 Config created: ${configPath}`));
|
|
50336
50640
|
console.log(import_chalk16.default.gray(` Mode: ${chosenMode}`));
|
|
50337
50641
|
}
|
|
@@ -50383,8 +50687,13 @@ function registerInitCommand(program2) {
|
|
|
50383
50687
|
console.log(import_chalk16.default.gray(" You can try again later with: node9 daemon install"));
|
|
50384
50688
|
}
|
|
50385
50689
|
}
|
|
50690
|
+
} else if (isDaemonServiceEnabled()) {
|
|
50691
|
+
console.log(import_chalk16.default.green(" \u2713 Daemon login service already installed & enabled"));
|
|
50386
50692
|
} else {
|
|
50387
|
-
|
|
50693
|
+
const healed = ensureAutostartHealthy(!!getConfig().settings.autoStartDaemon);
|
|
50694
|
+
console.log(
|
|
50695
|
+
healed === "repaired" ? import_chalk16.default.green(" \u2713 Re-enabled daemon login service (was installed but disabled)") : import_chalk16.default.gray(" \xB7 Daemon login service is disabled (autostart off) \u2014 left as-is")
|
|
50696
|
+
);
|
|
50388
50697
|
}
|
|
50389
50698
|
if (!isTestingMode()) {
|
|
50390
50699
|
process.stdout.write(import_chalk16.default.dim(" Starting daemon..."));
|
|
@@ -50426,14 +50735,14 @@ function registerInitCommand(program2) {
|
|
|
50426
50735
|
|
|
50427
50736
|
// src/cli/commands/heal.ts
|
|
50428
50737
|
var import_chalk17 = __toESM(require("chalk"));
|
|
50429
|
-
var
|
|
50738
|
+
var import_fs56 = __toESM(require("fs"));
|
|
50430
50739
|
init_agent_wiring();
|
|
50431
50740
|
init_setup();
|
|
50432
50741
|
init_hook_baseline();
|
|
50433
50742
|
var hasHookSurface = (a) => a.hooks.length > 0;
|
|
50434
50743
|
function backupForHeal(file) {
|
|
50435
50744
|
try {
|
|
50436
|
-
if (file &&
|
|
50745
|
+
if (file && import_fs56.default.existsSync(file)) import_fs56.default.copyFileSync(file, `${file}.node9-heal-bak`);
|
|
50437
50746
|
} catch {
|
|
50438
50747
|
}
|
|
50439
50748
|
}
|
|
@@ -50600,7 +50909,7 @@ function registerConnectCommand(program2) {
|
|
|
50600
50909
|
}
|
|
50601
50910
|
|
|
50602
50911
|
// src/cli/commands/undo.ts
|
|
50603
|
-
var
|
|
50912
|
+
var import_path54 = __toESM(require("path"));
|
|
50604
50913
|
var import_chalk20 = __toESM(require("chalk"));
|
|
50605
50914
|
|
|
50606
50915
|
// src/tui/undo-navigator.ts
|
|
@@ -50759,7 +51068,7 @@ function findMatchingCwd(startDir, history) {
|
|
|
50759
51068
|
let dir = startDir;
|
|
50760
51069
|
while (true) {
|
|
50761
51070
|
if (cwds.has(dir)) return dir;
|
|
50762
|
-
const parent =
|
|
51071
|
+
const parent = import_path54.default.dirname(dir);
|
|
50763
51072
|
if (parent === dir) return null;
|
|
50764
51073
|
dir = parent;
|
|
50765
51074
|
}
|
|
@@ -51393,18 +51702,18 @@ function registerMcpGatewayCommand(program2) {
|
|
|
51393
51702
|
|
|
51394
51703
|
// src/mcp-server/index.ts
|
|
51395
51704
|
var import_readline5 = __toESM(require("readline"));
|
|
51396
|
-
var
|
|
51397
|
-
var
|
|
51398
|
-
var
|
|
51705
|
+
var import_fs58 = __toESM(require("fs"));
|
|
51706
|
+
var import_os52 = __toESM(require("os"));
|
|
51707
|
+
var import_path56 = __toESM(require("path"));
|
|
51399
51708
|
var import_child_process11 = require("child_process");
|
|
51400
51709
|
init_core();
|
|
51401
51710
|
init_daemon();
|
|
51402
51711
|
init_shields();
|
|
51403
51712
|
|
|
51404
51713
|
// src/auth/egress-config.ts
|
|
51405
|
-
var
|
|
51406
|
-
var
|
|
51407
|
-
var
|
|
51714
|
+
var import_fs57 = __toESM(require("fs"));
|
|
51715
|
+
var import_os51 = __toESM(require("os"));
|
|
51716
|
+
var import_path55 = __toESM(require("path"));
|
|
51408
51717
|
var DEFAULT_EGRESS = {
|
|
51409
51718
|
enabled: false,
|
|
51410
51719
|
mode: "review",
|
|
@@ -51413,12 +51722,12 @@ var DEFAULT_EGRESS = {
|
|
|
51413
51722
|
allowPrivate: true
|
|
51414
51723
|
};
|
|
51415
51724
|
function egressConfigPath() {
|
|
51416
|
-
return
|
|
51725
|
+
return import_path55.default.join(import_os51.default.homedir(), ".node9", "config.json");
|
|
51417
51726
|
}
|
|
51418
51727
|
function readEgressRawConfig() {
|
|
51419
51728
|
let text;
|
|
51420
51729
|
try {
|
|
51421
|
-
text =
|
|
51730
|
+
text = import_fs57.default.readFileSync(egressConfigPath(), "utf8");
|
|
51422
51731
|
} catch (err2) {
|
|
51423
51732
|
if (err2.code === "ENOENT") return {};
|
|
51424
51733
|
throw err2;
|
|
@@ -51433,8 +51742,8 @@ function readEgressRawConfig() {
|
|
|
51433
51742
|
}
|
|
51434
51743
|
function writeEgressRawConfig(config) {
|
|
51435
51744
|
const p = egressConfigPath();
|
|
51436
|
-
|
|
51437
|
-
|
|
51745
|
+
import_fs57.default.mkdirSync(import_path55.default.dirname(p), { recursive: true });
|
|
51746
|
+
import_fs57.default.writeFileSync(p, JSON.stringify(config, null, 2) + "\n", { mode: 384 });
|
|
51438
51747
|
}
|
|
51439
51748
|
function applyEgress(config, change) {
|
|
51440
51749
|
const policy = config.policy = config.policy ?? {};
|
|
@@ -51819,13 +52128,13 @@ function handleStatus() {
|
|
|
51819
52128
|
lines.push(`Active shields: ${activeShields.length > 0 ? activeShields.join(", ") : "none"}`);
|
|
51820
52129
|
lines.push(`Smart rules: ${config.policy.smartRules.length} loaded`);
|
|
51821
52130
|
lines.push(`DLP: ${config.policy.dlp?.enabled !== false ? "enabled" : "disabled"}`);
|
|
51822
|
-
const projectConfig =
|
|
51823
|
-
const globalConfig =
|
|
52131
|
+
const projectConfig = import_path56.default.join(process.cwd(), "node9.config.json");
|
|
52132
|
+
const globalConfig = import_path56.default.join(import_os52.default.homedir(), ".node9", "config.json");
|
|
51824
52133
|
lines.push(
|
|
51825
|
-
`Project config (node9.config.json): ${
|
|
52134
|
+
`Project config (node9.config.json): ${import_fs58.default.existsSync(projectConfig) ? "present" : "not found"}`
|
|
51826
52135
|
);
|
|
51827
52136
|
lines.push(
|
|
51828
|
-
`Global config (~/.node9/config.json): ${
|
|
52137
|
+
`Global config (~/.node9/config.json): ${import_fs58.default.existsSync(globalConfig) ? "present" : "not found"}`
|
|
51829
52138
|
);
|
|
51830
52139
|
return lines.join("\n");
|
|
51831
52140
|
}
|
|
@@ -51931,21 +52240,21 @@ function handleEgressDeny(args) {
|
|
|
51931
52240
|
addEgressHost("deny", host);
|
|
51932
52241
|
return `Denied egress to ${host} (deny always wins over allow).`;
|
|
51933
52242
|
}
|
|
51934
|
-
var GLOBAL_CONFIG_PATH =
|
|
52243
|
+
var GLOBAL_CONFIG_PATH = import_path56.default.join(import_os52.default.homedir(), ".node9", "config.json");
|
|
51935
52244
|
var APPROVER_CHANNELS = ["native", "browser", "cloud", "terminal"];
|
|
51936
52245
|
function readGlobalConfigRaw() {
|
|
51937
52246
|
try {
|
|
51938
|
-
if (
|
|
51939
|
-
return JSON.parse(
|
|
52247
|
+
if (import_fs58.default.existsSync(GLOBAL_CONFIG_PATH)) {
|
|
52248
|
+
return JSON.parse(import_fs58.default.readFileSync(GLOBAL_CONFIG_PATH, "utf-8"));
|
|
51940
52249
|
}
|
|
51941
52250
|
} catch {
|
|
51942
52251
|
}
|
|
51943
52252
|
return {};
|
|
51944
52253
|
}
|
|
51945
52254
|
function writeGlobalConfigRaw(data) {
|
|
51946
|
-
const dir =
|
|
51947
|
-
if (!
|
|
51948
|
-
|
|
52255
|
+
const dir = import_path56.default.dirname(GLOBAL_CONFIG_PATH);
|
|
52256
|
+
if (!import_fs58.default.existsSync(dir)) import_fs58.default.mkdirSync(dir, { recursive: true });
|
|
52257
|
+
import_fs58.default.writeFileSync(GLOBAL_CONFIG_PATH, JSON.stringify(data, null, 2) + "\n");
|
|
51949
52258
|
}
|
|
51950
52259
|
function handleApproverList() {
|
|
51951
52260
|
const config = getConfig();
|
|
@@ -51989,9 +52298,9 @@ function handleApproverSet(args) {
|
|
|
51989
52298
|
function handleAuditGet(args) {
|
|
51990
52299
|
const limit = Math.min(typeof args.limit === "number" ? args.limit : 20, 100);
|
|
51991
52300
|
const filter = typeof args.filter === "string" && args.filter !== "all" ? args.filter : null;
|
|
51992
|
-
const auditPath =
|
|
51993
|
-
if (!
|
|
51994
|
-
const rawLines =
|
|
52301
|
+
const auditPath = import_path56.default.join(import_os52.default.homedir(), ".node9", "audit.log");
|
|
52302
|
+
if (!import_fs58.default.existsSync(auditPath)) return "No audit log found.";
|
|
52303
|
+
const rawLines = import_fs58.default.readFileSync(auditPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
51995
52304
|
const parsed = [];
|
|
51996
52305
|
for (const line of rawLines) {
|
|
51997
52306
|
try {
|
|
@@ -52365,7 +52674,7 @@ function registerTrustCommand(program2) {
|
|
|
52365
52674
|
// src/cli/commands/mcp-pin.ts
|
|
52366
52675
|
var import_chalk24 = __toESM(require("chalk"));
|
|
52367
52676
|
init_mcp_pin();
|
|
52368
|
-
var
|
|
52677
|
+
var import_fs59 = __toESM(require("fs"));
|
|
52369
52678
|
|
|
52370
52679
|
// src/cli/commands/mcp-gateway-cmd.ts
|
|
52371
52680
|
var import_chalk23 = __toESM(require("chalk"));
|
|
@@ -52572,7 +52881,7 @@ function registerMcpPinCommand(program2) {
|
|
|
52572
52881
|
let repoCorrupt = false;
|
|
52573
52882
|
if (found.source === "repo") {
|
|
52574
52883
|
try {
|
|
52575
|
-
const raw =
|
|
52884
|
+
const raw = import_fs59.default.readFileSync(found.path, "utf-8");
|
|
52576
52885
|
const parsed = JSON.parse(raw);
|
|
52577
52886
|
repoEntries = parsed.servers ?? {};
|
|
52578
52887
|
} catch {
|
|
@@ -53072,8 +53381,8 @@ function registerPostureCommand(program2) {
|
|
|
53072
53381
|
var import_chalk30 = __toESM(require("chalk"));
|
|
53073
53382
|
|
|
53074
53383
|
// src/ci-check/fetch.ts
|
|
53075
|
-
var
|
|
53076
|
-
var
|
|
53384
|
+
var import_fs60 = __toESM(require("fs"));
|
|
53385
|
+
var import_path57 = __toESM(require("path"));
|
|
53077
53386
|
var import_node_child_process = require("child_process");
|
|
53078
53387
|
var import_undici = __toESM(require_undici());
|
|
53079
53388
|
var cachedGhToken;
|
|
@@ -53157,7 +53466,7 @@ function parseRepoUrl(input) {
|
|
|
53157
53466
|
function isLocalPath(input) {
|
|
53158
53467
|
if (input.startsWith(".") || input.startsWith("/") || input.startsWith("~")) return true;
|
|
53159
53468
|
try {
|
|
53160
|
-
return
|
|
53469
|
+
return import_fs60.default.existsSync(input) && import_fs60.default.statSync(input).isDirectory();
|
|
53161
53470
|
} catch {
|
|
53162
53471
|
return false;
|
|
53163
53472
|
}
|
|
@@ -53272,10 +53581,10 @@ function readLocalTree(dir) {
|
|
|
53272
53581
|
const files = [];
|
|
53273
53582
|
const notes = [];
|
|
53274
53583
|
const add = (rel) => {
|
|
53275
|
-
const abs =
|
|
53584
|
+
const abs = import_path57.default.join(root, rel);
|
|
53276
53585
|
try {
|
|
53277
|
-
if (
|
|
53278
|
-
files.push({ path: rel, content:
|
|
53586
|
+
if (import_fs60.default.existsSync(abs) && import_fs60.default.statSync(abs).isFile()) {
|
|
53587
|
+
files.push({ path: rel, content: import_fs60.default.readFileSync(abs, "utf8") });
|
|
53279
53588
|
}
|
|
53280
53589
|
} catch {
|
|
53281
53590
|
}
|
|
@@ -53295,7 +53604,7 @@ function readLocalTree(dir) {
|
|
|
53295
53604
|
dirsVisited++;
|
|
53296
53605
|
let entries;
|
|
53297
53606
|
try {
|
|
53298
|
-
entries =
|
|
53607
|
+
entries = import_fs60.default.readdirSync(import_path57.default.join(root, relDir), { withFileTypes: true });
|
|
53299
53608
|
} catch {
|
|
53300
53609
|
return;
|
|
53301
53610
|
}
|
|
@@ -53316,11 +53625,11 @@ function readLocalTree(dir) {
|
|
|
53316
53625
|
`repo is large \u2014 some agent-surface files may be INCOMPLETE (capped at ${MAX_SURFACE_FILES} files / ${MAX_DIRS} dirs).`
|
|
53317
53626
|
);
|
|
53318
53627
|
for (const rel of matches) collect(rel);
|
|
53319
|
-
const wfDir =
|
|
53628
|
+
const wfDir = import_path57.default.join(root, WORKFLOW_DIR);
|
|
53320
53629
|
try {
|
|
53321
|
-
if (
|
|
53322
|
-
for (const name of
|
|
53323
|
-
if (/\.ya?ml$/.test(name)) add(
|
|
53630
|
+
if (import_fs60.default.existsSync(wfDir)) {
|
|
53631
|
+
for (const name of import_fs60.default.readdirSync(wfDir)) {
|
|
53632
|
+
if (/\.ya?ml$/.test(name)) add(import_path57.default.join(WORKFLOW_DIR, name));
|
|
53324
53633
|
}
|
|
53325
53634
|
}
|
|
53326
53635
|
} catch {
|
|
@@ -53593,7 +53902,7 @@ function severityFromScore(score) {
|
|
|
53593
53902
|
if (score >= 1) return "advisory";
|
|
53594
53903
|
return null;
|
|
53595
53904
|
}
|
|
53596
|
-
function analyzeWorkflow(
|
|
53905
|
+
function analyzeWorkflow(path71, content) {
|
|
53597
53906
|
let raw;
|
|
53598
53907
|
try {
|
|
53599
53908
|
raw = (0, import_yaml.parse)(content) ?? {};
|
|
@@ -53714,7 +54023,7 @@ function analyzeWorkflow(path70, content) {
|
|
|
53714
54023
|
dimension: "workflows",
|
|
53715
54024
|
severity,
|
|
53716
54025
|
title,
|
|
53717
|
-
file:
|
|
54026
|
+
file: path71,
|
|
53718
54027
|
signals,
|
|
53719
54028
|
mitigations: mitigations.length ? mitigations : void 0,
|
|
53720
54029
|
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."
|
|
@@ -53790,7 +54099,7 @@ function evalAgentJob(job, wf, raw, untrustedTrigger, reusable) {
|
|
|
53790
54099
|
if (reusable && !loadedGun && SEVERITY_RANK2[severity] > SEVERITY_RANK2.medium) severity = "medium";
|
|
53791
54100
|
return { severity, secrets, injectable, canReadEnv };
|
|
53792
54101
|
}
|
|
53793
|
-
function analyzeWorkflowSecrets(
|
|
54102
|
+
function analyzeWorkflowSecrets(path71, content) {
|
|
53794
54103
|
let raw;
|
|
53795
54104
|
try {
|
|
53796
54105
|
raw = (0, import_yaml.parse)(content) ?? {};
|
|
@@ -53810,7 +54119,7 @@ function analyzeWorkflowSecrets(path70, content) {
|
|
|
53810
54119
|
dimension: "data",
|
|
53811
54120
|
severity: worst.severity,
|
|
53812
54121
|
title: worst.severity === "advisory" ? "Secrets reachable by the agent \u2014 hardening" : "Exfiltratable secrets reachable by an injectable agent",
|
|
53813
|
-
file:
|
|
54122
|
+
file: path71,
|
|
53814
54123
|
signals: [
|
|
53815
54124
|
`agent can reach: ${worst.secrets.map((s) => s.name).join(", ")}`,
|
|
53816
54125
|
worst.injectable ? "the agent is externally triggerable (untrusted trigger, no gate)" : "gated / not externally triggerable \u2014 latent risk only",
|
|
@@ -53837,7 +54146,7 @@ function hookCommands(hooks) {
|
|
|
53837
54146
|
}
|
|
53838
54147
|
return out;
|
|
53839
54148
|
}
|
|
53840
|
-
function analyzeAgentConfig(
|
|
54149
|
+
function analyzeAgentConfig(path71, content) {
|
|
53841
54150
|
let cfg;
|
|
53842
54151
|
try {
|
|
53843
54152
|
cfg = JSON.parse(content);
|
|
@@ -53856,7 +54165,7 @@ function analyzeAgentConfig(path70, content) {
|
|
|
53856
54165
|
dimension: "toolRules",
|
|
53857
54166
|
severity: high ? "high" : "medium",
|
|
53858
54167
|
title: high ? "Agent hook runs UNPINNED/remote third-party code on every action" : "Agent hook runs third-party code in the agent hot path",
|
|
53859
|
-
file:
|
|
54168
|
+
file: path71,
|
|
53860
54169
|
signals: [
|
|
53861
54170
|
`hook command: \`${cmd.slice(0, 120)}\``,
|
|
53862
54171
|
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"
|
|
@@ -53876,7 +54185,7 @@ function analyzeAgentConfig(path70, content) {
|
|
|
53876
54185
|
dimension: "toolRules",
|
|
53877
54186
|
severity: hasBackstop ? "medium" : "high",
|
|
53878
54187
|
title: hasBackstop ? "Committed agent config pre-authorizes broad tools" : "Committed agent config pre-authorizes broad tools with no deny backstop",
|
|
53879
|
-
file:
|
|
54188
|
+
file: path71,
|
|
53880
54189
|
signals: [
|
|
53881
54190
|
`broad allow(s): ${broad.slice(0, 5).join(", ")}`,
|
|
53882
54191
|
hasBackstop ? "a `deny` list backstops the broad allow" : "no `deny` entry covers Bash/Write/Edit \u2014 every contributor is pre-authorized for catastrophic tools"
|
|
@@ -53889,16 +54198,16 @@ function analyzeAgentConfig(path70, content) {
|
|
|
53889
54198
|
|
|
53890
54199
|
// src/ci-check/mcp.ts
|
|
53891
54200
|
init_dist();
|
|
53892
|
-
function analyzeMcp(
|
|
54201
|
+
function analyzeMcp(path71, content) {
|
|
53893
54202
|
let cfg;
|
|
53894
54203
|
try {
|
|
53895
54204
|
cfg = JSON.parse(content);
|
|
53896
54205
|
} catch {
|
|
53897
54206
|
return [];
|
|
53898
54207
|
}
|
|
53899
|
-
return analyzeMcpServers(cfg.mcpServers ?? {},
|
|
54208
|
+
return analyzeMcpServers(cfg.mcpServers ?? {}, path71);
|
|
53900
54209
|
}
|
|
53901
|
-
function analyzeMcpServers(servers,
|
|
54210
|
+
function analyzeMcpServers(servers, path71) {
|
|
53902
54211
|
const findings = [];
|
|
53903
54212
|
for (const [name, srv] of Object.entries(servers ?? {})) {
|
|
53904
54213
|
if (!srv || srv.disabled) continue;
|
|
@@ -53909,7 +54218,7 @@ function analyzeMcpServers(servers, path70) {
|
|
|
53909
54218
|
dimension: "mcp",
|
|
53910
54219
|
severity: "medium",
|
|
53911
54220
|
title: `MCP server "${name}" runs an unpinned executable`,
|
|
53912
|
-
file:
|
|
54221
|
+
file: path71,
|
|
53913
54222
|
signals: [`\`${argv.slice(0, 120)}\` \u2014 unversioned/@latest npx`],
|
|
53914
54223
|
fix: "Pin the MCP server package to an exact version so a PR (or a registry compromise) can\u2019t swap the toolchain."
|
|
53915
54224
|
});
|
|
@@ -53923,7 +54232,7 @@ function analyzeMcpServers(servers, path70) {
|
|
|
53923
54232
|
dimension: "mcp",
|
|
53924
54233
|
severity: "high",
|
|
53925
54234
|
title: `MCP server "${name}" has an inline credential`,
|
|
53926
|
-
file:
|
|
54235
|
+
file: path71,
|
|
53927
54236
|
signals: [
|
|
53928
54237
|
`env.${k} matches ${hit.patternName} \u2014 agent-reachable secret committed to the repo`
|
|
53929
54238
|
],
|
|
@@ -53937,7 +54246,7 @@ function analyzeMcpServers(servers, path70) {
|
|
|
53937
54246
|
|
|
53938
54247
|
// src/ci-check/codex.ts
|
|
53939
54248
|
var import_smol_toml5 = require("smol-toml");
|
|
53940
|
-
function analyzeCodexConfig(
|
|
54249
|
+
function analyzeCodexConfig(path71, content) {
|
|
53941
54250
|
let cfg;
|
|
53942
54251
|
try {
|
|
53943
54252
|
cfg = (0, import_smol_toml5.parse)(content);
|
|
@@ -53945,7 +54254,7 @@ function analyzeCodexConfig(path70, content) {
|
|
|
53945
54254
|
return [];
|
|
53946
54255
|
}
|
|
53947
54256
|
const findings = [];
|
|
53948
|
-
findings.push(...analyzeMcpServers(cfg.mcp_servers ?? {},
|
|
54257
|
+
findings.push(...analyzeMcpServers(cfg.mcp_servers ?? {}, path71));
|
|
53949
54258
|
const sandbox = typeof cfg.sandbox_mode === "string" ? cfg.sandbox_mode : "";
|
|
53950
54259
|
const approval = typeof cfg.approval_policy === "string" ? cfg.approval_policy : "";
|
|
53951
54260
|
const fullAccess = /danger-full-access/i.test(sandbox);
|
|
@@ -53960,7 +54269,7 @@ function analyzeCodexConfig(path70, content) {
|
|
|
53960
54269
|
dimension: "toolRules",
|
|
53961
54270
|
severity: fullAccess ? "high" : "medium",
|
|
53962
54271
|
title: fullAccess ? "Codex config grants a full-access sandbox" : "Codex config never requires approval",
|
|
53963
|
-
file:
|
|
54272
|
+
file: path71,
|
|
53964
54273
|
signals,
|
|
53965
54274
|
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.'
|
|
53966
54275
|
});
|
|
@@ -54016,10 +54325,10 @@ function decodeSuspiciousBase64(text) {
|
|
|
54016
54325
|
}
|
|
54017
54326
|
return out;
|
|
54018
54327
|
}
|
|
54019
|
-
function mk(severity, title, signals, fix,
|
|
54020
|
-
return { check: "CI-6", dimension: "instructions", severity, title, file:
|
|
54328
|
+
function mk(severity, title, signals, fix, path71) {
|
|
54329
|
+
return { check: "CI-6", dimension: "instructions", severity, title, file: path71, signals, fix };
|
|
54021
54330
|
}
|
|
54022
|
-
function analyzeInstructionFile(
|
|
54331
|
+
function analyzeInstructionFile(path71, content) {
|
|
54023
54332
|
const findings = [];
|
|
54024
54333
|
const decoded = decodeSuspiciousBase64(content);
|
|
54025
54334
|
if (TAG_CHARS.test(content))
|
|
@@ -54031,7 +54340,7 @@ function analyzeInstructionFile(path70, content) {
|
|
|
54031
54340
|
"contains Unicode tag characters (U+E0000\u2013E007F) \u2014 an invisible instruction-smuggling channel with no legitimate use in text"
|
|
54032
54341
|
],
|
|
54033
54342
|
"Remove the tag characters. Instruction files must be plain, reviewable text.",
|
|
54034
|
-
|
|
54343
|
+
path71
|
|
54035
54344
|
)
|
|
54036
54345
|
);
|
|
54037
54346
|
if (BIDI_OVERRIDE.test(content))
|
|
@@ -54043,7 +54352,7 @@ function analyzeInstructionFile(path70, content) {
|
|
|
54043
54352
|
"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"
|
|
54044
54353
|
],
|
|
54045
54354
|
"Remove the bidi override characters.",
|
|
54046
|
-
|
|
54355
|
+
path71
|
|
54047
54356
|
)
|
|
54048
54357
|
);
|
|
54049
54358
|
else if (BIDI_EMBED_ISOLATE.test(content))
|
|
@@ -54055,7 +54364,7 @@ function analyzeInstructionFile(path70, content) {
|
|
|
54055
54364
|
"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"
|
|
54056
54365
|
],
|
|
54057
54366
|
"Confirm the bidi marks are legitimate RTL formatting; remove otherwise.",
|
|
54058
|
-
|
|
54367
|
+
path71
|
|
54059
54368
|
)
|
|
54060
54369
|
);
|
|
54061
54370
|
const zw = suspiciousZeroWidth(content);
|
|
@@ -54069,7 +54378,7 @@ function analyzeInstructionFile(path70, content) {
|
|
|
54069
54378
|
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)"
|
|
54070
54379
|
],
|
|
54071
54380
|
"Remove the zero-width characters. Instruction files must be plain, reviewable text.",
|
|
54072
|
-
|
|
54381
|
+
path71
|
|
54073
54382
|
)
|
|
54074
54383
|
);
|
|
54075
54384
|
}
|
|
@@ -54085,7 +54394,7 @@ function analyzeInstructionFile(path70, content) {
|
|
|
54085
54394
|
`contains a prompt-override / role-impersonation directive (\`${m[0].slice(0, 60).trim()}\`)${ovEnc ? " \u2014 concealed in a base64 blob" : ""}`
|
|
54086
54395
|
],
|
|
54087
54396
|
"Remove the override text. An instruction file should not tell the agent to ignore its own rules.",
|
|
54088
|
-
|
|
54397
|
+
path71
|
|
54089
54398
|
)
|
|
54090
54399
|
);
|
|
54091
54400
|
}
|
|
@@ -54097,7 +54406,7 @@ function analyzeInstructionFile(path70, content) {
|
|
|
54097
54406
|
"Instruction directs the agent to fetch and run remote code",
|
|
54098
54407
|
[`\`${fo[0].slice(0, 70).trim()}\` \u2014 fetch-and-obey, outside an install/setup section`],
|
|
54099
54408
|
"Do not instruct the agent to pipe remote content into a shell; pin and vendor scripts instead.",
|
|
54100
|
-
|
|
54409
|
+
path71
|
|
54101
54410
|
)
|
|
54102
54411
|
);
|
|
54103
54412
|
}
|
|
@@ -54109,7 +54418,7 @@ function analyzeInstructionFile(path70, content) {
|
|
|
54109
54418
|
"Instruction points the agent at credential material",
|
|
54110
54419
|
[`references \`${sp[0].slice(0, 50).trim()}\` \u2014 directs the agent toward secrets`],
|
|
54111
54420
|
"Do not reference credential files or paths in agent instructions.",
|
|
54112
|
-
|
|
54421
|
+
path71
|
|
54113
54422
|
)
|
|
54114
54423
|
);
|
|
54115
54424
|
}
|
|
@@ -54121,7 +54430,7 @@ function analyzeInstructionFile(path70, content) {
|
|
|
54121
54430
|
"Instruction directs the agent to send data to an external endpoint",
|
|
54122
54431
|
[`\`${ex[0].slice(0, 70).trim()}\` \u2014 possible exfiltration directive`],
|
|
54123
54432
|
"Remove external post/upload directives from agent instructions.",
|
|
54124
|
-
|
|
54433
|
+
path71
|
|
54125
54434
|
)
|
|
54126
54435
|
);
|
|
54127
54436
|
}
|
|
@@ -54421,19 +54730,19 @@ function registerEgressCommand(program2) {
|
|
|
54421
54730
|
var import_chalk32 = __toESM(require("chalk"));
|
|
54422
54731
|
|
|
54423
54732
|
// src/shields/jail.ts
|
|
54424
|
-
var
|
|
54425
|
-
var
|
|
54426
|
-
var
|
|
54733
|
+
var import_fs61 = __toESM(require("fs"));
|
|
54734
|
+
var import_os53 = __toESM(require("os"));
|
|
54735
|
+
var import_path58 = __toESM(require("path"));
|
|
54427
54736
|
init_build();
|
|
54428
54737
|
init_shields();
|
|
54429
54738
|
var USER_JAIL_SHIELD = "user-jail";
|
|
54430
54739
|
function jailStorePath() {
|
|
54431
|
-
return
|
|
54740
|
+
return import_path58.default.join(import_os53.default.homedir(), ".node9", "jail-paths.json");
|
|
54432
54741
|
}
|
|
54433
54742
|
function readJailPaths() {
|
|
54434
54743
|
let text;
|
|
54435
54744
|
try {
|
|
54436
|
-
text =
|
|
54745
|
+
text = import_fs61.default.readFileSync(jailStorePath(), "utf8");
|
|
54437
54746
|
} catch (err2) {
|
|
54438
54747
|
if (err2.code === "ENOENT") return [];
|
|
54439
54748
|
throw err2;
|
|
@@ -54451,8 +54760,8 @@ function readJailPaths() {
|
|
|
54451
54760
|
}
|
|
54452
54761
|
function writeJailPaths(paths) {
|
|
54453
54762
|
const p = jailStorePath();
|
|
54454
|
-
|
|
54455
|
-
|
|
54763
|
+
import_fs61.default.mkdirSync(import_path58.default.dirname(p), { recursive: true });
|
|
54764
|
+
import_fs61.default.writeFileSync(p, JSON.stringify({ paths }, null, 2) + "\n", { mode: 384 });
|
|
54456
54765
|
}
|
|
54457
54766
|
function addJailPath(rawPath, verdict) {
|
|
54458
54767
|
const norm = rawPath.trim();
|
|
@@ -54474,14 +54783,14 @@ function removeJailPath(rawPath) {
|
|
|
54474
54783
|
return { removed, paths: after };
|
|
54475
54784
|
}
|
|
54476
54785
|
function regenerateUserJail(paths) {
|
|
54477
|
-
const file =
|
|
54786
|
+
const file = import_path58.default.join(USER_SHIELDS_DIR_PATH, `${USER_JAIL_SHIELD}.json`);
|
|
54478
54787
|
if (paths.length === 0) {
|
|
54479
54788
|
const active2 = readActiveShields();
|
|
54480
54789
|
if (active2.includes(USER_JAIL_SHIELD)) {
|
|
54481
54790
|
writeActiveShields(active2.filter((s) => s !== USER_JAIL_SHIELD));
|
|
54482
54791
|
}
|
|
54483
54792
|
try {
|
|
54484
|
-
|
|
54793
|
+
import_fs61.default.rmSync(file, { force: true });
|
|
54485
54794
|
} catch {
|
|
54486
54795
|
}
|
|
54487
54796
|
return;
|
|
@@ -54595,14 +54904,14 @@ function registerJailCommand(program2) {
|
|
|
54595
54904
|
|
|
54596
54905
|
// src/cli/commands/sandbox.ts
|
|
54597
54906
|
var import_chalk33 = __toESM(require("chalk"));
|
|
54598
|
-
var
|
|
54599
|
-
var
|
|
54907
|
+
var import_fs64 = __toESM(require("fs"));
|
|
54908
|
+
var import_path61 = __toESM(require("path"));
|
|
54600
54909
|
var import_child_process13 = require("child_process");
|
|
54601
54910
|
init_config();
|
|
54602
54911
|
|
|
54603
54912
|
// src/sandbox/config.ts
|
|
54604
|
-
var
|
|
54605
|
-
var
|
|
54913
|
+
var import_fs62 = __toESM(require("fs"));
|
|
54914
|
+
var import_path59 = __toESM(require("path"));
|
|
54606
54915
|
var import_yaml2 = require("yaml");
|
|
54607
54916
|
var SANDBOX_CONFIG_FILE = "node9.sandbox.yaml";
|
|
54608
54917
|
var FORBIDDEN_ENV = /* @__PURE__ */ new Set(["NODE9_API_KEY", "NODE9_API_URL"]);
|
|
@@ -54675,16 +54984,16 @@ function scaffoldSandboxYaml(agent) {
|
|
|
54675
54984
|
return header + (0, import_yaml2.stringify)(defaultSandboxConfig(agent));
|
|
54676
54985
|
}
|
|
54677
54986
|
function sandboxConfigPath(cwd = process.cwd()) {
|
|
54678
|
-
return
|
|
54987
|
+
return import_path59.default.join(cwd, SANDBOX_CONFIG_FILE);
|
|
54679
54988
|
}
|
|
54680
54989
|
function loadSandboxConfig(cwd = process.cwd(), fallbackAgent = "claude") {
|
|
54681
54990
|
const p = sandboxConfigPath(cwd);
|
|
54682
|
-
if (!
|
|
54991
|
+
if (!import_fs62.default.existsSync(p)) {
|
|
54683
54992
|
throw new Error(`sandbox: ${SANDBOX_CONFIG_FILE} not found \u2014 run \`node9 sandbox new\` first.`);
|
|
54684
54993
|
}
|
|
54685
54994
|
let raw;
|
|
54686
54995
|
try {
|
|
54687
|
-
raw = (0, import_yaml2.parse)(
|
|
54996
|
+
raw = (0, import_yaml2.parse)(import_fs62.default.readFileSync(p, "utf-8"));
|
|
54688
54997
|
} catch (err2) {
|
|
54689
54998
|
throw new Error(
|
|
54690
54999
|
`sandbox: ${SANDBOX_CONFIG_FILE} is not valid YAML \u2014 ${err2.message}`
|
|
@@ -54742,14 +55051,14 @@ function compileAllowlist(input) {
|
|
|
54742
55051
|
init_templates();
|
|
54743
55052
|
|
|
54744
55053
|
// src/sandbox/runtime.ts
|
|
54745
|
-
var
|
|
54746
|
-
var
|
|
54747
|
-
var
|
|
55054
|
+
var import_fs63 = __toESM(require("fs"));
|
|
55055
|
+
var import_os54 = __toESM(require("os"));
|
|
55056
|
+
var import_path60 = __toESM(require("path"));
|
|
54748
55057
|
var import_crypto14 = __toESM(require("crypto"));
|
|
54749
55058
|
var import_child_process12 = require("child_process");
|
|
54750
55059
|
init_templates();
|
|
54751
55060
|
function sandboxDataDir(cwd = process.cwd()) {
|
|
54752
|
-
return
|
|
55061
|
+
return import_path60.default.join(cwd, ".node9", "sandbox", "data");
|
|
54753
55062
|
}
|
|
54754
55063
|
function detectEngine(engine) {
|
|
54755
55064
|
const r = (0, import_child_process12.spawnSync)(engine, ["--version"], { encoding: "utf-8" });
|
|
@@ -54760,7 +55069,7 @@ function detectEngine(engine) {
|
|
|
54760
55069
|
}
|
|
54761
55070
|
function agentCredentialsMount(agent) {
|
|
54762
55071
|
const rel = agent === "codex" ? ".codex/auth.json" : ".claude/.credentials.json";
|
|
54763
|
-
return { hostPath:
|
|
55072
|
+
return { hostPath: import_path60.default.join(import_os54.default.homedir(), rel), target: `/home/${RUN_AS_USER}/${rel}` };
|
|
54764
55073
|
}
|
|
54765
55074
|
function buildRunArgs(opts) {
|
|
54766
55075
|
const { config, workspaceHostPath, dataHostPath, allowlistHostPath, agentArgs } = opts;
|
|
@@ -54770,7 +55079,7 @@ function buildRunArgs(opts) {
|
|
|
54770
55079
|
args.push("-v", `${allowlistHostPath}:${ALLOWED_DOMAINS_PATH}:ro`);
|
|
54771
55080
|
if (config.node9.mountAgentCredentials) {
|
|
54772
55081
|
const creds = agentCredentialsMount(config.agent);
|
|
54773
|
-
if (
|
|
55082
|
+
if (import_fs63.default.existsSync(creds.hostPath)) {
|
|
54774
55083
|
args.push("-v", `${creds.hostPath}:${creds.target}`);
|
|
54775
55084
|
}
|
|
54776
55085
|
}
|
|
@@ -54788,30 +55097,30 @@ function imageContentHash(dockerfile, entrypoint) {
|
|
|
54788
55097
|
return import_crypto14.default.createHash("sha256").update(dockerfile).update("\0").update(entrypoint).digest("hex").slice(0, 16);
|
|
54789
55098
|
}
|
|
54790
55099
|
function sandboxBuildDir(cwd = process.cwd()) {
|
|
54791
|
-
return
|
|
55100
|
+
return import_path60.default.join(cwd, ".node9", "sandbox", "build");
|
|
54792
55101
|
}
|
|
54793
55102
|
function writeBuildContext(cwd, dockerfile, entrypoint) {
|
|
54794
55103
|
const dir = sandboxBuildDir(cwd);
|
|
54795
|
-
|
|
54796
|
-
|
|
54797
|
-
|
|
55104
|
+
import_fs63.default.mkdirSync(dir, { recursive: true });
|
|
55105
|
+
import_fs63.default.writeFileSync(import_path60.default.join(dir, "Dockerfile"), dockerfile);
|
|
55106
|
+
import_fs63.default.writeFileSync(import_path60.default.join(dir, "entrypoint.sh"), entrypoint);
|
|
54798
55107
|
return dir;
|
|
54799
55108
|
}
|
|
54800
55109
|
function writeAllowlist(cwd, hosts) {
|
|
54801
|
-
const dir =
|
|
54802
|
-
|
|
54803
|
-
const p =
|
|
54804
|
-
|
|
55110
|
+
const dir = import_path60.default.join(cwd, ".node9", "sandbox");
|
|
55111
|
+
import_fs63.default.mkdirSync(dir, { recursive: true });
|
|
55112
|
+
const p = import_path60.default.join(dir, "allowed-domains.txt");
|
|
55113
|
+
import_fs63.default.writeFileSync(p, hosts.join("\n") + "\n");
|
|
54805
55114
|
return p;
|
|
54806
55115
|
}
|
|
54807
55116
|
function resolveHomePath(p) {
|
|
54808
|
-
return p.startsWith("~") ?
|
|
55117
|
+
return p.startsWith("~") ? import_path60.default.join(import_os54.default.homedir(), p.slice(1)) : import_path60.default.resolve(p);
|
|
54809
55118
|
}
|
|
54810
55119
|
|
|
54811
55120
|
// src/cli/commands/sandbox.ts
|
|
54812
55121
|
function seedDataDirConfig(dataDir, sandbox) {
|
|
54813
|
-
|
|
54814
|
-
const configPath =
|
|
55122
|
+
import_fs64.default.mkdirSync(dataDir, { recursive: true });
|
|
55123
|
+
const configPath = import_path61.default.join(dataDir, "config.json");
|
|
54815
55124
|
const seed = {
|
|
54816
55125
|
settings: {
|
|
54817
55126
|
approvers: {
|
|
@@ -54822,7 +55131,7 @@ function seedDataDirConfig(dataDir, sandbox) {
|
|
|
54822
55131
|
}
|
|
54823
55132
|
}
|
|
54824
55133
|
};
|
|
54825
|
-
|
|
55134
|
+
import_fs64.default.writeFileSync(configPath, JSON.stringify(seed, null, 2), { mode: 384 });
|
|
54826
55135
|
}
|
|
54827
55136
|
function registerSandboxCommand(program2, version2) {
|
|
54828
55137
|
const node9Version2 = pinnedNode9Version(version2);
|
|
@@ -54830,13 +55139,13 @@ function registerSandboxCommand(program2, version2) {
|
|
|
54830
55139
|
cmd.command("new").description(`Scaffold ${SANDBOX_CONFIG_FILE} in this project`).option("--agent <agent>", "claude (default) or codex", "claude").action((opts) => {
|
|
54831
55140
|
const agent = opts.agent === "codex" ? "codex" : "claude";
|
|
54832
55141
|
const p = sandboxConfigPath();
|
|
54833
|
-
if (
|
|
55142
|
+
if (import_fs64.default.existsSync(p)) {
|
|
54834
55143
|
console.log(
|
|
54835
55144
|
import_chalk33.default.yellow(` ${SANDBOX_CONFIG_FILE} already exists \u2014 leaving it untouched.`)
|
|
54836
55145
|
);
|
|
54837
55146
|
return;
|
|
54838
55147
|
}
|
|
54839
|
-
|
|
55148
|
+
import_fs64.default.writeFileSync(p, scaffoldSandboxYaml(agent));
|
|
54840
55149
|
console.log(
|
|
54841
55150
|
import_chalk33.default.green(` \u2713 wrote ${SANDBOX_CONFIG_FILE}`) + import_chalk33.default.dim(` (agent: ${agent})`)
|
|
54842
55151
|
);
|
|
@@ -54876,8 +55185,8 @@ function registerSandboxCommand(program2, version2) {
|
|
|
54876
55185
|
const buildDir = writeBuildContext(cwd, dockerfile, entrypoint);
|
|
54877
55186
|
const hash = imageContentHash(dockerfile, entrypoint);
|
|
54878
55187
|
const image = sandbox.runtime.image;
|
|
54879
|
-
const hashFile =
|
|
54880
|
-
const lastHash =
|
|
55188
|
+
const hashFile = import_path61.default.join(sandboxBuildDir(cwd), ".image-hash");
|
|
55189
|
+
const lastHash = import_fs64.default.existsSync(hashFile) ? import_fs64.default.readFileSync(hashFile, "utf-8").trim() : "";
|
|
54881
55190
|
const imageExists = (0, import_child_process13.spawnSync)(sandbox.runtime.engine, ["image", "inspect", image], { stdio: "ignore" }).status === 0;
|
|
54882
55191
|
const needBuild = sandbox.runtime.rebuild === "always" || !imageExists || sandbox.runtime.rebuild !== "never" && lastHash !== hash;
|
|
54883
55192
|
if (needBuild) {
|
|
@@ -54889,7 +55198,7 @@ function registerSandboxCommand(program2, version2) {
|
|
|
54889
55198
|
console.error(import_chalk33.default.red(" build failed."));
|
|
54890
55199
|
process.exit(b.status ?? 1);
|
|
54891
55200
|
}
|
|
54892
|
-
|
|
55201
|
+
import_fs64.default.writeFileSync(hashFile, hash);
|
|
54893
55202
|
}
|
|
54894
55203
|
const dataDir = sandboxDataDir(cwd);
|
|
54895
55204
|
seedDataDirConfig(dataDir, sandbox);
|
|
@@ -54903,7 +55212,7 @@ function registerSandboxCommand(program2, version2) {
|
|
|
54903
55212
|
});
|
|
54904
55213
|
if (sandbox.node9.mountAgentCredentials) {
|
|
54905
55214
|
const creds = agentCredentialsMount(sandbox.agent);
|
|
54906
|
-
if (
|
|
55215
|
+
if (import_fs64.default.existsSync(creds.hostPath)) {
|
|
54907
55216
|
console.log(import_chalk33.default.dim(` mounting ${creds.hostPath} (agent credentials, rw)`));
|
|
54908
55217
|
} else {
|
|
54909
55218
|
console.log(
|
|
@@ -54919,20 +55228,20 @@ function registerSandboxCommand(program2, version2) {
|
|
|
54919
55228
|
process.exit(r.status ?? 0);
|
|
54920
55229
|
});
|
|
54921
55230
|
cmd.command("tail").description("Stream the sandbox's audit log (host-side)").action(() => {
|
|
54922
|
-
const auditPath =
|
|
54923
|
-
if (!
|
|
55231
|
+
const auditPath = import_path61.default.join(sandboxDataDir(), "audit.log");
|
|
55232
|
+
if (!import_fs64.default.existsSync(auditPath)) {
|
|
54924
55233
|
console.log(import_chalk33.default.dim(" no sandbox audit yet."));
|
|
54925
55234
|
return;
|
|
54926
55235
|
}
|
|
54927
55236
|
(0, import_child_process13.spawnSync)("tail", ["-f", auditPath], { stdio: "inherit" });
|
|
54928
55237
|
});
|
|
54929
55238
|
cmd.command("logs").description("Dump the sandbox's audit log").action(() => {
|
|
54930
|
-
const auditPath =
|
|
54931
|
-
if (!
|
|
55239
|
+
const auditPath = import_path61.default.join(sandboxDataDir(), "audit.log");
|
|
55240
|
+
if (!import_fs64.default.existsSync(auditPath)) {
|
|
54932
55241
|
console.log(import_chalk33.default.dim(" no sandbox audit yet."));
|
|
54933
55242
|
return;
|
|
54934
55243
|
}
|
|
54935
|
-
process.stdout.write(
|
|
55244
|
+
process.stdout.write(import_fs64.default.readFileSync(auditPath, "utf-8"));
|
|
54936
55245
|
});
|
|
54937
55246
|
cmd.command("clean").description("Remove the sandbox image, build context, and data").action(() => {
|
|
54938
55247
|
const cwd = process.cwd();
|
|
@@ -54946,16 +55255,16 @@ function registerSandboxCommand(program2, version2) {
|
|
|
54946
55255
|
stdio: "ignore"
|
|
54947
55256
|
});
|
|
54948
55257
|
}
|
|
54949
|
-
|
|
55258
|
+
import_fs64.default.rmSync(import_path61.default.join(cwd, ".node9", "sandbox"), { recursive: true, force: true });
|
|
54950
55259
|
console.log(import_chalk33.default.green(" \u2713 sandbox image + build + data removed."));
|
|
54951
55260
|
});
|
|
54952
55261
|
}
|
|
54953
55262
|
|
|
54954
55263
|
// src/cli/commands/sessions.ts
|
|
54955
55264
|
var import_chalk34 = __toESM(require("chalk"));
|
|
54956
|
-
var
|
|
54957
|
-
var
|
|
54958
|
-
var
|
|
55265
|
+
var import_fs65 = __toESM(require("fs"));
|
|
55266
|
+
var import_path62 = __toESM(require("path"));
|
|
55267
|
+
var import_os55 = __toESM(require("os"));
|
|
54959
55268
|
init_scan_summary();
|
|
54960
55269
|
init_litellm();
|
|
54961
55270
|
init_cost_gemini();
|
|
@@ -54976,10 +55285,10 @@ function encodeProjectPath(projectPath) {
|
|
|
54976
55285
|
}
|
|
54977
55286
|
function sessionJsonlPath(projectPath, sessionId) {
|
|
54978
55287
|
const encoded = encodeProjectPath(projectPath);
|
|
54979
|
-
return
|
|
55288
|
+
return import_path62.default.join(import_os55.default.homedir(), ".claude", "projects", encoded, `${sessionId}.jsonl`);
|
|
54980
55289
|
}
|
|
54981
55290
|
function projectLabel(projectPath) {
|
|
54982
|
-
return projectPath.replace(
|
|
55291
|
+
return projectPath.replace(import_os55.default.homedir(), "~");
|
|
54983
55292
|
}
|
|
54984
55293
|
function parseHistoryLines(lines) {
|
|
54985
55294
|
const entries = [];
|
|
@@ -55048,10 +55357,10 @@ function parseSessionLines(lines) {
|
|
|
55048
55357
|
return { toolCalls, costUSD, hasSnapshot, modifiedFiles };
|
|
55049
55358
|
}
|
|
55050
55359
|
function loadAuditEntries(auditPath) {
|
|
55051
|
-
const aPath = auditPath ??
|
|
55360
|
+
const aPath = auditPath ?? import_path62.default.join(import_os55.default.homedir(), ".node9", "audit.log");
|
|
55052
55361
|
let raw;
|
|
55053
55362
|
try {
|
|
55054
|
-
raw =
|
|
55363
|
+
raw = import_fs65.default.readFileSync(aPath, "utf-8");
|
|
55055
55364
|
} catch {
|
|
55056
55365
|
return [];
|
|
55057
55366
|
}
|
|
@@ -55087,8 +55396,8 @@ function auditEntriesInWindow(entries, windowStart, windowEnd) {
|
|
|
55087
55396
|
return result;
|
|
55088
55397
|
}
|
|
55089
55398
|
function buildGeminiSessions(days, allAuditEntries) {
|
|
55090
|
-
const tmpDir =
|
|
55091
|
-
if (!
|
|
55399
|
+
const tmpDir = import_path62.default.join(import_os55.default.homedir(), ".gemini", "tmp");
|
|
55400
|
+
if (!import_fs65.default.existsSync(tmpDir)) return [];
|
|
55092
55401
|
const cutoff = days !== null ? (() => {
|
|
55093
55402
|
const d = /* @__PURE__ */ new Date();
|
|
55094
55403
|
d.setDate(d.getDate() - days);
|
|
@@ -55097,35 +55406,35 @@ function buildGeminiSessions(days, allAuditEntries) {
|
|
|
55097
55406
|
})() : null;
|
|
55098
55407
|
let slugDirs;
|
|
55099
55408
|
try {
|
|
55100
|
-
slugDirs =
|
|
55409
|
+
slugDirs = import_fs65.default.readdirSync(tmpDir);
|
|
55101
55410
|
} catch {
|
|
55102
55411
|
return [];
|
|
55103
55412
|
}
|
|
55104
55413
|
const summaries = [];
|
|
55105
55414
|
for (const slug2 of slugDirs) {
|
|
55106
|
-
const slugPath =
|
|
55415
|
+
const slugPath = import_path62.default.join(tmpDir, slug2);
|
|
55107
55416
|
try {
|
|
55108
|
-
if (!
|
|
55417
|
+
if (!import_fs65.default.statSync(slugPath).isDirectory()) continue;
|
|
55109
55418
|
} catch {
|
|
55110
55419
|
continue;
|
|
55111
55420
|
}
|
|
55112
|
-
let projectRoot =
|
|
55421
|
+
let projectRoot = import_path62.default.join(import_os55.default.homedir(), slug2);
|
|
55113
55422
|
try {
|
|
55114
|
-
projectRoot =
|
|
55423
|
+
projectRoot = import_fs65.default.readFileSync(import_path62.default.join(slugPath, ".project_root"), "utf-8").trim();
|
|
55115
55424
|
} catch {
|
|
55116
55425
|
}
|
|
55117
|
-
const chatsDir =
|
|
55118
|
-
if (!
|
|
55426
|
+
const chatsDir = import_path62.default.join(slugPath, "chats");
|
|
55427
|
+
if (!import_fs65.default.existsSync(chatsDir)) continue;
|
|
55119
55428
|
let chatFiles;
|
|
55120
55429
|
try {
|
|
55121
|
-
chatFiles =
|
|
55430
|
+
chatFiles = import_fs65.default.readdirSync(chatsDir).filter((f) => f.endsWith(".json"));
|
|
55122
55431
|
} catch {
|
|
55123
55432
|
continue;
|
|
55124
55433
|
}
|
|
55125
55434
|
for (const chatFile of chatFiles) {
|
|
55126
55435
|
let raw;
|
|
55127
55436
|
try {
|
|
55128
|
-
raw =
|
|
55437
|
+
raw = import_fs65.default.readFileSync(import_path62.default.join(chatsDir, chatFile), "utf-8");
|
|
55129
55438
|
} catch {
|
|
55130
55439
|
continue;
|
|
55131
55440
|
}
|
|
@@ -55205,8 +55514,8 @@ function buildGeminiSessions(days, allAuditEntries) {
|
|
|
55205
55514
|
return summaries;
|
|
55206
55515
|
}
|
|
55207
55516
|
function buildCodexSessions(days, allAuditEntries) {
|
|
55208
|
-
const sessionsBase =
|
|
55209
|
-
if (!
|
|
55517
|
+
const sessionsBase = import_path62.default.join(import_os55.default.homedir(), ".codex", "sessions");
|
|
55518
|
+
if (!import_fs65.default.existsSync(sessionsBase)) return [];
|
|
55210
55519
|
const cutoff = days !== null ? (() => {
|
|
55211
55520
|
const d = /* @__PURE__ */ new Date();
|
|
55212
55521
|
d.setDate(d.getDate() - days);
|
|
@@ -55215,29 +55524,29 @@ function buildCodexSessions(days, allAuditEntries) {
|
|
|
55215
55524
|
})() : null;
|
|
55216
55525
|
const jsonlFiles = [];
|
|
55217
55526
|
try {
|
|
55218
|
-
for (const year of
|
|
55219
|
-
const yearPath =
|
|
55527
|
+
for (const year of import_fs65.default.readdirSync(sessionsBase)) {
|
|
55528
|
+
const yearPath = import_path62.default.join(sessionsBase, year);
|
|
55220
55529
|
try {
|
|
55221
|
-
if (!
|
|
55530
|
+
if (!import_fs65.default.statSync(yearPath).isDirectory()) continue;
|
|
55222
55531
|
} catch {
|
|
55223
55532
|
continue;
|
|
55224
55533
|
}
|
|
55225
|
-
for (const month of
|
|
55226
|
-
const monthPath =
|
|
55534
|
+
for (const month of import_fs65.default.readdirSync(yearPath)) {
|
|
55535
|
+
const monthPath = import_path62.default.join(yearPath, month);
|
|
55227
55536
|
try {
|
|
55228
|
-
if (!
|
|
55537
|
+
if (!import_fs65.default.statSync(monthPath).isDirectory()) continue;
|
|
55229
55538
|
} catch {
|
|
55230
55539
|
continue;
|
|
55231
55540
|
}
|
|
55232
|
-
for (const day of
|
|
55233
|
-
const dayPath =
|
|
55541
|
+
for (const day of import_fs65.default.readdirSync(monthPath)) {
|
|
55542
|
+
const dayPath = import_path62.default.join(monthPath, day);
|
|
55234
55543
|
try {
|
|
55235
|
-
if (!
|
|
55544
|
+
if (!import_fs65.default.statSync(dayPath).isDirectory()) continue;
|
|
55236
55545
|
} catch {
|
|
55237
55546
|
continue;
|
|
55238
55547
|
}
|
|
55239
|
-
for (const file of
|
|
55240
|
-
if (file.endsWith(".jsonl")) jsonlFiles.push(
|
|
55548
|
+
for (const file of import_fs65.default.readdirSync(dayPath)) {
|
|
55549
|
+
if (file.endsWith(".jsonl")) jsonlFiles.push(import_path62.default.join(dayPath, file));
|
|
55241
55550
|
}
|
|
55242
55551
|
}
|
|
55243
55552
|
}
|
|
@@ -55249,7 +55558,7 @@ function buildCodexSessions(days, allAuditEntries) {
|
|
|
55249
55558
|
for (const filePath of jsonlFiles) {
|
|
55250
55559
|
let lines;
|
|
55251
55560
|
try {
|
|
55252
|
-
lines =
|
|
55561
|
+
lines = import_fs65.default.readFileSync(filePath, "utf-8").split("\n");
|
|
55253
55562
|
} catch {
|
|
55254
55563
|
continue;
|
|
55255
55564
|
}
|
|
@@ -55335,10 +55644,10 @@ function buildCodexSessions(days, allAuditEntries) {
|
|
|
55335
55644
|
return summaries;
|
|
55336
55645
|
}
|
|
55337
55646
|
function buildSessions(days, historyPath) {
|
|
55338
|
-
const hPath = historyPath ??
|
|
55647
|
+
const hPath = historyPath ?? import_path62.default.join(import_os55.default.homedir(), ".claude", "history.jsonl");
|
|
55339
55648
|
let historyRaw = "";
|
|
55340
55649
|
try {
|
|
55341
|
-
historyRaw =
|
|
55650
|
+
historyRaw = import_fs65.default.readFileSync(hPath, "utf-8");
|
|
55342
55651
|
} catch {
|
|
55343
55652
|
}
|
|
55344
55653
|
const cutoff = days !== null ? (() => {
|
|
@@ -55362,7 +55671,7 @@ function buildSessions(days, historyPath) {
|
|
|
55362
55671
|
const jsonlFile = sessionJsonlPath(entry.project, entry.sessionId);
|
|
55363
55672
|
let sessionLines = [];
|
|
55364
55673
|
try {
|
|
55365
|
-
sessionLines =
|
|
55674
|
+
sessionLines = import_fs65.default.readFileSync(jsonlFile, "utf-8").split("\n");
|
|
55366
55675
|
} catch {
|
|
55367
55676
|
}
|
|
55368
55677
|
const { toolCalls, costUSD, hasSnapshot, modifiedFiles } = parseSessionLines(sessionLines);
|
|
@@ -55756,12 +56065,12 @@ function registerSessionTaintCommand(program2) {
|
|
|
55756
56065
|
|
|
55757
56066
|
// src/cli/commands/skill-pin.ts
|
|
55758
56067
|
var import_chalk36 = __toESM(require("chalk"));
|
|
55759
|
-
var
|
|
55760
|
-
var
|
|
55761
|
-
var
|
|
56068
|
+
var import_fs66 = __toESM(require("fs"));
|
|
56069
|
+
var import_os56 = __toESM(require("os"));
|
|
56070
|
+
var import_path63 = __toESM(require("path"));
|
|
55762
56071
|
function wipeSkillSessions() {
|
|
55763
56072
|
try {
|
|
55764
|
-
|
|
56073
|
+
import_fs66.default.rmSync(import_path63.default.join(import_os56.default.homedir(), ".node9", "skill-sessions"), {
|
|
55765
56074
|
recursive: true,
|
|
55766
56075
|
force: true
|
|
55767
56076
|
});
|
|
@@ -55843,15 +56152,15 @@ function registerSkillPinCommand(program2) {
|
|
|
55843
56152
|
}
|
|
55844
56153
|
|
|
55845
56154
|
// src/cli/commands/decisions.ts
|
|
55846
|
-
var
|
|
55847
|
-
var
|
|
55848
|
-
var
|
|
56155
|
+
var import_fs67 = __toESM(require("fs"));
|
|
56156
|
+
var import_os57 = __toESM(require("os"));
|
|
56157
|
+
var import_path64 = __toESM(require("path"));
|
|
55849
56158
|
var import_chalk37 = __toESM(require("chalk"));
|
|
55850
|
-
var DECISIONS_FILE2 =
|
|
56159
|
+
var DECISIONS_FILE2 = import_path64.default.join(import_os57.default.homedir(), ".node9", "decisions.json");
|
|
55851
56160
|
function readDecisions() {
|
|
55852
56161
|
try {
|
|
55853
|
-
if (!
|
|
55854
|
-
const raw =
|
|
56162
|
+
if (!import_fs67.default.existsSync(DECISIONS_FILE2)) return {};
|
|
56163
|
+
const raw = import_fs67.default.readFileSync(DECISIONS_FILE2, "utf-8");
|
|
55855
56164
|
const parsed = JSON.parse(raw);
|
|
55856
56165
|
const out = {};
|
|
55857
56166
|
for (const [k, v] of Object.entries(parsed)) {
|
|
@@ -55863,11 +56172,11 @@ function readDecisions() {
|
|
|
55863
56172
|
}
|
|
55864
56173
|
}
|
|
55865
56174
|
function writeDecisions(d) {
|
|
55866
|
-
const dir =
|
|
55867
|
-
if (!
|
|
56175
|
+
const dir = import_path64.default.dirname(DECISIONS_FILE2);
|
|
56176
|
+
if (!import_fs67.default.existsSync(dir)) import_fs67.default.mkdirSync(dir, { recursive: true });
|
|
55868
56177
|
const tmp = `${DECISIONS_FILE2}.${process.pid}.tmp`;
|
|
55869
|
-
|
|
55870
|
-
|
|
56178
|
+
import_fs67.default.writeFileSync(tmp, JSON.stringify(d, null, 2));
|
|
56179
|
+
import_fs67.default.renameSync(tmp, DECISIONS_FILE2);
|
|
55871
56180
|
}
|
|
55872
56181
|
function registerDecisionsCommand(program2) {
|
|
55873
56182
|
const cmd = program2.command("decisions").description('Manage persistent "Always Allow" / "Always Deny" tool decisions');
|
|
@@ -55924,18 +56233,18 @@ Persistent decisions (${entries.length})
|
|
|
55924
56233
|
|
|
55925
56234
|
// src/cli/commands/dlp.ts
|
|
55926
56235
|
var import_chalk38 = __toESM(require("chalk"));
|
|
55927
|
-
var
|
|
55928
|
-
var
|
|
55929
|
-
var
|
|
55930
|
-
var AUDIT_LOG =
|
|
55931
|
-
var RESOLVED_FILE =
|
|
56236
|
+
var import_fs68 = __toESM(require("fs"));
|
|
56237
|
+
var import_path65 = __toESM(require("path"));
|
|
56238
|
+
var import_os58 = __toESM(require("os"));
|
|
56239
|
+
var AUDIT_LOG = import_path65.default.join(import_os58.default.homedir(), ".node9", "audit.log");
|
|
56240
|
+
var RESOLVED_FILE = import_path65.default.join(import_os58.default.homedir(), ".node9", "dlp-resolved.json");
|
|
55932
56241
|
var ANSI_RE = /\x1b(?:\[[0-9;?]*[a-zA-Z]|\][^\x07\x1b]*(?:\x07|\x1b\\)|[@-_])/g;
|
|
55933
56242
|
function stripAnsi(s) {
|
|
55934
56243
|
return s.replace(ANSI_RE, "");
|
|
55935
56244
|
}
|
|
55936
56245
|
function loadResolved() {
|
|
55937
56246
|
try {
|
|
55938
|
-
const raw = JSON.parse(
|
|
56247
|
+
const raw = JSON.parse(import_fs68.default.readFileSync(RESOLVED_FILE, "utf-8"));
|
|
55939
56248
|
return new Set(raw);
|
|
55940
56249
|
} catch {
|
|
55941
56250
|
return /* @__PURE__ */ new Set();
|
|
@@ -55943,13 +56252,13 @@ function loadResolved() {
|
|
|
55943
56252
|
}
|
|
55944
56253
|
function saveResolved(resolved) {
|
|
55945
56254
|
try {
|
|
55946
|
-
|
|
56255
|
+
import_fs68.default.writeFileSync(RESOLVED_FILE, JSON.stringify([...resolved], null, 2), { mode: 384 });
|
|
55947
56256
|
} catch {
|
|
55948
56257
|
}
|
|
55949
56258
|
}
|
|
55950
56259
|
function loadDlpFindings() {
|
|
55951
|
-
if (!
|
|
55952
|
-
return
|
|
56260
|
+
if (!import_fs68.default.existsSync(AUDIT_LOG)) return [];
|
|
56261
|
+
return import_fs68.default.readFileSync(AUDIT_LOG, "utf-8").split("\n").flatMap((line) => {
|
|
55953
56262
|
if (!line.trim()) return [];
|
|
55954
56263
|
try {
|
|
55955
56264
|
const e = JSON.parse(line);
|
|
@@ -56047,15 +56356,15 @@ function registerDlpCommand(program2) {
|
|
|
56047
56356
|
|
|
56048
56357
|
// src/cli/commands/mask.ts
|
|
56049
56358
|
var import_chalk39 = __toESM(require("chalk"));
|
|
56050
|
-
var
|
|
56051
|
-
var
|
|
56052
|
-
var
|
|
56359
|
+
var import_fs69 = __toESM(require("fs"));
|
|
56360
|
+
var import_path66 = __toESM(require("path"));
|
|
56361
|
+
var import_os59 = __toESM(require("os"));
|
|
56053
56362
|
init_dlp();
|
|
56054
56363
|
function findJsonlFiles(dir) {
|
|
56055
56364
|
const results = [];
|
|
56056
|
-
if (!
|
|
56057
|
-
for (const entry of
|
|
56058
|
-
const full =
|
|
56365
|
+
if (!import_fs69.default.existsSync(dir)) return results;
|
|
56366
|
+
for (const entry of import_fs69.default.readdirSync(dir, { withFileTypes: true })) {
|
|
56367
|
+
const full = import_path66.default.join(dir, entry.name);
|
|
56059
56368
|
if (entry.isDirectory()) results.push(...findJsonlFiles(full));
|
|
56060
56369
|
else if (entry.isFile() && entry.name.endsWith(".jsonl")) results.push(full);
|
|
56061
56370
|
}
|
|
@@ -56098,7 +56407,7 @@ function redactJson(obj) {
|
|
|
56098
56407
|
function processFile(filePath, dryRun) {
|
|
56099
56408
|
let raw;
|
|
56100
56409
|
try {
|
|
56101
|
-
raw =
|
|
56410
|
+
raw = import_fs69.default.readFileSync(filePath, "utf-8");
|
|
56102
56411
|
} catch {
|
|
56103
56412
|
return { redactedLines: 0, patterns: [] };
|
|
56104
56413
|
}
|
|
@@ -56130,14 +56439,14 @@ function processFile(filePath, dryRun) {
|
|
|
56130
56439
|
}
|
|
56131
56440
|
}
|
|
56132
56441
|
if (!dryRun && redactedLines > 0) {
|
|
56133
|
-
|
|
56442
|
+
import_fs69.default.writeFileSync(filePath, newLines.join("\n"), "utf-8");
|
|
56134
56443
|
}
|
|
56135
56444
|
return { redactedLines, patterns };
|
|
56136
56445
|
}
|
|
56137
56446
|
function processJsonFile(filePath, dryRun) {
|
|
56138
56447
|
let raw;
|
|
56139
56448
|
try {
|
|
56140
|
-
raw =
|
|
56449
|
+
raw = import_fs69.default.readFileSync(filePath, "utf-8");
|
|
56141
56450
|
} catch {
|
|
56142
56451
|
return { redactedLines: 0, patterns: [] };
|
|
56143
56452
|
}
|
|
@@ -56150,15 +56459,15 @@ function processJsonFile(filePath, dryRun) {
|
|
|
56150
56459
|
const { value, modified, found } = redactJson(parsed);
|
|
56151
56460
|
if (!modified) return { redactedLines: 0, patterns: [] };
|
|
56152
56461
|
if (!dryRun) {
|
|
56153
|
-
|
|
56462
|
+
import_fs69.default.writeFileSync(filePath, JSON.stringify(value, null, 2), "utf-8");
|
|
56154
56463
|
}
|
|
56155
56464
|
return { redactedLines: 1, patterns: found };
|
|
56156
56465
|
}
|
|
56157
56466
|
function findJsonFiles(dir) {
|
|
56158
56467
|
const results = [];
|
|
56159
|
-
if (!
|
|
56160
|
-
for (const entry of
|
|
56161
|
-
const full =
|
|
56468
|
+
if (!import_fs69.default.existsSync(dir)) return results;
|
|
56469
|
+
for (const entry of import_fs69.default.readdirSync(dir, { withFileTypes: true })) {
|
|
56470
|
+
const full = import_path66.default.join(dir, entry.name);
|
|
56162
56471
|
if (entry.isDirectory()) results.push(...findJsonFiles(full));
|
|
56163
56472
|
else if (entry.isFile() && entry.name.endsWith(".json")) results.push(full);
|
|
56164
56473
|
}
|
|
@@ -56167,9 +56476,9 @@ function findJsonFiles(dir) {
|
|
|
56167
56476
|
function registerMaskCommand(program2) {
|
|
56168
56477
|
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) => {
|
|
56169
56478
|
const dryRun = !!options.dryRun;
|
|
56170
|
-
const home =
|
|
56171
|
-
const claudeDir =
|
|
56172
|
-
const geminiDir =
|
|
56479
|
+
const home = import_os59.default.homedir();
|
|
56480
|
+
const claudeDir = import_path66.default.join(home, ".claude", "projects");
|
|
56481
|
+
const geminiDir = import_path66.default.join(home, ".gemini", "tmp");
|
|
56173
56482
|
const allFiles = [
|
|
56174
56483
|
...findJsonlFiles(claudeDir).map((p) => ({ path: p, type: "jsonl" })),
|
|
56175
56484
|
...findJsonFiles(geminiDir).map((p) => ({ path: p, type: "json" }))
|
|
@@ -56177,7 +56486,7 @@ function registerMaskCommand(program2) {
|
|
|
56177
56486
|
const cutoff = options.all ? null : new Date(Date.now() - 30 * 24 * 60 * 60 * 1e3);
|
|
56178
56487
|
const filtered = cutoff ? allFiles.filter((f) => {
|
|
56179
56488
|
try {
|
|
56180
|
-
return
|
|
56489
|
+
return import_fs69.default.statSync(f.path).mtime >= cutoff;
|
|
56181
56490
|
} catch {
|
|
56182
56491
|
return false;
|
|
56183
56492
|
}
|
|
@@ -56233,7 +56542,7 @@ function registerMaskCommand(program2) {
|
|
|
56233
56542
|
// src/cli.ts
|
|
56234
56543
|
init_blast();
|
|
56235
56544
|
var { version } = JSON.parse(
|
|
56236
|
-
|
|
56545
|
+
import_fs72.default.readFileSync(import_path69.default.join(__dirname, "../package.json"), "utf-8")
|
|
56237
56546
|
);
|
|
56238
56547
|
var program = new import_commander.Command();
|
|
56239
56548
|
program.name("node9").description("The Sudo Command for AI Agents").version(version);
|
|
@@ -56259,6 +56568,11 @@ program.command("login").argument("<apiKey>").option("--local", "Save key for au
|
|
|
56259
56568
|
} else {
|
|
56260
56569
|
console.log(import_chalk41.default.green(`\u2705 Logged in \u2014 agent mode`));
|
|
56261
56570
|
console.log(import_chalk41.default.gray(` Team policy enforced for all calls via Node9 cloud.`));
|
|
56571
|
+
if (!isTestingMode()) {
|
|
56572
|
+
const healed = ensureAutostartHealthy(!!getConfig().settings.autoStartDaemon);
|
|
56573
|
+
if (healed === "repaired")
|
|
56574
|
+
console.log(import_chalk41.default.green(` \u2713 Re-enabled daemon autostart (survives reboot)`));
|
|
56575
|
+
}
|
|
56262
56576
|
}
|
|
56263
56577
|
});
|
|
56264
56578
|
program.command("signup").description("Create your node9 account / open the dashboard in your browser").option("--login", "Open the login page instead of signup").action((options) => {
|
|
@@ -56407,15 +56721,15 @@ program.command("uninstall").description("Remove all Node9 hooks and optionally
|
|
|
56407
56721
|
} catch {
|
|
56408
56722
|
}
|
|
56409
56723
|
if (options.purge) {
|
|
56410
|
-
const node9Dir =
|
|
56411
|
-
if (
|
|
56724
|
+
const node9Dir = import_path69.default.join(import_os62.default.homedir(), ".node9");
|
|
56725
|
+
if (import_fs72.default.existsSync(node9Dir)) {
|
|
56412
56726
|
const confirmed = await (0, import_prompts2.confirm)({
|
|
56413
56727
|
message: `Permanently delete ${node9Dir} (config, audit log, credentials)?`,
|
|
56414
56728
|
default: false
|
|
56415
56729
|
});
|
|
56416
56730
|
if (confirmed) {
|
|
56417
|
-
|
|
56418
|
-
if (
|
|
56731
|
+
import_fs72.default.rmSync(node9Dir, { recursive: true });
|
|
56732
|
+
if (import_fs72.default.existsSync(node9Dir)) {
|
|
56419
56733
|
console.error(
|
|
56420
56734
|
import_chalk41.default.red("\n \u26A0\uFE0F ~/.node9/ could not be fully deleted \u2014 remove it manually.")
|
|
56421
56735
|
);
|
|
@@ -56540,7 +56854,7 @@ program.command("tail").description("Stream live agent activity to the terminal"
|
|
|
56540
56854
|
});
|
|
56541
56855
|
program.command("monitor").description("Live interactive dashboard \u2014 activity feed, approvals, security signals").action(async () => {
|
|
56542
56856
|
try {
|
|
56543
|
-
const dashboardPath =
|
|
56857
|
+
const dashboardPath = import_path69.default.join(__dirname, "dashboard.mjs");
|
|
56544
56858
|
const dynamicImport = new Function("id", "return import(id)");
|
|
56545
56859
|
const mod = await dynamicImport(`file://${dashboardPath}`);
|
|
56546
56860
|
await mod.startMonitor();
|
|
@@ -56578,14 +56892,14 @@ Claude Code spawns this command every ~300ms and writes a JSON payload to stdin.
|
|
|
56578
56892
|
Run "node9 addto claude" to register it as the statusLine.`
|
|
56579
56893
|
).argument("[subcommand]", 'Optional: "debug on" / "debug off" to toggle stdin logging').argument("[state]", 'on|off \u2014 used with "debug" subcommand').action(async (subcommand, state) => {
|
|
56580
56894
|
if (subcommand === "debug") {
|
|
56581
|
-
const flagFile =
|
|
56895
|
+
const flagFile = import_path69.default.join(import_os62.default.homedir(), ".node9", "hud-debug");
|
|
56582
56896
|
if (state === "on") {
|
|
56583
|
-
|
|
56584
|
-
|
|
56897
|
+
import_fs72.default.mkdirSync(import_path69.default.dirname(flagFile), { recursive: true });
|
|
56898
|
+
import_fs72.default.writeFileSync(flagFile, "");
|
|
56585
56899
|
console.log("HUD debug logging enabled \u2192 ~/.node9/hud-debug.log");
|
|
56586
56900
|
console.log("Tail it with: tail -f ~/.node9/hud-debug.log");
|
|
56587
56901
|
} else if (state === "off") {
|
|
56588
|
-
if (
|
|
56902
|
+
if (import_fs72.default.existsSync(flagFile)) import_fs72.default.unlinkSync(flagFile);
|
|
56589
56903
|
console.log("HUD debug logging disabled.");
|
|
56590
56904
|
} else {
|
|
56591
56905
|
console.error("Usage: node9 hud debug on|off");
|
|
@@ -56708,9 +57022,9 @@ if (process.argv[2] !== "daemon") {
|
|
|
56708
57022
|
const isCheckHook = process.argv[2] === "check";
|
|
56709
57023
|
if (isCheckHook) {
|
|
56710
57024
|
if (process.env.NODE9_DEBUG === "1" || getConfig().settings.enableHookLogDebug) {
|
|
56711
|
-
const logPath =
|
|
57025
|
+
const logPath = import_path69.default.join(import_os62.default.homedir(), ".node9", "hook-debug.log");
|
|
56712
57026
|
const msg = reason instanceof Error ? reason.message : String(reason);
|
|
56713
|
-
|
|
57027
|
+
import_fs72.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] UNHANDLED: ${msg}
|
|
56714
57028
|
`);
|
|
56715
57029
|
}
|
|
56716
57030
|
process.exit(0);
|