@node9/proxy 1.35.0 → 1.35.2
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 +478 -467
- package/dist/cli.mjs +474 -463
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -206,8 +206,8 @@ function sanitizeConfig(raw) {
|
|
|
206
206
|
}
|
|
207
207
|
}
|
|
208
208
|
const lines = result.error.issues.map((issue) => {
|
|
209
|
-
const
|
|
210
|
-
return ` \u2022 ${
|
|
209
|
+
const path55 = issue.path.length > 0 ? issue.path.join(".") : "root";
|
|
210
|
+
return ` \u2022 ${path55}: ${issue.message}`;
|
|
211
211
|
});
|
|
212
212
|
return {
|
|
213
213
|
sanitized,
|
|
@@ -1256,9 +1256,9 @@ function matchesPattern(text, patterns) {
|
|
|
1256
1256
|
const withoutDotSlash = text.replace(/^\.\//, "");
|
|
1257
1257
|
return isMatch(withoutDotSlash) || isMatch(`./${withoutDotSlash}`);
|
|
1258
1258
|
}
|
|
1259
|
-
function getNestedValue(obj,
|
|
1259
|
+
function getNestedValue(obj, path55) {
|
|
1260
1260
|
if (!obj || typeof obj !== "object") return null;
|
|
1261
|
-
const segments =
|
|
1261
|
+
const segments = path55.split(".");
|
|
1262
1262
|
for (const seg of segments) {
|
|
1263
1263
|
if (FORBIDDEN_PATH_SEGMENTS.has(seg)) return null;
|
|
1264
1264
|
}
|
|
@@ -8154,7 +8154,7 @@ function binaryInPath(binary) {
|
|
|
8154
8154
|
return false;
|
|
8155
8155
|
}
|
|
8156
8156
|
function detectAgents(homeDir2 = import_os12.default.homedir()) {
|
|
8157
|
-
const
|
|
8157
|
+
const exists2 = (p) => {
|
|
8158
8158
|
try {
|
|
8159
8159
|
return import_fs13.default.existsSync(p);
|
|
8160
8160
|
} catch (err2) {
|
|
@@ -8168,7 +8168,7 @@ function detectAgents(homeDir2 = import_os12.default.homedir()) {
|
|
|
8168
8168
|
};
|
|
8169
8169
|
const desktopPath = claudeDesktopConfigPath(homeDir2);
|
|
8170
8170
|
return {
|
|
8171
|
-
claude:
|
|
8171
|
+
claude: exists2(import_path15.default.join(homeDir2, ".claude")) || exists2(import_path15.default.join(homeDir2, ".claude.json")),
|
|
8172
8172
|
// Antigravity (agy) shares the ~/.gemini root, so a bare
|
|
8173
8173
|
// `exists(~/.gemini)` would report the (EOL'd) Gemini CLI as
|
|
8174
8174
|
// installed on every agy machine — and `node9 init` would then
|
|
@@ -8178,35 +8178,35 @@ function detectAgents(homeDir2 = import_os12.default.homedir()) {
|
|
|
8178
8178
|
// creates ~/.gemini/settings.json on first run; agy does not touch
|
|
8179
8179
|
// it (it uses antigravity-cli/settings.json) — that file is the
|
|
8180
8180
|
// legacy-CLI discriminator.
|
|
8181
|
-
gemini:
|
|
8181
|
+
gemini: exists2(import_path15.default.join(homeDir2, ".gemini", "settings.json")) || binaryInPath("gemini"),
|
|
8182
8182
|
// agy creates ~/.gemini/antigravity-cli/ on first launch; the IDE
|
|
8183
8183
|
// creates antigravity-ide/. PATH fallback covers installed-but-
|
|
8184
8184
|
// never-launched (same class as opencode #186).
|
|
8185
|
-
antigravity:
|
|
8185
|
+
antigravity: exists2(import_path15.default.join(homeDir2, ".gemini", "antigravity-cli")) || exists2(import_path15.default.join(homeDir2, ".gemini", "antigravity-ide")) || binaryInPath("agy"),
|
|
8186
8186
|
// GitHub Copilot CLI creates ~/.copilot on first launch; PATH
|
|
8187
8187
|
// fallback covers installed-but-never-launched (same as opencode #186).
|
|
8188
|
-
copilot:
|
|
8189
|
-
cursor:
|
|
8190
|
-
codex:
|
|
8191
|
-
windsurf:
|
|
8192
|
-
vscode:
|
|
8193
|
-
claudeDesktop: desktopPath !== null &&
|
|
8188
|
+
copilot: exists2(import_path15.default.join(homeDir2, ".copilot")) || binaryInPath("copilot"),
|
|
8189
|
+
cursor: exists2(import_path15.default.join(homeDir2, ".cursor")),
|
|
8190
|
+
codex: exists2(import_path15.default.join(homeDir2, ".codex")),
|
|
8191
|
+
windsurf: exists2(import_path15.default.join(homeDir2, ".codeium", "windsurf")),
|
|
8192
|
+
vscode: exists2(import_path15.default.join(homeDir2, ".vscode")),
|
|
8193
|
+
claudeDesktop: desktopPath !== null && exists2(import_path15.default.dirname(desktopPath)),
|
|
8194
8194
|
// Opencode creates ~/.config/opencode lazily on first launch — fall back
|
|
8195
8195
|
// to a PATH lookup so installed-but-never-launched CLIs are still wired.
|
|
8196
|
-
opencode:
|
|
8196
|
+
opencode: exists2(import_path15.default.join(homeDir2, ".config", "opencode")) || binaryInPath("opencode"),
|
|
8197
8197
|
// Pi (https://pi.dev): config dir is ~/.pi/agent (CONFIG_DIR_NAME=".pi"
|
|
8198
8198
|
// + agentDir, verified against opensources/pi-main/packages/coding-agent/
|
|
8199
8199
|
// src/config.ts:449,475). The Bun-compiled binary path may create this
|
|
8200
8200
|
// dir lazily on first launch — same class of bug as opencode's #186
|
|
8201
8201
|
// (design R6) — so fall back to PATH lookup for installed-but-never-
|
|
8202
8202
|
// launched pi.
|
|
8203
|
-
pi:
|
|
8203
|
+
pi: exists2(import_path15.default.join(homeDir2, ".pi", "agent")) || binaryInPath("pi"),
|
|
8204
8204
|
// Hermes Agent (https://github.com/NousResearch/hermes-agent): home dir
|
|
8205
8205
|
// is $HERMES_HOME (default ~/.hermes) per hermes_constants.py:30. config.yaml
|
|
8206
8206
|
// appears after `hermes setup` has run; the directory alone exists from
|
|
8207
8207
|
// install time. PATH fallback covers the rare case where the user blew
|
|
8208
8208
|
// away ~/.hermes but kept the binary.
|
|
8209
|
-
hermes:
|
|
8209
|
+
hermes: exists2(hermesHomeDir(homeDir2)) || binaryInPath("hermes")
|
|
8210
8210
|
};
|
|
8211
8211
|
}
|
|
8212
8212
|
async function setupCursor() {
|
|
@@ -16951,20 +16951,20 @@ function getModelContextLimit(model) {
|
|
|
16951
16951
|
return 2e5;
|
|
16952
16952
|
}
|
|
16953
16953
|
function readSessionUsage() {
|
|
16954
|
-
const projectsDir =
|
|
16955
|
-
if (!
|
|
16954
|
+
const projectsDir = import_path52.default.join(import_os46.default.homedir(), ".claude", "projects");
|
|
16955
|
+
if (!import_fs51.default.existsSync(projectsDir)) return null;
|
|
16956
16956
|
let latestFile = null;
|
|
16957
16957
|
let latestMtime = 0;
|
|
16958
16958
|
try {
|
|
16959
|
-
for (const dir of
|
|
16960
|
-
const dirPath =
|
|
16959
|
+
for (const dir of import_fs51.default.readdirSync(projectsDir)) {
|
|
16960
|
+
const dirPath = import_path52.default.join(projectsDir, dir);
|
|
16961
16961
|
try {
|
|
16962
|
-
if (!
|
|
16963
|
-
for (const file of
|
|
16962
|
+
if (!import_fs51.default.statSync(dirPath).isDirectory()) continue;
|
|
16963
|
+
for (const file of import_fs51.default.readdirSync(dirPath)) {
|
|
16964
16964
|
if (!file.endsWith(".jsonl") || file.startsWith("agent-")) continue;
|
|
16965
|
-
const filePath =
|
|
16965
|
+
const filePath = import_path52.default.join(dirPath, file);
|
|
16966
16966
|
try {
|
|
16967
|
-
const mtime =
|
|
16967
|
+
const mtime = import_fs51.default.statSync(filePath).mtimeMs;
|
|
16968
16968
|
if (mtime > latestMtime) {
|
|
16969
16969
|
latestMtime = mtime;
|
|
16970
16970
|
latestFile = filePath;
|
|
@@ -16979,7 +16979,7 @@ function readSessionUsage() {
|
|
|
16979
16979
|
}
|
|
16980
16980
|
if (!latestFile) return null;
|
|
16981
16981
|
try {
|
|
16982
|
-
const lines =
|
|
16982
|
+
const lines = import_fs51.default.readFileSync(latestFile, "utf-8").split("\n");
|
|
16983
16983
|
let lastModel = "";
|
|
16984
16984
|
let lastInput = 0;
|
|
16985
16985
|
let lastOutput = 0;
|
|
@@ -17040,7 +17040,7 @@ function formatBase(activity) {
|
|
|
17040
17040
|
const time = new Date(activity.ts).toLocaleTimeString([], { hour12: false });
|
|
17041
17041
|
const icon = getIcon(activity.tool);
|
|
17042
17042
|
const toolName = activity.tool.slice(0, 16).padEnd(16);
|
|
17043
|
-
const argsStr = JSON.stringify(activity.args ?? {}).replace(/\s+/g, " ").replaceAll(
|
|
17043
|
+
const argsStr = JSON.stringify(activity.args ?? {}).replace(/\s+/g, " ").replaceAll(import_os46.default.homedir(), "~");
|
|
17044
17044
|
const argsPreview = argsStr.length > 70 ? argsStr.slice(0, 70) + "\u2026" : argsStr;
|
|
17045
17045
|
return `${import_chalk29.default.gray(time)} ${icon} ${agentLabel(activity.agent, activity.mcpServer, activity.sessionId)}${import_chalk29.default.white.bold(toolName)} ${import_chalk29.default.dim(argsPreview)}`;
|
|
17046
17046
|
}
|
|
@@ -17079,9 +17079,9 @@ function renderPending(activity) {
|
|
|
17079
17079
|
}
|
|
17080
17080
|
async function ensureDaemon() {
|
|
17081
17081
|
let pidPort = null;
|
|
17082
|
-
if (
|
|
17082
|
+
if (import_fs51.default.existsSync(PID_FILE)) {
|
|
17083
17083
|
try {
|
|
17084
|
-
const { port } = JSON.parse(
|
|
17084
|
+
const { port } = JSON.parse(import_fs51.default.readFileSync(PID_FILE, "utf-8"));
|
|
17085
17085
|
pidPort = port;
|
|
17086
17086
|
} catch {
|
|
17087
17087
|
console.error(import_chalk29.default.dim("\u26A0\uFE0F Could not read PID file; falling back to default port."));
|
|
@@ -17237,9 +17237,9 @@ function buildRecoveryCardLines(req) {
|
|
|
17237
17237
|
];
|
|
17238
17238
|
}
|
|
17239
17239
|
function readApproversFromDisk() {
|
|
17240
|
-
const configPath =
|
|
17240
|
+
const configPath = import_path52.default.join(import_os46.default.homedir(), ".node9", "config.json");
|
|
17241
17241
|
try {
|
|
17242
|
-
const raw = JSON.parse(
|
|
17242
|
+
const raw = JSON.parse(import_fs51.default.readFileSync(configPath, "utf-8"));
|
|
17243
17243
|
const settings = raw.settings ?? {};
|
|
17244
17244
|
return settings.approvers ?? {};
|
|
17245
17245
|
} catch {
|
|
@@ -17255,15 +17255,15 @@ function approverStatusLine() {
|
|
|
17255
17255
|
return `${fmt("native", "native")} ${fmt("cloud", "cloud")} ${fmt("terminal", "terminal")}`;
|
|
17256
17256
|
}
|
|
17257
17257
|
function toggleApprover(channel) {
|
|
17258
|
-
const configPath =
|
|
17258
|
+
const configPath = import_path52.default.join(import_os46.default.homedir(), ".node9", "config.json");
|
|
17259
17259
|
try {
|
|
17260
|
-
const raw = JSON.parse(
|
|
17260
|
+
const raw = JSON.parse(import_fs51.default.readFileSync(configPath, "utf-8"));
|
|
17261
17261
|
const settings = raw.settings ?? {};
|
|
17262
17262
|
const approvers = settings.approvers ?? {};
|
|
17263
17263
|
approvers[channel] = approvers[channel] === false;
|
|
17264
17264
|
settings.approvers = approvers;
|
|
17265
17265
|
raw.settings = settings;
|
|
17266
|
-
|
|
17266
|
+
import_fs51.default.writeFileSync(configPath, JSON.stringify(raw, null, 2) + "\n");
|
|
17267
17267
|
} catch (err2) {
|
|
17268
17268
|
process.stderr.write(`[node9] toggleApprover failed: ${String(err2)}
|
|
17269
17269
|
`);
|
|
@@ -17435,8 +17435,8 @@ async function startTail(options = {}) {
|
|
|
17435
17435
|
}
|
|
17436
17436
|
postDecisionHttp(req2.id, httpDecision, authToken, port, httpOpts).catch((err2) => {
|
|
17437
17437
|
try {
|
|
17438
|
-
|
|
17439
|
-
|
|
17438
|
+
import_fs51.default.appendFileSync(
|
|
17439
|
+
import_path52.default.join(import_os46.default.homedir(), ".node9", "hook-debug.log"),
|
|
17440
17440
|
`[tail] POST /decision failed: ${String(err2)}
|
|
17441
17441
|
`
|
|
17442
17442
|
);
|
|
@@ -17500,9 +17500,9 @@ async function startTail(options = {}) {
|
|
|
17500
17500
|
};
|
|
17501
17501
|
process.stdin.on("keypress", onKeypress);
|
|
17502
17502
|
}
|
|
17503
|
-
const auditLog =
|
|
17503
|
+
const auditLog = import_path52.default.join(import_os46.default.homedir(), ".node9", "audit.log");
|
|
17504
17504
|
try {
|
|
17505
|
-
const unackedDlp =
|
|
17505
|
+
const unackedDlp = import_fs51.default.readFileSync(auditLog, "utf-8").split("\n").filter((l) => l.includes('"response-dlp"')).length;
|
|
17506
17506
|
if (unackedDlp > 0) {
|
|
17507
17507
|
console.log("");
|
|
17508
17508
|
console.log(
|
|
@@ -17542,7 +17542,7 @@ async function startTail(options = {}) {
|
|
|
17542
17542
|
if (stallWarned) return;
|
|
17543
17543
|
if (Date.now() - lastActivityFromDaemon < STALL_THRESHOLD_MS) return;
|
|
17544
17544
|
try {
|
|
17545
|
-
const auditMtime =
|
|
17545
|
+
const auditMtime = import_fs51.default.statSync(auditLog).mtimeMs;
|
|
17546
17546
|
if (Date.now() - auditMtime >= STALL_THRESHOLD_MS) return;
|
|
17547
17547
|
console.log("");
|
|
17548
17548
|
console.log(
|
|
@@ -17727,20 +17727,20 @@ async function startTail(options = {}) {
|
|
|
17727
17727
|
process.exit(1);
|
|
17728
17728
|
});
|
|
17729
17729
|
}
|
|
17730
|
-
var import_http2, import_chalk29,
|
|
17730
|
+
var import_http2, import_chalk29, import_fs51, import_os46, import_path52, import_readline6, import_child_process12, PID_FILE, ICONS, MODEL_CONTEXT_LIMITS, RESET2, BOLD2, RED, YELLOW, CYAN, GRAY, GREEN, HIDE_CURSOR, SHOW_CURSOR, ERASE_DOWN, pendingShownForId, pendingWrappedLines, DIVIDER;
|
|
17731
17731
|
var init_tail = __esm({
|
|
17732
17732
|
"src/tui/tail.ts"() {
|
|
17733
17733
|
"use strict";
|
|
17734
17734
|
import_http2 = __toESM(require("http"));
|
|
17735
17735
|
import_chalk29 = __toESM(require("chalk"));
|
|
17736
|
-
|
|
17737
|
-
|
|
17738
|
-
|
|
17736
|
+
import_fs51 = __toESM(require("fs"));
|
|
17737
|
+
import_os46 = __toESM(require("os"));
|
|
17738
|
+
import_path52 = __toESM(require("path"));
|
|
17739
17739
|
import_readline6 = __toESM(require("readline"));
|
|
17740
17740
|
import_child_process12 = require("child_process");
|
|
17741
17741
|
init_daemon2();
|
|
17742
17742
|
init_daemon();
|
|
17743
|
-
PID_FILE =
|
|
17743
|
+
PID_FILE = import_path52.default.join(import_os46.default.homedir(), ".node9", "daemon.pid");
|
|
17744
17744
|
ICONS = {
|
|
17745
17745
|
bash: "\u{1F4BB}",
|
|
17746
17746
|
shell: "\u{1F4BB}",
|
|
@@ -17862,9 +17862,9 @@ function formatTimeLeft(resetsAt) {
|
|
|
17862
17862
|
return ` (${m}m left)`;
|
|
17863
17863
|
}
|
|
17864
17864
|
function safeReadJson(filePath) {
|
|
17865
|
-
if (!
|
|
17865
|
+
if (!import_fs52.default.existsSync(filePath)) return null;
|
|
17866
17866
|
try {
|
|
17867
|
-
return JSON.parse(
|
|
17867
|
+
return JSON.parse(import_fs52.default.readFileSync(filePath, "utf-8"));
|
|
17868
17868
|
} catch {
|
|
17869
17869
|
return null;
|
|
17870
17870
|
}
|
|
@@ -17885,12 +17885,12 @@ function countHooksInFile(filePath) {
|
|
|
17885
17885
|
return Object.keys(cfg.hooks).length;
|
|
17886
17886
|
}
|
|
17887
17887
|
function countRulesInDir(rulesDir) {
|
|
17888
|
-
if (!
|
|
17888
|
+
if (!import_fs52.default.existsSync(rulesDir)) return 0;
|
|
17889
17889
|
let count = 0;
|
|
17890
17890
|
try {
|
|
17891
|
-
for (const entry of
|
|
17891
|
+
for (const entry of import_fs52.default.readdirSync(rulesDir, { withFileTypes: true })) {
|
|
17892
17892
|
if (entry.isDirectory()) {
|
|
17893
|
-
count += countRulesInDir(
|
|
17893
|
+
count += countRulesInDir(import_path53.default.join(rulesDir, entry.name));
|
|
17894
17894
|
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
17895
17895
|
count++;
|
|
17896
17896
|
}
|
|
@@ -17901,46 +17901,46 @@ function countRulesInDir(rulesDir) {
|
|
|
17901
17901
|
}
|
|
17902
17902
|
function isSamePath(a, b) {
|
|
17903
17903
|
try {
|
|
17904
|
-
return
|
|
17904
|
+
return import_path53.default.resolve(a) === import_path53.default.resolve(b);
|
|
17905
17905
|
} catch {
|
|
17906
17906
|
return false;
|
|
17907
17907
|
}
|
|
17908
17908
|
}
|
|
17909
17909
|
function countConfigs(cwd) {
|
|
17910
|
-
const homeDir2 =
|
|
17911
|
-
const claudeDir =
|
|
17910
|
+
const homeDir2 = import_os47.default.homedir();
|
|
17911
|
+
const claudeDir = import_path53.default.join(homeDir2, ".claude");
|
|
17912
17912
|
let claudeMdCount = 0;
|
|
17913
17913
|
let rulesCount = 0;
|
|
17914
17914
|
let hooksCount = 0;
|
|
17915
17915
|
const userMcpServers = /* @__PURE__ */ new Set();
|
|
17916
17916
|
const projectMcpServers = /* @__PURE__ */ new Set();
|
|
17917
|
-
if (
|
|
17918
|
-
rulesCount += countRulesInDir(
|
|
17919
|
-
const userSettings =
|
|
17917
|
+
if (import_fs52.default.existsSync(import_path53.default.join(claudeDir, "CLAUDE.md"))) claudeMdCount++;
|
|
17918
|
+
rulesCount += countRulesInDir(import_path53.default.join(claudeDir, "rules"));
|
|
17919
|
+
const userSettings = import_path53.default.join(claudeDir, "settings.json");
|
|
17920
17920
|
for (const name of getMcpServerNames(userSettings)) userMcpServers.add(name);
|
|
17921
17921
|
hooksCount += countHooksInFile(userSettings);
|
|
17922
|
-
const userClaudeJson =
|
|
17922
|
+
const userClaudeJson = import_path53.default.join(homeDir2, ".claude.json");
|
|
17923
17923
|
for (const name of getMcpServerNames(userClaudeJson)) userMcpServers.add(name);
|
|
17924
17924
|
for (const name of getDisabledMcpServers(userClaudeJson, "disabledMcpServers")) {
|
|
17925
17925
|
userMcpServers.delete(name);
|
|
17926
17926
|
}
|
|
17927
17927
|
if (cwd) {
|
|
17928
|
-
if (
|
|
17929
|
-
if (
|
|
17930
|
-
const projectClaudeDir =
|
|
17928
|
+
if (import_fs52.default.existsSync(import_path53.default.join(cwd, "CLAUDE.md"))) claudeMdCount++;
|
|
17929
|
+
if (import_fs52.default.existsSync(import_path53.default.join(cwd, "CLAUDE.local.md"))) claudeMdCount++;
|
|
17930
|
+
const projectClaudeDir = import_path53.default.join(cwd, ".claude");
|
|
17931
17931
|
const overlapsUserScope = isSamePath(projectClaudeDir, claudeDir);
|
|
17932
17932
|
if (!overlapsUserScope) {
|
|
17933
|
-
if (
|
|
17934
|
-
rulesCount += countRulesInDir(
|
|
17935
|
-
const projSettings =
|
|
17933
|
+
if (import_fs52.default.existsSync(import_path53.default.join(projectClaudeDir, "CLAUDE.md"))) claudeMdCount++;
|
|
17934
|
+
rulesCount += countRulesInDir(import_path53.default.join(projectClaudeDir, "rules"));
|
|
17935
|
+
const projSettings = import_path53.default.join(projectClaudeDir, "settings.json");
|
|
17936
17936
|
for (const name of getMcpServerNames(projSettings)) projectMcpServers.add(name);
|
|
17937
17937
|
hooksCount += countHooksInFile(projSettings);
|
|
17938
17938
|
}
|
|
17939
|
-
if (
|
|
17940
|
-
const localSettings =
|
|
17939
|
+
if (import_fs52.default.existsSync(import_path53.default.join(projectClaudeDir, "CLAUDE.local.md"))) claudeMdCount++;
|
|
17940
|
+
const localSettings = import_path53.default.join(projectClaudeDir, "settings.local.json");
|
|
17941
17941
|
for (const name of getMcpServerNames(localSettings)) projectMcpServers.add(name);
|
|
17942
17942
|
hooksCount += countHooksInFile(localSettings);
|
|
17943
|
-
const mcpJsonServers = getMcpServerNames(
|
|
17943
|
+
const mcpJsonServers = getMcpServerNames(import_path53.default.join(cwd, ".mcp.json"));
|
|
17944
17944
|
const disabledMcpJson = getDisabledMcpServers(localSettings, "disabledMcpjsonServers");
|
|
17945
17945
|
for (const name of disabledMcpJson) mcpJsonServers.delete(name);
|
|
17946
17946
|
for (const name of mcpJsonServers) projectMcpServers.add(name);
|
|
@@ -17973,12 +17973,12 @@ function readActiveShieldsHud() {
|
|
|
17973
17973
|
return shieldsCache.value;
|
|
17974
17974
|
}
|
|
17975
17975
|
try {
|
|
17976
|
-
const shieldsPath =
|
|
17977
|
-
if (!
|
|
17976
|
+
const shieldsPath = import_path53.default.join(import_os47.default.homedir(), ".node9", "shields.json");
|
|
17977
|
+
if (!import_fs52.default.existsSync(shieldsPath)) {
|
|
17978
17978
|
shieldsCache = { value: [], ts: now };
|
|
17979
17979
|
return [];
|
|
17980
17980
|
}
|
|
17981
|
-
const parsed = JSON.parse(
|
|
17981
|
+
const parsed = JSON.parse(import_fs52.default.readFileSync(shieldsPath, "utf-8"));
|
|
17982
17982
|
if (!Array.isArray(parsed.active)) {
|
|
17983
17983
|
shieldsCache = { value: [], ts: now };
|
|
17984
17984
|
return [];
|
|
@@ -18080,17 +18080,17 @@ function renderContextLine(stdin) {
|
|
|
18080
18080
|
async function main() {
|
|
18081
18081
|
try {
|
|
18082
18082
|
const [stdin, daemonStatus2] = await Promise.all([readStdin(), queryDaemon()]);
|
|
18083
|
-
if (
|
|
18083
|
+
if (import_fs52.default.existsSync(import_path53.default.join(import_os47.default.homedir(), ".node9", "hud-debug"))) {
|
|
18084
18084
|
try {
|
|
18085
|
-
const logPath =
|
|
18085
|
+
const logPath = import_path53.default.join(import_os47.default.homedir(), ".node9", "hud-debug.log");
|
|
18086
18086
|
const MAX_LOG_SIZE = 10 * 1024 * 1024;
|
|
18087
18087
|
let size = 0;
|
|
18088
18088
|
try {
|
|
18089
|
-
size =
|
|
18089
|
+
size = import_fs52.default.statSync(logPath).size;
|
|
18090
18090
|
} catch {
|
|
18091
18091
|
}
|
|
18092
18092
|
if (size < MAX_LOG_SIZE) {
|
|
18093
|
-
|
|
18093
|
+
import_fs52.default.appendFileSync(
|
|
18094
18094
|
logPath,
|
|
18095
18095
|
JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), stdin }) + "\n"
|
|
18096
18096
|
);
|
|
@@ -18111,11 +18111,11 @@ async function main() {
|
|
|
18111
18111
|
try {
|
|
18112
18112
|
const cwd = stdin.cwd ?? process.cwd();
|
|
18113
18113
|
for (const configPath of [
|
|
18114
|
-
|
|
18115
|
-
|
|
18114
|
+
import_path53.default.join(cwd, "node9.config.json"),
|
|
18115
|
+
import_path53.default.join(import_os47.default.homedir(), ".node9", "config.json")
|
|
18116
18116
|
]) {
|
|
18117
|
-
if (!
|
|
18118
|
-
const cfg = JSON.parse(
|
|
18117
|
+
if (!import_fs52.default.existsSync(configPath)) continue;
|
|
18118
|
+
const cfg = JSON.parse(import_fs52.default.readFileSync(configPath, "utf-8"));
|
|
18119
18119
|
const hud = cfg.settings?.hud;
|
|
18120
18120
|
if (hud && "showEnvironmentCounts" in hud) return hud.showEnvironmentCounts !== false;
|
|
18121
18121
|
}
|
|
@@ -18133,13 +18133,13 @@ async function main() {
|
|
|
18133
18133
|
renderOffline();
|
|
18134
18134
|
}
|
|
18135
18135
|
}
|
|
18136
|
-
var
|
|
18136
|
+
var import_fs52, import_path53, import_os47, import_http3, RESET3, BOLD3, DIM, RED2, GREEN2, YELLOW2, BLUE, MAGENTA, CYAN2, WHITE, BAR_FILLED, BAR_EMPTY, BAR_WIDTH, shieldsCache, SHIELDS_CACHE_TTL_MS;
|
|
18137
18137
|
var init_hud = __esm({
|
|
18138
18138
|
"src/cli/hud.ts"() {
|
|
18139
18139
|
"use strict";
|
|
18140
|
-
|
|
18141
|
-
|
|
18142
|
-
|
|
18140
|
+
import_fs52 = __toESM(require("fs"));
|
|
18141
|
+
import_path53 = __toESM(require("path"));
|
|
18142
|
+
import_os47 = __toESM(require("os"));
|
|
18143
18143
|
import_http3 = __toESM(require("http"));
|
|
18144
18144
|
init_daemon();
|
|
18145
18145
|
RESET3 = "\x1B[0m";
|
|
@@ -18166,9 +18166,9 @@ init_core();
|
|
|
18166
18166
|
init_setup();
|
|
18167
18167
|
init_daemon2();
|
|
18168
18168
|
var import_chalk30 = __toESM(require("chalk"));
|
|
18169
|
-
var
|
|
18170
|
-
var
|
|
18171
|
-
var
|
|
18169
|
+
var import_fs53 = __toESM(require("fs"));
|
|
18170
|
+
var import_path54 = __toESM(require("path"));
|
|
18171
|
+
var import_os48 = __toESM(require("os"));
|
|
18172
18172
|
var import_prompts2 = require("@inquirer/prompts");
|
|
18173
18173
|
|
|
18174
18174
|
// src/utils/duration.ts
|
|
@@ -19956,15 +19956,184 @@ function registerConfigShowCommand(program2) {
|
|
|
19956
19956
|
|
|
19957
19957
|
// src/cli/commands/doctor.ts
|
|
19958
19958
|
var import_chalk11 = __toESM(require("chalk"));
|
|
19959
|
-
var
|
|
19960
|
-
var
|
|
19961
|
-
var
|
|
19959
|
+
var import_fs39 = __toESM(require("fs"));
|
|
19960
|
+
var import_path40 = __toESM(require("path"));
|
|
19961
|
+
var import_os35 = __toESM(require("os"));
|
|
19962
19962
|
var import_child_process8 = require("child_process");
|
|
19963
19963
|
init_daemon();
|
|
19964
19964
|
init_config();
|
|
19965
|
+
|
|
19966
|
+
// src/agent-wiring.ts
|
|
19967
|
+
var import_fs38 = __toESM(require("fs"));
|
|
19968
|
+
var import_path39 = __toESM(require("path"));
|
|
19969
|
+
var import_os34 = __toESM(require("os"));
|
|
19970
|
+
var yaml2 = __toESM(require("yaml"));
|
|
19971
|
+
init_setup();
|
|
19972
|
+
function readJson2(filePath) {
|
|
19973
|
+
if (!import_fs38.default.existsSync(filePath)) return null;
|
|
19974
|
+
try {
|
|
19975
|
+
return JSON.parse(import_fs38.default.readFileSync(filePath, "utf-8"));
|
|
19976
|
+
} catch {
|
|
19977
|
+
return "invalid";
|
|
19978
|
+
}
|
|
19979
|
+
}
|
|
19980
|
+
function matchersHaveNode9Hook(matchers) {
|
|
19981
|
+
return (matchers ?? []).some((m) => (m.hooks ?? []).some((h) => isNode9Hook(h.command)));
|
|
19982
|
+
}
|
|
19983
|
+
function flatHaveNode9Hook(entries) {
|
|
19984
|
+
return (Array.isArray(entries) ? entries : []).some((h) => isNode9Hook(h.command));
|
|
19985
|
+
}
|
|
19986
|
+
function readHookRoot(filePath, format) {
|
|
19987
|
+
if (!import_fs38.default.existsSync(filePath)) return "absent";
|
|
19988
|
+
let raw;
|
|
19989
|
+
try {
|
|
19990
|
+
raw = import_fs38.default.readFileSync(filePath, "utf-8");
|
|
19991
|
+
} catch {
|
|
19992
|
+
return "absent";
|
|
19993
|
+
}
|
|
19994
|
+
try {
|
|
19995
|
+
const parsed = format === "yaml" ? yaml2.parse(raw) : JSON.parse(raw);
|
|
19996
|
+
return parsed?.hooks ?? {};
|
|
19997
|
+
} catch {
|
|
19998
|
+
return "invalid";
|
|
19999
|
+
}
|
|
20000
|
+
}
|
|
20001
|
+
function eventWired(root, ev, format) {
|
|
20002
|
+
const arr = root[ev.key];
|
|
20003
|
+
if (format === "matcher") return matchersHaveNode9Hook(arr);
|
|
20004
|
+
return flatHaveNode9Hook(arr);
|
|
20005
|
+
}
|
|
20006
|
+
function readMcp(filePath) {
|
|
20007
|
+
const parsed = readJson2(filePath);
|
|
20008
|
+
if (parsed === null || parsed === "invalid") return { wrapped: [], present: false };
|
|
20009
|
+
const servers = parsed.mcpServers ?? {};
|
|
20010
|
+
const entries = Object.entries(servers);
|
|
20011
|
+
const present = entries.some(([, s]) => s?.command === "node9");
|
|
20012
|
+
const wrapped = entries.filter(([, s]) => s?.command === "node9" && Array.isArray(s.args) && s.args.length > 0).map(([name, s]) => `${name} \u2192 ${s.args.join(" ")}`);
|
|
20013
|
+
return { wrapped, present };
|
|
20014
|
+
}
|
|
20015
|
+
var exists = (p) => {
|
|
20016
|
+
try {
|
|
20017
|
+
return import_fs38.default.existsSync(p);
|
|
20018
|
+
} catch {
|
|
20019
|
+
return false;
|
|
20020
|
+
}
|
|
20021
|
+
};
|
|
20022
|
+
var ck = (key) => ({ key, kind: "check" });
|
|
20023
|
+
var lg = (key) => ({ key, kind: "log" });
|
|
20024
|
+
var DEFAULT_LABEL_PAD = 11;
|
|
20025
|
+
var hookLabelOf = (ev, pad) => `${ev.key.padEnd(pad)} (node9 ${ev.kind})`;
|
|
20026
|
+
var AGENT_SPECS = [
|
|
20027
|
+
{
|
|
20028
|
+
id: "claude",
|
|
20029
|
+
label: "Claude Code",
|
|
20030
|
+
setupCommand: "node9 setup claude",
|
|
20031
|
+
hookFile: (h) => import_path39.default.join(h, ".claude", "settings.json"),
|
|
20032
|
+
hookFormat: "matcher",
|
|
20033
|
+
hookEvents: [ck("PreToolUse"), lg("PostToolUse")],
|
|
20034
|
+
mcpFile: (h) => import_path39.default.join(h, ".claude.json"),
|
|
20035
|
+
present: (h) => exists(import_path39.default.join(h, ".claude", "settings.json")) || exists(import_path39.default.join(h, ".claude.json"))
|
|
20036
|
+
},
|
|
20037
|
+
{
|
|
20038
|
+
id: "gemini",
|
|
20039
|
+
label: "Gemini CLI",
|
|
20040
|
+
setupCommand: "node9 setup gemini",
|
|
20041
|
+
hookFile: (h) => import_path39.default.join(h, ".gemini", "settings.json"),
|
|
20042
|
+
hookFormat: "matcher",
|
|
20043
|
+
hookEvents: [ck("BeforeTool"), lg("AfterTool")],
|
|
20044
|
+
mcpFile: (h) => import_path39.default.join(h, ".gemini", "settings.json"),
|
|
20045
|
+
present: (h) => exists(import_path39.default.join(h, ".gemini", "settings.json"))
|
|
20046
|
+
},
|
|
20047
|
+
{
|
|
20048
|
+
id: "codex",
|
|
20049
|
+
label: "Codex",
|
|
20050
|
+
setupCommand: "node9 setup codex",
|
|
20051
|
+
hookFile: (h) => import_path39.default.join(h, ".codex", "hooks.json"),
|
|
20052
|
+
hookFormat: "matcher",
|
|
20053
|
+
hookEvents: [ck("PreToolUse"), ck("UserPromptSubmit")],
|
|
20054
|
+
present: (h) => exists(import_path39.default.join(h, ".codex"))
|
|
20055
|
+
},
|
|
20056
|
+
{
|
|
20057
|
+
id: "antigravity",
|
|
20058
|
+
label: "Antigravity",
|
|
20059
|
+
setupCommand: "node9 setup antigravity",
|
|
20060
|
+
hookFile: (h) => import_path39.default.join(h, ".gemini", "config", "hooks.json"),
|
|
20061
|
+
hookFormat: "matcher",
|
|
20062
|
+
hookEvents: [ck("PreToolUse"), lg("PostToolUse")],
|
|
20063
|
+
mcpFile: (h) => import_path39.default.join(h, ".gemini", "config", "mcp_config.json"),
|
|
20064
|
+
present: (h) => exists(import_path39.default.join(h, ".gemini", "config", "hooks.json")) || exists(import_path39.default.join(h, ".gemini", "antigravity-cli")) || exists(import_path39.default.join(h, ".gemini", "antigravity-ide"))
|
|
20065
|
+
},
|
|
20066
|
+
{
|
|
20067
|
+
id: "copilot",
|
|
20068
|
+
label: "GitHub Copilot",
|
|
20069
|
+
setupCommand: "node9 setup copilot",
|
|
20070
|
+
hookFile: (h) => import_path39.default.join(h, ".copilot", "hooks", "node9.json"),
|
|
20071
|
+
hookFormat: "flat",
|
|
20072
|
+
hookEvents: [ck("PreToolUse"), lg("PostToolUse"), ck("UserPromptSubmit")],
|
|
20073
|
+
mcpFile: (h) => import_path39.default.join(h, ".copilot", "mcp-config.json"),
|
|
20074
|
+
present: (h) => exists(import_path39.default.join(h, ".copilot"))
|
|
20075
|
+
},
|
|
20076
|
+
{
|
|
20077
|
+
id: "cursor",
|
|
20078
|
+
label: "Cursor",
|
|
20079
|
+
setupCommand: "node9 setup cursor",
|
|
20080
|
+
// MCP-only — no hook file (see note above).
|
|
20081
|
+
hookFormat: "flat",
|
|
20082
|
+
hookEvents: [],
|
|
20083
|
+
mcpFile: (h) => import_path39.default.join(h, ".cursor", "mcp.json"),
|
|
20084
|
+
present: (h) => exists(import_path39.default.join(h, ".cursor", "mcp.json"))
|
|
20085
|
+
},
|
|
20086
|
+
{
|
|
20087
|
+
id: "hermes",
|
|
20088
|
+
label: "Hermes Agent",
|
|
20089
|
+
setupCommand: "node9 setup hermes",
|
|
20090
|
+
hookFile: (h) => hermesConfigPath(h),
|
|
20091
|
+
hookFormat: "yaml",
|
|
20092
|
+
hookEvents: [ck("pre_tool_call"), lg("post_tool_call")],
|
|
20093
|
+
labelPad: 14,
|
|
20094
|
+
// 'post_tool_call' is wider than the default
|
|
20095
|
+
present: (h) => exists(hermesConfigPath(h))
|
|
20096
|
+
}
|
|
20097
|
+
];
|
|
20098
|
+
function getAgentWiring(home = import_os34.default.homedir()) {
|
|
20099
|
+
const detected = detectAgents(home);
|
|
20100
|
+
return AGENT_SPECS.map((spec) => {
|
|
20101
|
+
const root = spec.hookFile ? readHookRoot(spec.hookFile(home), spec.hookFormat) : "absent";
|
|
20102
|
+
const primary = spec.hookEvents[0];
|
|
20103
|
+
const rootPresent = root !== "absent" && root !== "invalid";
|
|
20104
|
+
const pad = spec.labelPad ?? DEFAULT_LABEL_PAD;
|
|
20105
|
+
const hooks = spec.hookEvents.map((ev) => ({
|
|
20106
|
+
label: hookLabelOf(ev, pad),
|
|
20107
|
+
wired: rootPresent && eventWired(root, ev, spec.hookFormat)
|
|
20108
|
+
}));
|
|
20109
|
+
let wireState;
|
|
20110
|
+
if (root === "absent") wireState = "absent";
|
|
20111
|
+
else if (root === "invalid") wireState = "invalid";
|
|
20112
|
+
else wireState = primary && eventWired(root, primary, spec.hookFormat) ? "wired" : "unwired";
|
|
20113
|
+
const mcp = spec.mcpFile ? readMcp(spec.mcpFile(home)) : null;
|
|
20114
|
+
const anyHookWired = hooks.some((h) => h.wired);
|
|
20115
|
+
return {
|
|
20116
|
+
id: spec.id,
|
|
20117
|
+
label: spec.label,
|
|
20118
|
+
setupCommand: spec.setupCommand,
|
|
20119
|
+
installed: detected[spec.id],
|
|
20120
|
+
present: spec.present(home),
|
|
20121
|
+
hooks,
|
|
20122
|
+
wireState,
|
|
20123
|
+
hookLabel: primary ? `${primary.key} hook` : "MCP proxy",
|
|
20124
|
+
settingsPath: spec.hookFile ? spec.hookFile(home) : spec.mcpFile ? spec.mcpFile(home) : "",
|
|
20125
|
+
configFormat: spec.hookFormat === "yaml" ? "YAML" : "JSON",
|
|
20126
|
+
mcpServers: mcp ? mcp.wrapped : null,
|
|
20127
|
+
mcpProtected: mcp ? mcp.present : false,
|
|
20128
|
+
isProtected: anyHookWired || (mcp?.present ?? false)
|
|
20129
|
+
};
|
|
20130
|
+
});
|
|
20131
|
+
}
|
|
20132
|
+
|
|
20133
|
+
// src/cli/commands/doctor.ts
|
|
19965
20134
|
function registerDoctorCommand(program2, version2) {
|
|
19966
20135
|
program2.command("doctor").description("Check that Node9 is installed and configured correctly").action(async () => {
|
|
19967
|
-
const homeDir2 =
|
|
20136
|
+
const homeDir2 = import_os35.default.homedir();
|
|
19968
20137
|
let failures = 0;
|
|
19969
20138
|
function pass(msg) {
|
|
19970
20139
|
console.log(import_chalk11.default.green(" \u2705 ") + msg);
|
|
@@ -20013,10 +20182,10 @@ function registerDoctorCommand(program2, version2) {
|
|
|
20013
20182
|
);
|
|
20014
20183
|
}
|
|
20015
20184
|
section("Configuration");
|
|
20016
|
-
const globalConfigPath =
|
|
20017
|
-
if (
|
|
20185
|
+
const globalConfigPath = import_path40.default.join(homeDir2, ".node9", "config.json");
|
|
20186
|
+
if (import_fs39.default.existsSync(globalConfigPath)) {
|
|
20018
20187
|
try {
|
|
20019
|
-
JSON.parse(
|
|
20188
|
+
JSON.parse(import_fs39.default.readFileSync(globalConfigPath, "utf-8"));
|
|
20020
20189
|
pass("~/.node9/config.json found and valid");
|
|
20021
20190
|
} catch {
|
|
20022
20191
|
fail("~/.node9/config.json is invalid JSON", "Run: node9 init --force");
|
|
@@ -20024,10 +20193,10 @@ function registerDoctorCommand(program2, version2) {
|
|
|
20024
20193
|
} else {
|
|
20025
20194
|
warn("~/.node9/config.json not found (using defaults)", "Run: node9 init");
|
|
20026
20195
|
}
|
|
20027
|
-
const projectConfigPath =
|
|
20028
|
-
if (
|
|
20196
|
+
const projectConfigPath = import_path40.default.join(process.cwd(), "node9.config.json");
|
|
20197
|
+
if (import_fs39.default.existsSync(projectConfigPath)) {
|
|
20029
20198
|
try {
|
|
20030
|
-
JSON.parse(
|
|
20199
|
+
JSON.parse(import_fs39.default.readFileSync(projectConfigPath, "utf-8"));
|
|
20031
20200
|
pass("node9.config.json found and valid (project)");
|
|
20032
20201
|
} catch {
|
|
20033
20202
|
fail(
|
|
@@ -20036,8 +20205,8 @@ function registerDoctorCommand(program2, version2) {
|
|
|
20036
20205
|
);
|
|
20037
20206
|
}
|
|
20038
20207
|
}
|
|
20039
|
-
const credsPath =
|
|
20040
|
-
if (
|
|
20208
|
+
const credsPath = import_path40.default.join(homeDir2, ".node9", "credentials.json");
|
|
20209
|
+
if (import_fs39.default.existsSync(credsPath)) {
|
|
20041
20210
|
pass("Cloud credentials found (~/.node9/credentials.json)");
|
|
20042
20211
|
} else {
|
|
20043
20212
|
warn(
|
|
@@ -20046,62 +20215,25 @@ function registerDoctorCommand(program2, version2) {
|
|
|
20046
20215
|
);
|
|
20047
20216
|
}
|
|
20048
20217
|
section("Agent Hooks");
|
|
20049
|
-
const
|
|
20050
|
-
|
|
20051
|
-
|
|
20052
|
-
|
|
20053
|
-
|
|
20054
|
-
|
|
20055
|
-
);
|
|
20056
|
-
|
|
20057
|
-
|
|
20058
|
-
|
|
20059
|
-
|
|
20060
|
-
"Run: node9 setup claude"
|
|
20061
|
-
);
|
|
20062
|
-
} catch {
|
|
20063
|
-
fail("Claude Code \u2014 ~/.claude/settings.json is invalid JSON");
|
|
20064
|
-
}
|
|
20065
|
-
} else {
|
|
20066
|
-
warn("Claude Code \u2014 not configured", "Run: node9 setup claude");
|
|
20067
|
-
}
|
|
20068
|
-
const geminiSettingsPath = import_path39.default.join(homeDir2, ".gemini", "settings.json");
|
|
20069
|
-
if (import_fs38.default.existsSync(geminiSettingsPath)) {
|
|
20070
|
-
try {
|
|
20071
|
-
const gs = JSON.parse(import_fs38.default.readFileSync(geminiSettingsPath, "utf-8"));
|
|
20072
|
-
const hasHook = gs.hooks?.BeforeTool?.some(
|
|
20073
|
-
(m) => m.hooks.some((h) => h.command?.includes("node9") || h.command?.includes("cli.js"))
|
|
20074
|
-
);
|
|
20075
|
-
if (hasHook) pass("Gemini CLI \u2014 BeforeTool hook active");
|
|
20076
|
-
else
|
|
20077
|
-
fail(
|
|
20078
|
-
"Gemini CLI \u2014 hooks file found but node9 hook missing",
|
|
20079
|
-
"Run: node9 setup gemini"
|
|
20080
|
-
);
|
|
20081
|
-
} catch {
|
|
20082
|
-
fail("Gemini CLI \u2014 ~/.gemini/settings.json is invalid JSON");
|
|
20218
|
+
const notConfigured = [];
|
|
20219
|
+
for (const a of getAgentWiring(homeDir2)) {
|
|
20220
|
+
const anyHookWired = a.hooks.some((h) => h.wired);
|
|
20221
|
+
if (a.isProtected) {
|
|
20222
|
+
pass(`${a.label} \u2014 ${anyHookWired ? `${a.hookLabel} active` : "MCP proxy active"}`);
|
|
20223
|
+
} else if (a.wireState === "invalid") {
|
|
20224
|
+
fail(`${a.label} \u2014 settings file is invalid JSON`, a.settingsPath);
|
|
20225
|
+
} else if (a.wireState === "unwired") {
|
|
20226
|
+
fail(`${a.label} \u2014 settings found but node9 hook missing`, `Run: ${a.setupCommand}`);
|
|
20227
|
+
} else {
|
|
20228
|
+
notConfigured.push(a.label);
|
|
20083
20229
|
}
|
|
20084
|
-
} else {
|
|
20085
|
-
warn("Gemini CLI \u2014 not configured", "Run: node9 setup gemini (skip if not using Gemini)");
|
|
20086
20230
|
}
|
|
20087
|
-
|
|
20088
|
-
|
|
20089
|
-
|
|
20090
|
-
|
|
20091
|
-
|
|
20092
|
-
|
|
20093
|
-
);
|
|
20094
|
-
if (hasHook) pass("Cursor \u2014 preToolUse hook active");
|
|
20095
|
-
else
|
|
20096
|
-
fail(
|
|
20097
|
-
"Cursor \u2014 hooks file found but node9 hook missing",
|
|
20098
|
-
"Run: node9 setup cursor"
|
|
20099
|
-
);
|
|
20100
|
-
} catch {
|
|
20101
|
-
fail("Cursor \u2014 ~/.cursor/hooks.json is invalid JSON");
|
|
20102
|
-
}
|
|
20103
|
-
} else {
|
|
20104
|
-
warn("Cursor \u2014 not configured", "Run: node9 setup cursor (skip if not using Cursor)");
|
|
20231
|
+
if (notConfigured.length > 0) {
|
|
20232
|
+
console.log(
|
|
20233
|
+
import_chalk11.default.gray(
|
|
20234
|
+
` \xB7 Not configured: ${notConfigured.join(", ")} \u2014 run \`node9 setup <agent>\` if you use one`
|
|
20235
|
+
)
|
|
20236
|
+
);
|
|
20105
20237
|
}
|
|
20106
20238
|
section("Daemon (optional)");
|
|
20107
20239
|
if (isDaemonRunning()) {
|
|
@@ -20118,7 +20250,7 @@ function registerDoctorCommand(program2, version2) {
|
|
|
20118
20250
|
try {
|
|
20119
20251
|
const { shipLagBytes: shipLagBytes2, readWatermark: readWatermark2, AUDIT_SHIP_WATERMARK: AUDIT_SHIP_WATERMARK2 } = await Promise.resolve().then(() => (init_audit_shipper(), audit_shipper_exports));
|
|
20120
20252
|
const cfg = getConfig();
|
|
20121
|
-
const creds =
|
|
20253
|
+
const creds = import_fs39.default.existsSync(import_path40.default.join(import_os35.default.homedir(), ".node9", "credentials.json"));
|
|
20122
20254
|
if (!creds) {
|
|
20123
20255
|
warn("Not logged in \u2014 audit rows stay local", "Run: node9 login <api-key>");
|
|
20124
20256
|
} else if (!cfg.settings.approvers.cloud) {
|
|
@@ -20168,9 +20300,9 @@ function registerDoctorCommand(program2, version2) {
|
|
|
20168
20300
|
|
|
20169
20301
|
// src/cli/commands/audit.ts
|
|
20170
20302
|
var import_chalk12 = __toESM(require("chalk"));
|
|
20171
|
-
var
|
|
20172
|
-
var
|
|
20173
|
-
var
|
|
20303
|
+
var import_fs40 = __toESM(require("fs"));
|
|
20304
|
+
var import_path41 = __toESM(require("path"));
|
|
20305
|
+
var import_os36 = __toESM(require("os"));
|
|
20174
20306
|
function formatRelativeTime(timestamp) {
|
|
20175
20307
|
const diff = Date.now() - new Date(timestamp).getTime();
|
|
20176
20308
|
const sec = Math.floor(diff / 1e3);
|
|
@@ -20183,14 +20315,14 @@ function formatRelativeTime(timestamp) {
|
|
|
20183
20315
|
}
|
|
20184
20316
|
function registerAuditCommand(program2) {
|
|
20185
20317
|
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) => {
|
|
20186
|
-
const logPath =
|
|
20187
|
-
if (!
|
|
20318
|
+
const logPath = import_path41.default.join(import_os36.default.homedir(), ".node9", "audit.log");
|
|
20319
|
+
if (!import_fs40.default.existsSync(logPath)) {
|
|
20188
20320
|
console.log(
|
|
20189
20321
|
import_chalk12.default.yellow("No audit logs found. Run node9 with an agent to generate entries.")
|
|
20190
20322
|
);
|
|
20191
20323
|
return;
|
|
20192
20324
|
}
|
|
20193
|
-
const raw =
|
|
20325
|
+
const raw = import_fs40.default.readFileSync(logPath, "utf-8");
|
|
20194
20326
|
const lines = raw.split("\n").filter((l) => l.trim() !== "");
|
|
20195
20327
|
let entries = lines.flatMap((line) => {
|
|
20196
20328
|
try {
|
|
@@ -20246,9 +20378,9 @@ function registerAuditCommand(program2) {
|
|
|
20246
20378
|
var import_chalk13 = __toESM(require("chalk"));
|
|
20247
20379
|
|
|
20248
20380
|
// src/cli/aggregate/report-audit.ts
|
|
20249
|
-
var
|
|
20250
|
-
var
|
|
20251
|
-
var
|
|
20381
|
+
var import_fs41 = __toESM(require("fs"));
|
|
20382
|
+
var import_os37 = __toESM(require("os"));
|
|
20383
|
+
var import_path42 = __toESM(require("path"));
|
|
20252
20384
|
init_costSync();
|
|
20253
20385
|
init_litellm();
|
|
20254
20386
|
init_cost_codex();
|
|
@@ -20331,8 +20463,8 @@ function getDateRange(period, now) {
|
|
|
20331
20463
|
}
|
|
20332
20464
|
}
|
|
20333
20465
|
function parseAuditLog(logPath) {
|
|
20334
|
-
if (!
|
|
20335
|
-
const raw =
|
|
20466
|
+
if (!import_fs41.default.existsSync(logPath)) return [];
|
|
20467
|
+
const raw = import_fs41.default.readFileSync(logPath, "utf-8");
|
|
20336
20468
|
return raw.split("\n").flatMap((line) => {
|
|
20337
20469
|
if (!line.trim()) return [];
|
|
20338
20470
|
try {
|
|
@@ -20379,25 +20511,25 @@ function freezeClaudeCost(acc) {
|
|
|
20379
20511
|
};
|
|
20380
20512
|
}
|
|
20381
20513
|
function processClaudeCostProject(proj, projectsDir, start, end, acc) {
|
|
20382
|
-
const projPath =
|
|
20514
|
+
const projPath = import_path42.default.join(projectsDir, proj);
|
|
20383
20515
|
let files;
|
|
20384
20516
|
try {
|
|
20385
|
-
const stat =
|
|
20517
|
+
const stat = import_fs41.default.statSync(projPath);
|
|
20386
20518
|
if (!stat.isDirectory()) return;
|
|
20387
|
-
files =
|
|
20519
|
+
files = import_fs41.default.readdirSync(projPath).filter((f) => f.endsWith(".jsonl") && !f.startsWith("agent-"));
|
|
20388
20520
|
} catch {
|
|
20389
20521
|
return;
|
|
20390
20522
|
}
|
|
20391
20523
|
const startMs = start.getTime();
|
|
20392
20524
|
for (const file of files) {
|
|
20393
|
-
const filePath =
|
|
20525
|
+
const filePath = import_path42.default.join(projPath, file);
|
|
20394
20526
|
try {
|
|
20395
|
-
if (
|
|
20527
|
+
if (import_fs41.default.statSync(filePath).mtimeMs < startMs) continue;
|
|
20396
20528
|
} catch {
|
|
20397
20529
|
continue;
|
|
20398
20530
|
}
|
|
20399
20531
|
try {
|
|
20400
|
-
const raw =
|
|
20532
|
+
const raw = import_fs41.default.readFileSync(filePath, "utf-8");
|
|
20401
20533
|
for (const line of raw.split("\n")) {
|
|
20402
20534
|
if (!line.trim()) continue;
|
|
20403
20535
|
let entry;
|
|
@@ -20447,10 +20579,10 @@ function processClaudeCostProject(proj, projectsDir, start, end, acc) {
|
|
|
20447
20579
|
}
|
|
20448
20580
|
function loadClaudeCost(start, end, projectsDir) {
|
|
20449
20581
|
const acc = emptyClaudeCostAccumulator();
|
|
20450
|
-
if (!
|
|
20582
|
+
if (!import_fs41.default.existsSync(projectsDir)) return freezeClaudeCost(acc);
|
|
20451
20583
|
let dirs;
|
|
20452
20584
|
try {
|
|
20453
|
-
dirs =
|
|
20585
|
+
dirs = import_fs41.default.readdirSync(projectsDir);
|
|
20454
20586
|
} catch {
|
|
20455
20587
|
return freezeClaudeCost(acc);
|
|
20456
20588
|
}
|
|
@@ -20462,7 +20594,7 @@ function loadClaudeCost(start, end, projectsDir) {
|
|
|
20462
20594
|
function processCodexCostFile(filePath, start, end, acc) {
|
|
20463
20595
|
let lines;
|
|
20464
20596
|
try {
|
|
20465
|
-
lines =
|
|
20597
|
+
lines = import_fs41.default.readFileSync(filePath, "utf-8").split("\n");
|
|
20466
20598
|
} catch {
|
|
20467
20599
|
return;
|
|
20468
20600
|
}
|
|
@@ -20517,31 +20649,31 @@ function processCodexCostFile(filePath, start, end, acc) {
|
|
|
20517
20649
|
}
|
|
20518
20650
|
function listCodexSessionFiles2(sessionsBase) {
|
|
20519
20651
|
const jsonlFiles = [];
|
|
20520
|
-
if (!
|
|
20652
|
+
if (!import_fs41.default.existsSync(sessionsBase)) return jsonlFiles;
|
|
20521
20653
|
try {
|
|
20522
|
-
for (const year of
|
|
20523
|
-
const yearPath =
|
|
20654
|
+
for (const year of import_fs41.default.readdirSync(sessionsBase)) {
|
|
20655
|
+
const yearPath = import_path42.default.join(sessionsBase, year);
|
|
20524
20656
|
try {
|
|
20525
|
-
if (!
|
|
20657
|
+
if (!import_fs41.default.statSync(yearPath).isDirectory()) continue;
|
|
20526
20658
|
} catch {
|
|
20527
20659
|
continue;
|
|
20528
20660
|
}
|
|
20529
|
-
for (const month of
|
|
20530
|
-
const monthPath =
|
|
20661
|
+
for (const month of import_fs41.default.readdirSync(yearPath)) {
|
|
20662
|
+
const monthPath = import_path42.default.join(yearPath, month);
|
|
20531
20663
|
try {
|
|
20532
|
-
if (!
|
|
20664
|
+
if (!import_fs41.default.statSync(monthPath).isDirectory()) continue;
|
|
20533
20665
|
} catch {
|
|
20534
20666
|
continue;
|
|
20535
20667
|
}
|
|
20536
|
-
for (const day of
|
|
20537
|
-
const dayPath =
|
|
20668
|
+
for (const day of import_fs41.default.readdirSync(monthPath)) {
|
|
20669
|
+
const dayPath = import_path42.default.join(monthPath, day);
|
|
20538
20670
|
try {
|
|
20539
|
-
if (!
|
|
20671
|
+
if (!import_fs41.default.statSync(dayPath).isDirectory()) continue;
|
|
20540
20672
|
} catch {
|
|
20541
20673
|
continue;
|
|
20542
20674
|
}
|
|
20543
|
-
for (const file of
|
|
20544
|
-
if (file.endsWith(".jsonl")) jsonlFiles.push(
|
|
20675
|
+
for (const file of import_fs41.default.readdirSync(dayPath)) {
|
|
20676
|
+
if (file.endsWith(".jsonl")) jsonlFiles.push(import_path42.default.join(dayPath, file));
|
|
20545
20677
|
}
|
|
20546
20678
|
}
|
|
20547
20679
|
}
|
|
@@ -20606,13 +20738,13 @@ function freezeGeminiCost(acc) {
|
|
|
20606
20738
|
function processGeminiCostFile(filePath, projectKey, start, end, acc) {
|
|
20607
20739
|
const startMs = start.getTime();
|
|
20608
20740
|
try {
|
|
20609
|
-
if (
|
|
20741
|
+
if (import_fs41.default.statSync(filePath).mtimeMs < startMs) return;
|
|
20610
20742
|
} catch {
|
|
20611
20743
|
return;
|
|
20612
20744
|
}
|
|
20613
20745
|
let raw;
|
|
20614
20746
|
try {
|
|
20615
|
-
raw =
|
|
20747
|
+
raw = import_fs41.default.readFileSync(filePath, "utf-8");
|
|
20616
20748
|
} catch {
|
|
20617
20749
|
return;
|
|
20618
20750
|
}
|
|
@@ -20661,30 +20793,30 @@ function listGeminiSessionFiles2(geminiTmpDir2) {
|
|
|
20661
20793
|
const out = [];
|
|
20662
20794
|
let dirs;
|
|
20663
20795
|
try {
|
|
20664
|
-
if (!
|
|
20665
|
-
dirs =
|
|
20796
|
+
if (!import_fs41.default.statSync(geminiTmpDir2).isDirectory()) return out;
|
|
20797
|
+
dirs = import_fs41.default.readdirSync(geminiTmpDir2);
|
|
20666
20798
|
} catch {
|
|
20667
20799
|
return out;
|
|
20668
20800
|
}
|
|
20669
20801
|
for (const proj of dirs) {
|
|
20670
|
-
const chatsDir =
|
|
20802
|
+
const chatsDir = import_path42.default.join(geminiTmpDir2, proj, "chats");
|
|
20671
20803
|
let files;
|
|
20672
20804
|
try {
|
|
20673
|
-
if (!
|
|
20674
|
-
files =
|
|
20805
|
+
if (!import_fs41.default.statSync(chatsDir).isDirectory()) continue;
|
|
20806
|
+
files = import_fs41.default.readdirSync(chatsDir);
|
|
20675
20807
|
} catch {
|
|
20676
20808
|
continue;
|
|
20677
20809
|
}
|
|
20678
20810
|
for (const f of files) {
|
|
20679
20811
|
if (!f.endsWith(".jsonl")) continue;
|
|
20680
|
-
out.push({ projectKey: proj, file:
|
|
20812
|
+
out.push({ projectKey: proj, file: import_path42.default.join(chatsDir, f) });
|
|
20681
20813
|
}
|
|
20682
20814
|
}
|
|
20683
20815
|
return out;
|
|
20684
20816
|
}
|
|
20685
20817
|
function loadGeminiCost(start, end, geminiTmpDir2) {
|
|
20686
20818
|
const acc = emptyGeminiAccumulator();
|
|
20687
|
-
if (!
|
|
20819
|
+
if (!import_fs41.default.existsSync(geminiTmpDir2)) return freezeGeminiCost(acc);
|
|
20688
20820
|
for (const { projectKey, file } of listGeminiSessionFiles2(geminiTmpDir2)) {
|
|
20689
20821
|
processGeminiCostFile(file, projectKey, start, end, acc);
|
|
20690
20822
|
}
|
|
@@ -20692,11 +20824,11 @@ function loadGeminiCost(start, end, geminiTmpDir2) {
|
|
|
20692
20824
|
}
|
|
20693
20825
|
function aggregateReportFromAudit(period, opts = {}) {
|
|
20694
20826
|
const now = opts.now ?? /* @__PURE__ */ new Date();
|
|
20695
|
-
const auditLogPath = opts.auditLogPath ??
|
|
20696
|
-
const claudeProjectsDir = opts.claudeProjectsDir ??
|
|
20697
|
-
const codexSessionsDir2 = opts.codexSessionsDir ??
|
|
20698
|
-
const geminiTmpDir2 = opts.geminiTmpDir ??
|
|
20699
|
-
const hasAuditFile =
|
|
20827
|
+
const auditLogPath = opts.auditLogPath ?? import_path42.default.join(import_os37.default.homedir(), ".node9", "audit.log");
|
|
20828
|
+
const claudeProjectsDir = opts.claudeProjectsDir ?? import_path42.default.join(import_os37.default.homedir(), ".claude", "projects");
|
|
20829
|
+
const codexSessionsDir2 = opts.codexSessionsDir ?? import_path42.default.join(import_os37.default.homedir(), ".codex", "sessions");
|
|
20830
|
+
const geminiTmpDir2 = opts.geminiTmpDir ?? import_path42.default.join(import_os37.default.homedir(), ".gemini", "tmp");
|
|
20831
|
+
const hasAuditFile = import_fs41.default.existsSync(auditLogPath);
|
|
20700
20832
|
const allEntries = opts.preloadedAuditEntries ?? parseAuditLog(auditLogPath);
|
|
20701
20833
|
const unackedDlp = allEntries.filter((e) => e.source === "response-dlp");
|
|
20702
20834
|
const { start, end } = getDateRange(period, now);
|
|
@@ -21392,53 +21524,11 @@ function registerDaemonCommand(program2) {
|
|
|
21392
21524
|
|
|
21393
21525
|
// src/cli/commands/status.ts
|
|
21394
21526
|
var import_chalk15 = __toESM(require("chalk"));
|
|
21395
|
-
var
|
|
21396
|
-
var
|
|
21397
|
-
var
|
|
21398
|
-
var yaml2 = __toESM(require("yaml"));
|
|
21527
|
+
var import_fs42 = __toESM(require("fs"));
|
|
21528
|
+
var import_path43 = __toESM(require("path"));
|
|
21529
|
+
var import_os38 = __toESM(require("os"));
|
|
21399
21530
|
init_core();
|
|
21400
21531
|
init_daemon();
|
|
21401
|
-
init_setup();
|
|
21402
|
-
function readHermesHooks(configPath) {
|
|
21403
|
-
if (!import_fs41.default.existsSync(configPath)) return null;
|
|
21404
|
-
let raw;
|
|
21405
|
-
try {
|
|
21406
|
-
raw = import_fs41.default.readFileSync(configPath, "utf-8");
|
|
21407
|
-
} catch {
|
|
21408
|
-
return null;
|
|
21409
|
-
}
|
|
21410
|
-
try {
|
|
21411
|
-
const cfg = yaml2.parse(raw);
|
|
21412
|
-
const has = (event) => (cfg?.hooks?.[event] ?? []).some(
|
|
21413
|
-
(e) => typeof e?.command === "string" && isNode9Hook(e.command)
|
|
21414
|
-
);
|
|
21415
|
-
return { pre: has("pre_tool_call"), post: has("post_tool_call") };
|
|
21416
|
-
} catch {
|
|
21417
|
-
console.error(
|
|
21418
|
-
import_chalk15.default.yellow(
|
|
21419
|
-
` \u26A0\uFE0F Hermes config.yaml at ${configPath} is not valid YAML \u2014 showing as unwired.`
|
|
21420
|
-
)
|
|
21421
|
-
);
|
|
21422
|
-
return { pre: false, post: false };
|
|
21423
|
-
}
|
|
21424
|
-
}
|
|
21425
|
-
function readJson2(filePath) {
|
|
21426
|
-
try {
|
|
21427
|
-
if (import_fs41.default.existsSync(filePath)) return JSON.parse(import_fs41.default.readFileSync(filePath, "utf-8"));
|
|
21428
|
-
} catch {
|
|
21429
|
-
}
|
|
21430
|
-
return null;
|
|
21431
|
-
}
|
|
21432
|
-
function matchersHaveNode9Hook(matchers) {
|
|
21433
|
-
return (matchers ?? []).some((m) => (m.hooks ?? []).some((h) => isNode9Hook(h.command)));
|
|
21434
|
-
}
|
|
21435
|
-
function flatHaveNode9Hook(entries) {
|
|
21436
|
-
return (Array.isArray(entries) ? entries : []).some((h) => isNode9Hook(h.command));
|
|
21437
|
-
}
|
|
21438
|
-
function wrappedMcpServers(servers) {
|
|
21439
|
-
if (!servers) return [];
|
|
21440
|
-
return Object.entries(servers).filter(([, s]) => s.command === "node9" && Array.isArray(s.args) && s.args.length > 0).map(([name, s]) => `${name} \u2192 ${s.args.join(" ")}`);
|
|
21441
|
-
}
|
|
21442
21532
|
function printAgentSection(label, hookPairs, wrapped) {
|
|
21443
21533
|
console.log(import_chalk15.default.bold(` ${label}`));
|
|
21444
21534
|
for (const { name, present } of hookPairs) {
|
|
@@ -21492,115 +21582,36 @@ function registerStatusCommand(program2) {
|
|
|
21492
21582
|
console.log("");
|
|
21493
21583
|
const modeLabel = settings.mode === "audit" ? import_chalk15.default.blue("audit") : settings.mode === "strict" ? import_chalk15.default.red("strict") : import_chalk15.default.white("standard");
|
|
21494
21584
|
console.log(` Mode: ${modeLabel}`);
|
|
21495
|
-
const projectConfig =
|
|
21496
|
-
const globalConfig =
|
|
21585
|
+
const projectConfig = import_path43.default.join(process.cwd(), "node9.config.json");
|
|
21586
|
+
const globalConfig = import_path43.default.join(import_os38.default.homedir(), ".node9", "config.json");
|
|
21497
21587
|
console.log(
|
|
21498
|
-
` Local: ${
|
|
21588
|
+
` Local: ${import_fs42.default.existsSync(projectConfig) ? import_chalk15.default.green("Active (node9.config.json)") : import_chalk15.default.gray("Not present")}`
|
|
21499
21589
|
);
|
|
21500
21590
|
console.log(
|
|
21501
|
-
` Global: ${
|
|
21591
|
+
` Global: ${import_fs42.default.existsSync(globalConfig) ? import_chalk15.default.green("Active (~/.node9/config.json)") : import_chalk15.default.gray("Not present")}`
|
|
21502
21592
|
);
|
|
21503
21593
|
if (mergedConfig.policy.sandboxPaths.length > 0) {
|
|
21504
21594
|
console.log(
|
|
21505
21595
|
` Sandbox: ${import_chalk15.default.green(`${mergedConfig.policy.sandboxPaths.length} safe zones active`)}`
|
|
21506
21596
|
);
|
|
21507
21597
|
}
|
|
21508
|
-
const
|
|
21509
|
-
|
|
21510
|
-
import_path42.default.join(homeDir2, ".claude", "settings.json")
|
|
21511
|
-
);
|
|
21512
|
-
const claudeConfig = readJson2(import_path42.default.join(homeDir2, ".claude.json"));
|
|
21513
|
-
const geminiSettings = readJson2(
|
|
21514
|
-
import_path42.default.join(homeDir2, ".gemini", "settings.json")
|
|
21515
|
-
);
|
|
21516
|
-
const cursorConfig = readJson2(import_path42.default.join(homeDir2, ".cursor", "mcp.json"));
|
|
21517
|
-
const antigravityHooks = readJson2(
|
|
21518
|
-
import_path42.default.join(homeDir2, ".gemini", "config", "hooks.json")
|
|
21519
|
-
);
|
|
21520
|
-
const antigravityMcp = readJson2(
|
|
21521
|
-
import_path42.default.join(homeDir2, ".gemini", "config", "mcp_config.json")
|
|
21522
|
-
);
|
|
21523
|
-
const antigravityPresent = antigravityHooks !== null || import_fs41.default.existsSync(import_path42.default.join(homeDir2, ".gemini", "antigravity-cli")) || import_fs41.default.existsSync(import_path42.default.join(homeDir2, ".gemini", "antigravity-ide"));
|
|
21524
|
-
const copilotHooks = readJson2(
|
|
21525
|
-
import_path42.default.join(homeDir2, ".copilot", "hooks", "node9.json")
|
|
21526
|
-
);
|
|
21527
|
-
const copilotMcp = readJson2(
|
|
21528
|
-
import_path42.default.join(homeDir2, ".copilot", "mcp-config.json")
|
|
21529
|
-
);
|
|
21530
|
-
const copilotPresent = import_fs41.default.existsSync(import_path42.default.join(homeDir2, ".copilot"));
|
|
21531
|
-
const hermesHooks = readHermesHooks(hermesConfigPath(homeDir2));
|
|
21532
|
-
const agentFound = claudeSettings || claudeConfig || geminiSettings || cursorConfig || antigravityPresent || copilotPresent || hermesHooks;
|
|
21533
|
-
if (agentFound) {
|
|
21598
|
+
const wiring = getAgentWiring(import_os38.default.homedir()).filter((a) => a.present);
|
|
21599
|
+
if (wiring.length > 0) {
|
|
21534
21600
|
console.log("");
|
|
21535
21601
|
console.log(import_chalk15.default.bold(" Agent Wiring:"));
|
|
21536
21602
|
console.log("");
|
|
21537
|
-
|
|
21538
|
-
|
|
21539
|
-
|
|
21540
|
-
|
|
21541
|
-
|
|
21542
|
-
|
|
21543
|
-
|
|
21544
|
-
|
|
21545
|
-
],
|
|
21546
|
-
wrappedMcpServers(claudeConfig?.mcpServers)
|
|
21547
|
-
);
|
|
21548
|
-
console.log("");
|
|
21549
|
-
}
|
|
21550
|
-
if (geminiSettings) {
|
|
21551
|
-
const beforeHook = matchersHaveNode9Hook(geminiSettings.hooks?.BeforeTool);
|
|
21552
|
-
const afterHook = matchersHaveNode9Hook(geminiSettings.hooks?.AfterTool);
|
|
21553
|
-
printAgentSection(
|
|
21554
|
-
"Gemini CLI",
|
|
21555
|
-
[
|
|
21556
|
-
{ name: "BeforeTool (node9 check)", present: beforeHook },
|
|
21557
|
-
{ name: "AfterTool (node9 log)", present: afterHook }
|
|
21558
|
-
],
|
|
21559
|
-
wrappedMcpServers(geminiSettings.mcpServers)
|
|
21560
|
-
);
|
|
21561
|
-
console.log("");
|
|
21562
|
-
}
|
|
21563
|
-
if (antigravityPresent) {
|
|
21564
|
-
const preHook = matchersHaveNode9Hook(antigravityHooks?.hooks?.PreToolUse);
|
|
21565
|
-
const postHook = matchersHaveNode9Hook(antigravityHooks?.hooks?.PostToolUse);
|
|
21566
|
-
printAgentSection(
|
|
21567
|
-
"Antigravity",
|
|
21568
|
-
[
|
|
21569
|
-
{ name: "PreToolUse (node9 check)", present: preHook },
|
|
21570
|
-
{ name: "PostToolUse (node9 log)", present: postHook }
|
|
21571
|
-
],
|
|
21572
|
-
wrappedMcpServers(antigravityMcp?.mcpServers)
|
|
21573
|
-
);
|
|
21574
|
-
console.log("");
|
|
21575
|
-
}
|
|
21576
|
-
if (copilotPresent) {
|
|
21577
|
-
const preHook = flatHaveNode9Hook(copilotHooks?.hooks?.PreToolUse);
|
|
21578
|
-
const postHook = flatHaveNode9Hook(copilotHooks?.hooks?.PostToolUse);
|
|
21579
|
-
const promptHook = flatHaveNode9Hook(copilotHooks?.hooks?.UserPromptSubmit);
|
|
21580
|
-
printAgentSection(
|
|
21581
|
-
"GitHub Copilot",
|
|
21582
|
-
[
|
|
21583
|
-
{ name: "PreToolUse (node9 check)", present: preHook },
|
|
21584
|
-
{ name: "PostToolUse (node9 log)", present: postHook },
|
|
21585
|
-
{ name: "UserPromptSubmit (node9 check)", present: promptHook }
|
|
21586
|
-
],
|
|
21587
|
-
wrappedMcpServers(copilotMcp?.mcpServers)
|
|
21588
|
-
);
|
|
21589
|
-
console.log("");
|
|
21590
|
-
}
|
|
21591
|
-
if (cursorConfig) {
|
|
21592
|
-
printAgentSection("Cursor", [], wrappedMcpServers(cursorConfig.mcpServers));
|
|
21593
|
-
console.log("");
|
|
21594
|
-
}
|
|
21595
|
-
if (hermesHooks) {
|
|
21603
|
+
for (const a of wiring) {
|
|
21604
|
+
if (a.wireState === "invalid") {
|
|
21605
|
+
console.error(
|
|
21606
|
+
import_chalk15.default.yellow(
|
|
21607
|
+
` \u26A0\uFE0F ${a.label} config at ${a.settingsPath} is not valid ${a.configFormat} \u2014 showing as unwired.`
|
|
21608
|
+
)
|
|
21609
|
+
);
|
|
21610
|
+
}
|
|
21596
21611
|
printAgentSection(
|
|
21597
|
-
|
|
21598
|
-
|
|
21599
|
-
|
|
21600
|
-
{ name: "post_tool_call (node9 log)", present: hermesHooks.post }
|
|
21601
|
-
],
|
|
21602
|
-
null
|
|
21603
|
-
// Hermes has no MCP surface
|
|
21612
|
+
a.label,
|
|
21613
|
+
a.hooks.map((h) => ({ name: h.label, present: h.wired })),
|
|
21614
|
+
a.mcpServers
|
|
21604
21615
|
);
|
|
21605
21616
|
console.log("");
|
|
21606
21617
|
}
|
|
@@ -21619,9 +21630,9 @@ function registerStatusCommand(program2) {
|
|
|
21619
21630
|
|
|
21620
21631
|
// src/cli/commands/init.ts
|
|
21621
21632
|
var import_chalk16 = __toESM(require("chalk"));
|
|
21622
|
-
var
|
|
21623
|
-
var
|
|
21624
|
-
var
|
|
21633
|
+
var import_fs43 = __toESM(require("fs"));
|
|
21634
|
+
var import_path44 = __toESM(require("path"));
|
|
21635
|
+
var import_os39 = __toESM(require("os"));
|
|
21625
21636
|
var import_https4 = __toESM(require("https"));
|
|
21626
21637
|
init_core();
|
|
21627
21638
|
init_setup();
|
|
@@ -21711,16 +21722,16 @@ function registerInitCommand(program2) {
|
|
|
21711
21722
|
}
|
|
21712
21723
|
console.log("");
|
|
21713
21724
|
}
|
|
21714
|
-
const configPath =
|
|
21715
|
-
const isFirstInstall = !
|
|
21716
|
-
if (
|
|
21725
|
+
const configPath = import_path44.default.join(import_os39.default.homedir(), ".node9", "config.json");
|
|
21726
|
+
const isFirstInstall = !import_fs43.default.existsSync(configPath);
|
|
21727
|
+
if (import_fs43.default.existsSync(configPath) && !options.force) {
|
|
21717
21728
|
try {
|
|
21718
|
-
const existing = JSON.parse(
|
|
21729
|
+
const existing = JSON.parse(import_fs43.default.readFileSync(configPath, "utf-8"));
|
|
21719
21730
|
const settings = existing.settings ?? {};
|
|
21720
21731
|
if (settings.mode !== chosenMode) {
|
|
21721
21732
|
settings.mode = chosenMode;
|
|
21722
21733
|
existing.settings = settings;
|
|
21723
|
-
|
|
21734
|
+
import_fs43.default.writeFileSync(configPath, JSON.stringify(existing, null, 2) + "\n");
|
|
21724
21735
|
console.log(import_chalk16.default.green(`\u2705 Mode updated: ${chosenMode}`));
|
|
21725
21736
|
} else {
|
|
21726
21737
|
console.log(import_chalk16.default.blue(`\u2139\uFE0F Config already exists: ${configPath}`));
|
|
@@ -21733,9 +21744,9 @@ function registerInitCommand(program2) {
|
|
|
21733
21744
|
...DEFAULT_CONFIG,
|
|
21734
21745
|
settings: { ...DEFAULT_CONFIG.settings, mode: chosenMode }
|
|
21735
21746
|
};
|
|
21736
|
-
const dir =
|
|
21737
|
-
if (!
|
|
21738
|
-
|
|
21747
|
+
const dir = import_path44.default.dirname(configPath);
|
|
21748
|
+
if (!import_fs43.default.existsSync(dir)) import_fs43.default.mkdirSync(dir, { recursive: true });
|
|
21749
|
+
import_fs43.default.writeFileSync(configPath, JSON.stringify(configToSave, null, 2) + "\n");
|
|
21739
21750
|
console.log(import_chalk16.default.green(`\u2705 Config created: ${configPath}`));
|
|
21740
21751
|
console.log(import_chalk16.default.gray(` Mode: ${chosenMode}`));
|
|
21741
21752
|
}
|
|
@@ -21840,7 +21851,7 @@ function registerInitCommand(program2) {
|
|
|
21840
21851
|
}
|
|
21841
21852
|
|
|
21842
21853
|
// src/cli/commands/undo.ts
|
|
21843
|
-
var
|
|
21854
|
+
var import_path45 = __toESM(require("path"));
|
|
21844
21855
|
var import_chalk18 = __toESM(require("chalk"));
|
|
21845
21856
|
|
|
21846
21857
|
// src/tui/undo-navigator.ts
|
|
@@ -21999,7 +22010,7 @@ function findMatchingCwd(startDir, history) {
|
|
|
21999
22010
|
let dir = startDir;
|
|
22000
22011
|
while (true) {
|
|
22001
22012
|
if (cwds.has(dir)) return dir;
|
|
22002
|
-
const parent =
|
|
22013
|
+
const parent = import_path45.default.dirname(dir);
|
|
22003
22014
|
if (parent === dir) return null;
|
|
22004
22015
|
dir = parent;
|
|
22005
22016
|
}
|
|
@@ -22634,9 +22645,9 @@ function registerMcpGatewayCommand(program2) {
|
|
|
22634
22645
|
|
|
22635
22646
|
// src/mcp-server/index.ts
|
|
22636
22647
|
var import_readline5 = __toESM(require("readline"));
|
|
22637
|
-
var
|
|
22638
|
-
var
|
|
22639
|
-
var
|
|
22648
|
+
var import_fs44 = __toESM(require("fs"));
|
|
22649
|
+
var import_os40 = __toESM(require("os"));
|
|
22650
|
+
var import_path46 = __toESM(require("path"));
|
|
22640
22651
|
var import_child_process11 = require("child_process");
|
|
22641
22652
|
init_core();
|
|
22642
22653
|
init_daemon();
|
|
@@ -22887,13 +22898,13 @@ function handleStatus() {
|
|
|
22887
22898
|
lines.push(`Active shields: ${activeShields.length > 0 ? activeShields.join(", ") : "none"}`);
|
|
22888
22899
|
lines.push(`Smart rules: ${config.policy.smartRules.length} loaded`);
|
|
22889
22900
|
lines.push(`DLP: ${config.policy.dlp?.enabled !== false ? "enabled" : "disabled"}`);
|
|
22890
|
-
const projectConfig =
|
|
22891
|
-
const globalConfig =
|
|
22901
|
+
const projectConfig = import_path46.default.join(process.cwd(), "node9.config.json");
|
|
22902
|
+
const globalConfig = import_path46.default.join(import_os40.default.homedir(), ".node9", "config.json");
|
|
22892
22903
|
lines.push(
|
|
22893
|
-
`Project config (node9.config.json): ${
|
|
22904
|
+
`Project config (node9.config.json): ${import_fs44.default.existsSync(projectConfig) ? "present" : "not found"}`
|
|
22894
22905
|
);
|
|
22895
22906
|
lines.push(
|
|
22896
|
-
`Global config (~/.node9/config.json): ${
|
|
22907
|
+
`Global config (~/.node9/config.json): ${import_fs44.default.existsSync(globalConfig) ? "present" : "not found"}`
|
|
22897
22908
|
);
|
|
22898
22909
|
return lines.join("\n");
|
|
22899
22910
|
}
|
|
@@ -22967,21 +22978,21 @@ function handleShieldDisable(args) {
|
|
|
22967
22978
|
writeActiveShields(active.filter((s) => s !== name));
|
|
22968
22979
|
return `Shield "${name}" disabled.`;
|
|
22969
22980
|
}
|
|
22970
|
-
var GLOBAL_CONFIG_PATH =
|
|
22981
|
+
var GLOBAL_CONFIG_PATH = import_path46.default.join(import_os40.default.homedir(), ".node9", "config.json");
|
|
22971
22982
|
var APPROVER_CHANNELS = ["native", "browser", "cloud", "terminal"];
|
|
22972
22983
|
function readGlobalConfigRaw() {
|
|
22973
22984
|
try {
|
|
22974
|
-
if (
|
|
22975
|
-
return JSON.parse(
|
|
22985
|
+
if (import_fs44.default.existsSync(GLOBAL_CONFIG_PATH)) {
|
|
22986
|
+
return JSON.parse(import_fs44.default.readFileSync(GLOBAL_CONFIG_PATH, "utf-8"));
|
|
22976
22987
|
}
|
|
22977
22988
|
} catch {
|
|
22978
22989
|
}
|
|
22979
22990
|
return {};
|
|
22980
22991
|
}
|
|
22981
22992
|
function writeGlobalConfigRaw(data) {
|
|
22982
|
-
const dir =
|
|
22983
|
-
if (!
|
|
22984
|
-
|
|
22993
|
+
const dir = import_path46.default.dirname(GLOBAL_CONFIG_PATH);
|
|
22994
|
+
if (!import_fs44.default.existsSync(dir)) import_fs44.default.mkdirSync(dir, { recursive: true });
|
|
22995
|
+
import_fs44.default.writeFileSync(GLOBAL_CONFIG_PATH, JSON.stringify(data, null, 2) + "\n");
|
|
22985
22996
|
}
|
|
22986
22997
|
function handleApproverList() {
|
|
22987
22998
|
const config = getConfig();
|
|
@@ -23025,9 +23036,9 @@ function handleApproverSet(args) {
|
|
|
23025
23036
|
function handleAuditGet(args) {
|
|
23026
23037
|
const limit = Math.min(typeof args.limit === "number" ? args.limit : 20, 100);
|
|
23027
23038
|
const filter = typeof args.filter === "string" && args.filter !== "all" ? args.filter : null;
|
|
23028
|
-
const auditPath =
|
|
23029
|
-
if (!
|
|
23030
|
-
const rawLines =
|
|
23039
|
+
const auditPath = import_path46.default.join(import_os40.default.homedir(), ".node9", "audit.log");
|
|
23040
|
+
if (!import_fs44.default.existsSync(auditPath)) return "No audit log found.";
|
|
23041
|
+
const rawLines = import_fs44.default.readFileSync(auditPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
23031
23042
|
const parsed = [];
|
|
23032
23043
|
for (const line of rawLines) {
|
|
23033
23044
|
try {
|
|
@@ -23362,7 +23373,7 @@ function registerTrustCommand(program2) {
|
|
|
23362
23373
|
// src/cli/commands/mcp-pin.ts
|
|
23363
23374
|
var import_chalk21 = __toESM(require("chalk"));
|
|
23364
23375
|
init_mcp_pin();
|
|
23365
|
-
var
|
|
23376
|
+
var import_fs45 = __toESM(require("fs"));
|
|
23366
23377
|
function registerMcpPinCommand(program2) {
|
|
23367
23378
|
const pinCmd = program2.command("mcp").description("Manage MCP server tool definition pinning (rug pull defense)");
|
|
23368
23379
|
const pinSubCmd = pinCmd.command("pin").description("Manage pinned MCP server tool definitions");
|
|
@@ -23373,7 +23384,7 @@ function registerMcpPinCommand(program2) {
|
|
|
23373
23384
|
let repoCorrupt = false;
|
|
23374
23385
|
if (found.source === "repo") {
|
|
23375
23386
|
try {
|
|
23376
|
-
const raw =
|
|
23387
|
+
const raw = import_fs45.default.readFileSync(found.path, "utf-8");
|
|
23377
23388
|
const parsed = JSON.parse(raw);
|
|
23378
23389
|
repoEntries = parsed.servers ?? {};
|
|
23379
23390
|
} catch {
|
|
@@ -23686,9 +23697,9 @@ init_scan();
|
|
|
23686
23697
|
|
|
23687
23698
|
// src/cli/commands/sessions.ts
|
|
23688
23699
|
var import_chalk24 = __toESM(require("chalk"));
|
|
23689
|
-
var
|
|
23690
|
-
var
|
|
23691
|
-
var
|
|
23700
|
+
var import_fs46 = __toESM(require("fs"));
|
|
23701
|
+
var import_path47 = __toESM(require("path"));
|
|
23702
|
+
var import_os41 = __toESM(require("os"));
|
|
23692
23703
|
init_scan_summary();
|
|
23693
23704
|
init_litellm();
|
|
23694
23705
|
init_cost_gemini();
|
|
@@ -23709,10 +23720,10 @@ function encodeProjectPath(projectPath) {
|
|
|
23709
23720
|
}
|
|
23710
23721
|
function sessionJsonlPath(projectPath, sessionId) {
|
|
23711
23722
|
const encoded = encodeProjectPath(projectPath);
|
|
23712
|
-
return
|
|
23723
|
+
return import_path47.default.join(import_os41.default.homedir(), ".claude", "projects", encoded, `${sessionId}.jsonl`);
|
|
23713
23724
|
}
|
|
23714
23725
|
function projectLabel(projectPath) {
|
|
23715
|
-
return projectPath.replace(
|
|
23726
|
+
return projectPath.replace(import_os41.default.homedir(), "~");
|
|
23716
23727
|
}
|
|
23717
23728
|
function parseHistoryLines(lines) {
|
|
23718
23729
|
const entries = [];
|
|
@@ -23781,10 +23792,10 @@ function parseSessionLines(lines) {
|
|
|
23781
23792
|
return { toolCalls, costUSD, hasSnapshot, modifiedFiles };
|
|
23782
23793
|
}
|
|
23783
23794
|
function loadAuditEntries(auditPath) {
|
|
23784
|
-
const aPath = auditPath ??
|
|
23795
|
+
const aPath = auditPath ?? import_path47.default.join(import_os41.default.homedir(), ".node9", "audit.log");
|
|
23785
23796
|
let raw;
|
|
23786
23797
|
try {
|
|
23787
|
-
raw =
|
|
23798
|
+
raw = import_fs46.default.readFileSync(aPath, "utf-8");
|
|
23788
23799
|
} catch {
|
|
23789
23800
|
return [];
|
|
23790
23801
|
}
|
|
@@ -23820,8 +23831,8 @@ function auditEntriesInWindow(entries, windowStart, windowEnd) {
|
|
|
23820
23831
|
return result;
|
|
23821
23832
|
}
|
|
23822
23833
|
function buildGeminiSessions(days, allAuditEntries) {
|
|
23823
|
-
const tmpDir =
|
|
23824
|
-
if (!
|
|
23834
|
+
const tmpDir = import_path47.default.join(import_os41.default.homedir(), ".gemini", "tmp");
|
|
23835
|
+
if (!import_fs46.default.existsSync(tmpDir)) return [];
|
|
23825
23836
|
const cutoff = days !== null ? (() => {
|
|
23826
23837
|
const d = /* @__PURE__ */ new Date();
|
|
23827
23838
|
d.setDate(d.getDate() - days);
|
|
@@ -23830,35 +23841,35 @@ function buildGeminiSessions(days, allAuditEntries) {
|
|
|
23830
23841
|
})() : null;
|
|
23831
23842
|
let slugDirs;
|
|
23832
23843
|
try {
|
|
23833
|
-
slugDirs =
|
|
23844
|
+
slugDirs = import_fs46.default.readdirSync(tmpDir);
|
|
23834
23845
|
} catch {
|
|
23835
23846
|
return [];
|
|
23836
23847
|
}
|
|
23837
23848
|
const summaries = [];
|
|
23838
23849
|
for (const slug of slugDirs) {
|
|
23839
|
-
const slugPath =
|
|
23850
|
+
const slugPath = import_path47.default.join(tmpDir, slug);
|
|
23840
23851
|
try {
|
|
23841
|
-
if (!
|
|
23852
|
+
if (!import_fs46.default.statSync(slugPath).isDirectory()) continue;
|
|
23842
23853
|
} catch {
|
|
23843
23854
|
continue;
|
|
23844
23855
|
}
|
|
23845
|
-
let projectRoot =
|
|
23856
|
+
let projectRoot = import_path47.default.join(import_os41.default.homedir(), slug);
|
|
23846
23857
|
try {
|
|
23847
|
-
projectRoot =
|
|
23858
|
+
projectRoot = import_fs46.default.readFileSync(import_path47.default.join(slugPath, ".project_root"), "utf-8").trim();
|
|
23848
23859
|
} catch {
|
|
23849
23860
|
}
|
|
23850
|
-
const chatsDir =
|
|
23851
|
-
if (!
|
|
23861
|
+
const chatsDir = import_path47.default.join(slugPath, "chats");
|
|
23862
|
+
if (!import_fs46.default.existsSync(chatsDir)) continue;
|
|
23852
23863
|
let chatFiles;
|
|
23853
23864
|
try {
|
|
23854
|
-
chatFiles =
|
|
23865
|
+
chatFiles = import_fs46.default.readdirSync(chatsDir).filter((f) => f.endsWith(".json"));
|
|
23855
23866
|
} catch {
|
|
23856
23867
|
continue;
|
|
23857
23868
|
}
|
|
23858
23869
|
for (const chatFile of chatFiles) {
|
|
23859
23870
|
let raw;
|
|
23860
23871
|
try {
|
|
23861
|
-
raw =
|
|
23872
|
+
raw = import_fs46.default.readFileSync(import_path47.default.join(chatsDir, chatFile), "utf-8");
|
|
23862
23873
|
} catch {
|
|
23863
23874
|
continue;
|
|
23864
23875
|
}
|
|
@@ -23938,8 +23949,8 @@ function buildGeminiSessions(days, allAuditEntries) {
|
|
|
23938
23949
|
return summaries;
|
|
23939
23950
|
}
|
|
23940
23951
|
function buildCodexSessions(days, allAuditEntries) {
|
|
23941
|
-
const sessionsBase =
|
|
23942
|
-
if (!
|
|
23952
|
+
const sessionsBase = import_path47.default.join(import_os41.default.homedir(), ".codex", "sessions");
|
|
23953
|
+
if (!import_fs46.default.existsSync(sessionsBase)) return [];
|
|
23943
23954
|
const cutoff = days !== null ? (() => {
|
|
23944
23955
|
const d = /* @__PURE__ */ new Date();
|
|
23945
23956
|
d.setDate(d.getDate() - days);
|
|
@@ -23948,29 +23959,29 @@ function buildCodexSessions(days, allAuditEntries) {
|
|
|
23948
23959
|
})() : null;
|
|
23949
23960
|
const jsonlFiles = [];
|
|
23950
23961
|
try {
|
|
23951
|
-
for (const year of
|
|
23952
|
-
const yearPath =
|
|
23962
|
+
for (const year of import_fs46.default.readdirSync(sessionsBase)) {
|
|
23963
|
+
const yearPath = import_path47.default.join(sessionsBase, year);
|
|
23953
23964
|
try {
|
|
23954
|
-
if (!
|
|
23965
|
+
if (!import_fs46.default.statSync(yearPath).isDirectory()) continue;
|
|
23955
23966
|
} catch {
|
|
23956
23967
|
continue;
|
|
23957
23968
|
}
|
|
23958
|
-
for (const month of
|
|
23959
|
-
const monthPath =
|
|
23969
|
+
for (const month of import_fs46.default.readdirSync(yearPath)) {
|
|
23970
|
+
const monthPath = import_path47.default.join(yearPath, month);
|
|
23960
23971
|
try {
|
|
23961
|
-
if (!
|
|
23972
|
+
if (!import_fs46.default.statSync(monthPath).isDirectory()) continue;
|
|
23962
23973
|
} catch {
|
|
23963
23974
|
continue;
|
|
23964
23975
|
}
|
|
23965
|
-
for (const day of
|
|
23966
|
-
const dayPath =
|
|
23976
|
+
for (const day of import_fs46.default.readdirSync(monthPath)) {
|
|
23977
|
+
const dayPath = import_path47.default.join(monthPath, day);
|
|
23967
23978
|
try {
|
|
23968
|
-
if (!
|
|
23979
|
+
if (!import_fs46.default.statSync(dayPath).isDirectory()) continue;
|
|
23969
23980
|
} catch {
|
|
23970
23981
|
continue;
|
|
23971
23982
|
}
|
|
23972
|
-
for (const file of
|
|
23973
|
-
if (file.endsWith(".jsonl")) jsonlFiles.push(
|
|
23983
|
+
for (const file of import_fs46.default.readdirSync(dayPath)) {
|
|
23984
|
+
if (file.endsWith(".jsonl")) jsonlFiles.push(import_path47.default.join(dayPath, file));
|
|
23974
23985
|
}
|
|
23975
23986
|
}
|
|
23976
23987
|
}
|
|
@@ -23982,7 +23993,7 @@ function buildCodexSessions(days, allAuditEntries) {
|
|
|
23982
23993
|
for (const filePath of jsonlFiles) {
|
|
23983
23994
|
let lines;
|
|
23984
23995
|
try {
|
|
23985
|
-
lines =
|
|
23996
|
+
lines = import_fs46.default.readFileSync(filePath, "utf-8").split("\n");
|
|
23986
23997
|
} catch {
|
|
23987
23998
|
continue;
|
|
23988
23999
|
}
|
|
@@ -24068,10 +24079,10 @@ function buildCodexSessions(days, allAuditEntries) {
|
|
|
24068
24079
|
return summaries;
|
|
24069
24080
|
}
|
|
24070
24081
|
function buildSessions(days, historyPath) {
|
|
24071
|
-
const hPath = historyPath ??
|
|
24082
|
+
const hPath = historyPath ?? import_path47.default.join(import_os41.default.homedir(), ".claude", "history.jsonl");
|
|
24072
24083
|
let historyRaw = "";
|
|
24073
24084
|
try {
|
|
24074
|
-
historyRaw =
|
|
24085
|
+
historyRaw = import_fs46.default.readFileSync(hPath, "utf-8");
|
|
24075
24086
|
} catch {
|
|
24076
24087
|
}
|
|
24077
24088
|
const cutoff = days !== null ? (() => {
|
|
@@ -24095,7 +24106,7 @@ function buildSessions(days, historyPath) {
|
|
|
24095
24106
|
const jsonlFile = sessionJsonlPath(entry.project, entry.sessionId);
|
|
24096
24107
|
let sessionLines = [];
|
|
24097
24108
|
try {
|
|
24098
|
-
sessionLines =
|
|
24109
|
+
sessionLines = import_fs46.default.readFileSync(jsonlFile, "utf-8").split("\n");
|
|
24099
24110
|
} catch {
|
|
24100
24111
|
}
|
|
24101
24112
|
const { toolCalls, costUSD, hasSnapshot, modifiedFiles } = parseSessionLines(sessionLines);
|
|
@@ -24395,12 +24406,12 @@ function registerSessionsCommand(program2) {
|
|
|
24395
24406
|
|
|
24396
24407
|
// src/cli/commands/skill-pin.ts
|
|
24397
24408
|
var import_chalk25 = __toESM(require("chalk"));
|
|
24398
|
-
var
|
|
24399
|
-
var
|
|
24400
|
-
var
|
|
24409
|
+
var import_fs47 = __toESM(require("fs"));
|
|
24410
|
+
var import_os42 = __toESM(require("os"));
|
|
24411
|
+
var import_path48 = __toESM(require("path"));
|
|
24401
24412
|
function wipeSkillSessions() {
|
|
24402
24413
|
try {
|
|
24403
|
-
|
|
24414
|
+
import_fs47.default.rmSync(import_path48.default.join(import_os42.default.homedir(), ".node9", "skill-sessions"), {
|
|
24404
24415
|
recursive: true,
|
|
24405
24416
|
force: true
|
|
24406
24417
|
});
|
|
@@ -24482,15 +24493,15 @@ function registerSkillPinCommand(program2) {
|
|
|
24482
24493
|
}
|
|
24483
24494
|
|
|
24484
24495
|
// src/cli/commands/decisions.ts
|
|
24485
|
-
var
|
|
24486
|
-
var
|
|
24487
|
-
var
|
|
24496
|
+
var import_fs48 = __toESM(require("fs"));
|
|
24497
|
+
var import_os43 = __toESM(require("os"));
|
|
24498
|
+
var import_path49 = __toESM(require("path"));
|
|
24488
24499
|
var import_chalk26 = __toESM(require("chalk"));
|
|
24489
|
-
var DECISIONS_FILE2 =
|
|
24500
|
+
var DECISIONS_FILE2 = import_path49.default.join(import_os43.default.homedir(), ".node9", "decisions.json");
|
|
24490
24501
|
function readDecisions() {
|
|
24491
24502
|
try {
|
|
24492
|
-
if (!
|
|
24493
|
-
const raw =
|
|
24503
|
+
if (!import_fs48.default.existsSync(DECISIONS_FILE2)) return {};
|
|
24504
|
+
const raw = import_fs48.default.readFileSync(DECISIONS_FILE2, "utf-8");
|
|
24494
24505
|
const parsed = JSON.parse(raw);
|
|
24495
24506
|
const out = {};
|
|
24496
24507
|
for (const [k, v] of Object.entries(parsed)) {
|
|
@@ -24502,11 +24513,11 @@ function readDecisions() {
|
|
|
24502
24513
|
}
|
|
24503
24514
|
}
|
|
24504
24515
|
function writeDecisions(d) {
|
|
24505
|
-
const dir =
|
|
24506
|
-
if (!
|
|
24516
|
+
const dir = import_path49.default.dirname(DECISIONS_FILE2);
|
|
24517
|
+
if (!import_fs48.default.existsSync(dir)) import_fs48.default.mkdirSync(dir, { recursive: true });
|
|
24507
24518
|
const tmp = `${DECISIONS_FILE2}.${process.pid}.tmp`;
|
|
24508
|
-
|
|
24509
|
-
|
|
24519
|
+
import_fs48.default.writeFileSync(tmp, JSON.stringify(d, null, 2));
|
|
24520
|
+
import_fs48.default.renameSync(tmp, DECISIONS_FILE2);
|
|
24510
24521
|
}
|
|
24511
24522
|
function registerDecisionsCommand(program2) {
|
|
24512
24523
|
const cmd = program2.command("decisions").description('Manage persistent "Always Allow" / "Always Deny" tool decisions');
|
|
@@ -24563,18 +24574,18 @@ Persistent decisions (${entries.length})
|
|
|
24563
24574
|
|
|
24564
24575
|
// src/cli/commands/dlp.ts
|
|
24565
24576
|
var import_chalk27 = __toESM(require("chalk"));
|
|
24566
|
-
var
|
|
24567
|
-
var
|
|
24568
|
-
var
|
|
24569
|
-
var AUDIT_LOG =
|
|
24570
|
-
var RESOLVED_FILE =
|
|
24577
|
+
var import_fs49 = __toESM(require("fs"));
|
|
24578
|
+
var import_path50 = __toESM(require("path"));
|
|
24579
|
+
var import_os44 = __toESM(require("os"));
|
|
24580
|
+
var AUDIT_LOG = import_path50.default.join(import_os44.default.homedir(), ".node9", "audit.log");
|
|
24581
|
+
var RESOLVED_FILE = import_path50.default.join(import_os44.default.homedir(), ".node9", "dlp-resolved.json");
|
|
24571
24582
|
var ANSI_RE = /\x1b(?:\[[0-9;?]*[a-zA-Z]|\][^\x07\x1b]*(?:\x07|\x1b\\)|[@-_])/g;
|
|
24572
24583
|
function stripAnsi(s) {
|
|
24573
24584
|
return s.replace(ANSI_RE, "");
|
|
24574
24585
|
}
|
|
24575
24586
|
function loadResolved() {
|
|
24576
24587
|
try {
|
|
24577
|
-
const raw = JSON.parse(
|
|
24588
|
+
const raw = JSON.parse(import_fs49.default.readFileSync(RESOLVED_FILE, "utf-8"));
|
|
24578
24589
|
return new Set(raw);
|
|
24579
24590
|
} catch {
|
|
24580
24591
|
return /* @__PURE__ */ new Set();
|
|
@@ -24582,13 +24593,13 @@ function loadResolved() {
|
|
|
24582
24593
|
}
|
|
24583
24594
|
function saveResolved(resolved) {
|
|
24584
24595
|
try {
|
|
24585
|
-
|
|
24596
|
+
import_fs49.default.writeFileSync(RESOLVED_FILE, JSON.stringify([...resolved], null, 2), { mode: 384 });
|
|
24586
24597
|
} catch {
|
|
24587
24598
|
}
|
|
24588
24599
|
}
|
|
24589
24600
|
function loadDlpFindings() {
|
|
24590
|
-
if (!
|
|
24591
|
-
return
|
|
24601
|
+
if (!import_fs49.default.existsSync(AUDIT_LOG)) return [];
|
|
24602
|
+
return import_fs49.default.readFileSync(AUDIT_LOG, "utf-8").split("\n").flatMap((line) => {
|
|
24592
24603
|
if (!line.trim()) return [];
|
|
24593
24604
|
try {
|
|
24594
24605
|
const e = JSON.parse(line);
|
|
@@ -24686,15 +24697,15 @@ function registerDlpCommand(program2) {
|
|
|
24686
24697
|
|
|
24687
24698
|
// src/cli/commands/mask.ts
|
|
24688
24699
|
var import_chalk28 = __toESM(require("chalk"));
|
|
24689
|
-
var
|
|
24690
|
-
var
|
|
24691
|
-
var
|
|
24700
|
+
var import_fs50 = __toESM(require("fs"));
|
|
24701
|
+
var import_path51 = __toESM(require("path"));
|
|
24702
|
+
var import_os45 = __toESM(require("os"));
|
|
24692
24703
|
init_dlp();
|
|
24693
24704
|
function findJsonlFiles(dir) {
|
|
24694
24705
|
const results = [];
|
|
24695
|
-
if (!
|
|
24696
|
-
for (const entry of
|
|
24697
|
-
const full =
|
|
24706
|
+
if (!import_fs50.default.existsSync(dir)) return results;
|
|
24707
|
+
for (const entry of import_fs50.default.readdirSync(dir, { withFileTypes: true })) {
|
|
24708
|
+
const full = import_path51.default.join(dir, entry.name);
|
|
24698
24709
|
if (entry.isDirectory()) results.push(...findJsonlFiles(full));
|
|
24699
24710
|
else if (entry.isFile() && entry.name.endsWith(".jsonl")) results.push(full);
|
|
24700
24711
|
}
|
|
@@ -24737,7 +24748,7 @@ function redactJson(obj) {
|
|
|
24737
24748
|
function processFile(filePath, dryRun) {
|
|
24738
24749
|
let raw;
|
|
24739
24750
|
try {
|
|
24740
|
-
raw =
|
|
24751
|
+
raw = import_fs50.default.readFileSync(filePath, "utf-8");
|
|
24741
24752
|
} catch {
|
|
24742
24753
|
return { redactedLines: 0, patterns: [] };
|
|
24743
24754
|
}
|
|
@@ -24769,14 +24780,14 @@ function processFile(filePath, dryRun) {
|
|
|
24769
24780
|
}
|
|
24770
24781
|
}
|
|
24771
24782
|
if (!dryRun && redactedLines > 0) {
|
|
24772
|
-
|
|
24783
|
+
import_fs50.default.writeFileSync(filePath, newLines.join("\n"), "utf-8");
|
|
24773
24784
|
}
|
|
24774
24785
|
return { redactedLines, patterns };
|
|
24775
24786
|
}
|
|
24776
24787
|
function processJsonFile(filePath, dryRun) {
|
|
24777
24788
|
let raw;
|
|
24778
24789
|
try {
|
|
24779
|
-
raw =
|
|
24790
|
+
raw = import_fs50.default.readFileSync(filePath, "utf-8");
|
|
24780
24791
|
} catch {
|
|
24781
24792
|
return { redactedLines: 0, patterns: [] };
|
|
24782
24793
|
}
|
|
@@ -24789,15 +24800,15 @@ function processJsonFile(filePath, dryRun) {
|
|
|
24789
24800
|
const { value, modified, found } = redactJson(parsed);
|
|
24790
24801
|
if (!modified) return { redactedLines: 0, patterns: [] };
|
|
24791
24802
|
if (!dryRun) {
|
|
24792
|
-
|
|
24803
|
+
import_fs50.default.writeFileSync(filePath, JSON.stringify(value, null, 2), "utf-8");
|
|
24793
24804
|
}
|
|
24794
24805
|
return { redactedLines: 1, patterns: found };
|
|
24795
24806
|
}
|
|
24796
24807
|
function findJsonFiles(dir) {
|
|
24797
24808
|
const results = [];
|
|
24798
|
-
if (!
|
|
24799
|
-
for (const entry of
|
|
24800
|
-
const full =
|
|
24809
|
+
if (!import_fs50.default.existsSync(dir)) return results;
|
|
24810
|
+
for (const entry of import_fs50.default.readdirSync(dir, { withFileTypes: true })) {
|
|
24811
|
+
const full = import_path51.default.join(dir, entry.name);
|
|
24801
24812
|
if (entry.isDirectory()) results.push(...findJsonFiles(full));
|
|
24802
24813
|
else if (entry.isFile() && entry.name.endsWith(".json")) results.push(full);
|
|
24803
24814
|
}
|
|
@@ -24806,9 +24817,9 @@ function findJsonFiles(dir) {
|
|
|
24806
24817
|
function registerMaskCommand(program2) {
|
|
24807
24818
|
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) => {
|
|
24808
24819
|
const dryRun = !!options.dryRun;
|
|
24809
|
-
const home =
|
|
24810
|
-
const claudeDir =
|
|
24811
|
-
const geminiDir =
|
|
24820
|
+
const home = import_os45.default.homedir();
|
|
24821
|
+
const claudeDir = import_path51.default.join(home, ".claude", "projects");
|
|
24822
|
+
const geminiDir = import_path51.default.join(home, ".gemini", "tmp");
|
|
24812
24823
|
const allFiles = [
|
|
24813
24824
|
...findJsonlFiles(claudeDir).map((p) => ({ path: p, type: "jsonl" })),
|
|
24814
24825
|
...findJsonFiles(geminiDir).map((p) => ({ path: p, type: "json" }))
|
|
@@ -24816,7 +24827,7 @@ function registerMaskCommand(program2) {
|
|
|
24816
24827
|
const cutoff = options.all ? null : new Date(Date.now() - 30 * 24 * 60 * 60 * 1e3);
|
|
24817
24828
|
const filtered = cutoff ? allFiles.filter((f) => {
|
|
24818
24829
|
try {
|
|
24819
|
-
return
|
|
24830
|
+
return import_fs50.default.statSync(f.path).mtime >= cutoff;
|
|
24820
24831
|
} catch {
|
|
24821
24832
|
return false;
|
|
24822
24833
|
}
|
|
@@ -24872,20 +24883,20 @@ function registerMaskCommand(program2) {
|
|
|
24872
24883
|
// src/cli.ts
|
|
24873
24884
|
init_blast();
|
|
24874
24885
|
var { version } = JSON.parse(
|
|
24875
|
-
|
|
24886
|
+
import_fs53.default.readFileSync(import_path54.default.join(__dirname, "../package.json"), "utf-8")
|
|
24876
24887
|
);
|
|
24877
24888
|
var program = new import_commander.Command();
|
|
24878
24889
|
program.name("node9").description("The Sudo Command for AI Agents").version(version);
|
|
24879
24890
|
program.command("login").argument("<apiKey>").option("--local", "Save key for audit/logging only \u2014 local config still controls all decisions").option("--profile <name>", 'Save as a named profile (default: "default")').action((apiKey, options) => {
|
|
24880
24891
|
const DEFAULT_API_URL2 = "https://api.node9.ai/api/v1/intercept";
|
|
24881
|
-
const credPath =
|
|
24882
|
-
if (!
|
|
24883
|
-
|
|
24892
|
+
const credPath = import_path54.default.join(import_os48.default.homedir(), ".node9", "credentials.json");
|
|
24893
|
+
if (!import_fs53.default.existsSync(import_path54.default.dirname(credPath)))
|
|
24894
|
+
import_fs53.default.mkdirSync(import_path54.default.dirname(credPath), { recursive: true });
|
|
24884
24895
|
const profileName = options.profile || "default";
|
|
24885
24896
|
let existingCreds = {};
|
|
24886
24897
|
try {
|
|
24887
|
-
if (
|
|
24888
|
-
const raw = JSON.parse(
|
|
24898
|
+
if (import_fs53.default.existsSync(credPath)) {
|
|
24899
|
+
const raw = JSON.parse(import_fs53.default.readFileSync(credPath, "utf-8"));
|
|
24889
24900
|
if (raw.apiKey) {
|
|
24890
24901
|
existingCreds = {
|
|
24891
24902
|
default: { apiKey: raw.apiKey, apiUrl: raw.apiUrl || DEFAULT_API_URL2 }
|
|
@@ -24897,14 +24908,14 @@ program.command("login").argument("<apiKey>").option("--local", "Save key for au
|
|
|
24897
24908
|
} catch {
|
|
24898
24909
|
}
|
|
24899
24910
|
existingCreds[profileName] = { apiKey, apiUrl: DEFAULT_API_URL2 };
|
|
24900
|
-
|
|
24911
|
+
import_fs53.default.writeFileSync(credPath, JSON.stringify(existingCreds, null, 2), { mode: 384 });
|
|
24901
24912
|
let effectiveCloud = null;
|
|
24902
24913
|
if (profileName === "default") {
|
|
24903
|
-
const configPath =
|
|
24914
|
+
const configPath = import_path54.default.join(import_os48.default.homedir(), ".node9", "config.json");
|
|
24904
24915
|
let config = {};
|
|
24905
24916
|
try {
|
|
24906
|
-
if (
|
|
24907
|
-
config = JSON.parse(
|
|
24917
|
+
if (import_fs53.default.existsSync(configPath))
|
|
24918
|
+
config = JSON.parse(import_fs53.default.readFileSync(configPath, "utf-8"));
|
|
24908
24919
|
} catch {
|
|
24909
24920
|
}
|
|
24910
24921
|
if (!config.settings || typeof config.settings !== "object") config.settings = {};
|
|
@@ -24919,9 +24930,9 @@ program.command("login").argument("<apiKey>").option("--local", "Save key for au
|
|
|
24919
24930
|
approvers.cloud = false;
|
|
24920
24931
|
}
|
|
24921
24932
|
s.approvers = approvers;
|
|
24922
|
-
if (!
|
|
24923
|
-
|
|
24924
|
-
|
|
24933
|
+
if (!import_fs53.default.existsSync(import_path54.default.dirname(configPath)))
|
|
24934
|
+
import_fs53.default.mkdirSync(import_path54.default.dirname(configPath), { recursive: true });
|
|
24935
|
+
import_fs53.default.writeFileSync(configPath, JSON.stringify(config, null, 2), { mode: 384 });
|
|
24925
24936
|
effectiveCloud = approvers.cloud === true;
|
|
24926
24937
|
}
|
|
24927
24938
|
if (options.profile && profileName !== "default") {
|
|
@@ -25080,15 +25091,15 @@ program.command("uninstall").description("Remove all Node9 hooks and optionally
|
|
|
25080
25091
|
}
|
|
25081
25092
|
}
|
|
25082
25093
|
if (options.purge) {
|
|
25083
|
-
const node9Dir =
|
|
25084
|
-
if (
|
|
25094
|
+
const node9Dir = import_path54.default.join(import_os48.default.homedir(), ".node9");
|
|
25095
|
+
if (import_fs53.default.existsSync(node9Dir)) {
|
|
25085
25096
|
const confirmed = await (0, import_prompts2.confirm)({
|
|
25086
25097
|
message: `Permanently delete ${node9Dir} (config, audit log, credentials)?`,
|
|
25087
25098
|
default: false
|
|
25088
25099
|
});
|
|
25089
25100
|
if (confirmed) {
|
|
25090
|
-
|
|
25091
|
-
if (
|
|
25101
|
+
import_fs53.default.rmSync(node9Dir, { recursive: true });
|
|
25102
|
+
if (import_fs53.default.existsSync(node9Dir)) {
|
|
25092
25103
|
console.error(
|
|
25093
25104
|
import_chalk30.default.red("\n \u26A0\uFE0F ~/.node9/ could not be fully deleted \u2014 remove it manually.")
|
|
25094
25105
|
);
|
|
@@ -25203,7 +25214,7 @@ program.command("tail").description("Stream live agent activity to the terminal"
|
|
|
25203
25214
|
});
|
|
25204
25215
|
program.command("monitor").description("Live interactive dashboard \u2014 activity feed, approvals, security signals").action(async () => {
|
|
25205
25216
|
try {
|
|
25206
|
-
const dashboardPath =
|
|
25217
|
+
const dashboardPath = import_path54.default.join(__dirname, "dashboard.mjs");
|
|
25207
25218
|
const dynamicImport = new Function("id", "return import(id)");
|
|
25208
25219
|
const mod = await dynamicImport(`file://${dashboardPath}`);
|
|
25209
25220
|
await mod.startMonitor();
|
|
@@ -25241,14 +25252,14 @@ Claude Code spawns this command every ~300ms and writes a JSON payload to stdin.
|
|
|
25241
25252
|
Run "node9 addto claude" to register it as the statusLine.`
|
|
25242
25253
|
).argument("[subcommand]", 'Optional: "debug on" / "debug off" to toggle stdin logging').argument("[state]", 'on|off \u2014 used with "debug" subcommand').action(async (subcommand, state) => {
|
|
25243
25254
|
if (subcommand === "debug") {
|
|
25244
|
-
const flagFile =
|
|
25255
|
+
const flagFile = import_path54.default.join(import_os48.default.homedir(), ".node9", "hud-debug");
|
|
25245
25256
|
if (state === "on") {
|
|
25246
|
-
|
|
25247
|
-
|
|
25257
|
+
import_fs53.default.mkdirSync(import_path54.default.dirname(flagFile), { recursive: true });
|
|
25258
|
+
import_fs53.default.writeFileSync(flagFile, "");
|
|
25248
25259
|
console.log("HUD debug logging enabled \u2192 ~/.node9/hud-debug.log");
|
|
25249
25260
|
console.log("Tail it with: tail -f ~/.node9/hud-debug.log");
|
|
25250
25261
|
} else if (state === "off") {
|
|
25251
|
-
if (
|
|
25262
|
+
if (import_fs53.default.existsSync(flagFile)) import_fs53.default.unlinkSync(flagFile);
|
|
25252
25263
|
console.log("HUD debug logging disabled.");
|
|
25253
25264
|
} else {
|
|
25254
25265
|
console.error("Usage: node9 hud debug on|off");
|
|
@@ -25365,9 +25376,9 @@ if (process.argv[2] !== "daemon") {
|
|
|
25365
25376
|
const isCheckHook = process.argv[2] === "check";
|
|
25366
25377
|
if (isCheckHook) {
|
|
25367
25378
|
if (process.env.NODE9_DEBUG === "1" || getConfig().settings.enableHookLogDebug) {
|
|
25368
|
-
const logPath =
|
|
25379
|
+
const logPath = import_path54.default.join(import_os48.default.homedir(), ".node9", "hook-debug.log");
|
|
25369
25380
|
const msg = reason instanceof Error ? reason.message : String(reason);
|
|
25370
|
-
|
|
25381
|
+
import_fs53.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] UNHANDLED: ${msg}
|
|
25371
25382
|
`);
|
|
25372
25383
|
}
|
|
25373
25384
|
process.exit(0);
|