@node9/proxy 1.11.13 → 1.12.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/README.md +1 -1
- package/dist/cli.js +287 -251
- package/dist/cli.mjs +274 -238
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -147,8 +147,8 @@ function sanitizeConfig(raw) {
|
|
|
147
147
|
}
|
|
148
148
|
}
|
|
149
149
|
const lines = result.error.issues.map((issue) => {
|
|
150
|
-
const
|
|
151
|
-
return ` \u2022 ${
|
|
150
|
+
const path45 = issue.path.length > 0 ? issue.path.join(".") : "root";
|
|
151
|
+
return ` \u2022 ${path45}: ${issue.message}`;
|
|
152
152
|
});
|
|
153
153
|
return {
|
|
154
154
|
sanitized,
|
|
@@ -2066,9 +2066,9 @@ function matchesPattern(text, patterns) {
|
|
|
2066
2066
|
const withoutDotSlash = text.replace(/^\.\//, "");
|
|
2067
2067
|
return isMatch(withoutDotSlash) || isMatch(`./${withoutDotSlash}`);
|
|
2068
2068
|
}
|
|
2069
|
-
function getNestedValue(obj,
|
|
2069
|
+
function getNestedValue(obj, path45) {
|
|
2070
2070
|
if (!obj || typeof obj !== "object") return null;
|
|
2071
|
-
return
|
|
2071
|
+
return path45.split(".").reduce((prev, curr) => prev?.[curr], obj);
|
|
2072
2072
|
}
|
|
2073
2073
|
function normalizeCommandForPolicy(command) {
|
|
2074
2074
|
try {
|
|
@@ -5243,6 +5243,10 @@ var init_ui = __esm({
|
|
|
5243
5243
|
border-color: rgba(83, 155, 245, 0.35);
|
|
5244
5244
|
background: rgba(83, 155, 245, 0.04);
|
|
5245
5245
|
}
|
|
5246
|
+
.pending-card.discovery-card {
|
|
5247
|
+
border-color: rgba(120, 100, 255, 0.45);
|
|
5248
|
+
background: rgba(100, 80, 255, 0.06);
|
|
5249
|
+
}
|
|
5246
5250
|
.pending-card-header {
|
|
5247
5251
|
display: flex;
|
|
5248
5252
|
align-items: center;
|
|
@@ -7429,7 +7433,7 @@ var init_ui = __esm({
|
|
|
7429
7433
|
});
|
|
7430
7434
|
|
|
7431
7435
|
try {
|
|
7432
|
-
await fetch('/mcp/approve', {
|
|
7436
|
+
const res = await fetch('/mcp/approve', {
|
|
7433
7437
|
method: 'POST',
|
|
7434
7438
|
headers: {
|
|
7435
7439
|
'Content-Type': 'application/json',
|
|
@@ -7437,9 +7441,19 @@ var init_ui = __esm({
|
|
|
7437
7441
|
},
|
|
7438
7442
|
body: JSON.stringify({ id, serverKey, disabledTools }),
|
|
7439
7443
|
});
|
|
7444
|
+
if (!res.ok) {
|
|
7445
|
+
showToast(
|
|
7446
|
+
'\u26A0\uFE0F',
|
|
7447
|
+
'Approval failed',
|
|
7448
|
+
\`Server responded with \${res.status}\`,
|
|
7449
|
+
'toast-block'
|
|
7450
|
+
);
|
|
7451
|
+
return;
|
|
7452
|
+
}
|
|
7440
7453
|
closeMcpReview();
|
|
7441
7454
|
refreshMcpTools();
|
|
7442
7455
|
} catch (err) {
|
|
7456
|
+
showToast('\u26A0\uFE0F', 'Approval failed', 'Network error \u2014 check the daemon', 'toast-block');
|
|
7443
7457
|
console.error('Failed to approve MCP server:', err);
|
|
7444
7458
|
}
|
|
7445
7459
|
}
|
|
@@ -8254,6 +8268,10 @@ var init_ui2 = __esm({
|
|
|
8254
8268
|
|
|
8255
8269
|
// src/cli/daemon-starter.ts
|
|
8256
8270
|
import { spawn as spawn2, execSync } from "child_process";
|
|
8271
|
+
import path16 from "path";
|
|
8272
|
+
function isTestingMode() {
|
|
8273
|
+
return /^(1|true|yes)$/i.test(process.env.NODE9_TESTING ?? "");
|
|
8274
|
+
}
|
|
8257
8275
|
function openBrowserLocal() {
|
|
8258
8276
|
const url = `http://${DAEMON_HOST}:${DAEMON_PORT}/`;
|
|
8259
8277
|
try {
|
|
@@ -8264,8 +8282,9 @@ function openBrowserLocal() {
|
|
|
8264
8282
|
} catch {
|
|
8265
8283
|
}
|
|
8266
8284
|
}
|
|
8267
|
-
async function autoStartDaemonAndWait() {
|
|
8268
|
-
if (
|
|
8285
|
+
async function autoStartDaemonAndWait(openBrowser2 = true) {
|
|
8286
|
+
if (isTestingMode()) return false;
|
|
8287
|
+
if (!path16.isAbsolute(process.argv[1])) return false;
|
|
8269
8288
|
try {
|
|
8270
8289
|
const child = spawn2(process.execPath, [process.argv[1], "daemon"], {
|
|
8271
8290
|
detached: true,
|
|
@@ -8283,7 +8302,9 @@ async function autoStartDaemonAndWait() {
|
|
|
8283
8302
|
signal: AbortSignal.timeout(500)
|
|
8284
8303
|
});
|
|
8285
8304
|
if (res.ok) {
|
|
8286
|
-
|
|
8305
|
+
if (openBrowser2) {
|
|
8306
|
+
openBrowserLocal();
|
|
8307
|
+
}
|
|
8287
8308
|
return true;
|
|
8288
8309
|
}
|
|
8289
8310
|
} catch {
|
|
@@ -8492,7 +8513,7 @@ var init_scan_summary = __esm({
|
|
|
8492
8513
|
// src/cli/commands/scan.ts
|
|
8493
8514
|
import chalk2 from "chalk";
|
|
8494
8515
|
import fs13 from "fs";
|
|
8495
|
-
import
|
|
8516
|
+
import path17 from "path";
|
|
8496
8517
|
import os12 from "os";
|
|
8497
8518
|
function claudeModelPrice(model) {
|
|
8498
8519
|
const base = model.replace(/@.*$/, "").replace(/-\d{8}$/, "");
|
|
@@ -8592,11 +8613,11 @@ function buildRuleSources() {
|
|
|
8592
8613
|
}
|
|
8593
8614
|
function countScanFiles() {
|
|
8594
8615
|
let total = 0;
|
|
8595
|
-
const claudeDir =
|
|
8616
|
+
const claudeDir = path17.join(os12.homedir(), ".claude", "projects");
|
|
8596
8617
|
if (fs13.existsSync(claudeDir)) {
|
|
8597
8618
|
try {
|
|
8598
8619
|
for (const proj of fs13.readdirSync(claudeDir)) {
|
|
8599
|
-
const p =
|
|
8620
|
+
const p = path17.join(claudeDir, proj);
|
|
8600
8621
|
try {
|
|
8601
8622
|
if (!fs13.statSync(p).isDirectory()) continue;
|
|
8602
8623
|
total += fs13.readdirSync(p).filter((f) => f.endsWith(".jsonl") && !f.startsWith("agent-")).length;
|
|
@@ -8607,14 +8628,14 @@ function countScanFiles() {
|
|
|
8607
8628
|
} catch {
|
|
8608
8629
|
}
|
|
8609
8630
|
}
|
|
8610
|
-
const geminiDir =
|
|
8631
|
+
const geminiDir = path17.join(os12.homedir(), ".gemini", "tmp");
|
|
8611
8632
|
if (fs13.existsSync(geminiDir)) {
|
|
8612
8633
|
try {
|
|
8613
8634
|
for (const slug of fs13.readdirSync(geminiDir)) {
|
|
8614
|
-
const p =
|
|
8635
|
+
const p = path17.join(geminiDir, slug);
|
|
8615
8636
|
try {
|
|
8616
8637
|
if (!fs13.statSync(p).isDirectory()) continue;
|
|
8617
|
-
const chatsDir =
|
|
8638
|
+
const chatsDir = path17.join(p, "chats");
|
|
8618
8639
|
if (fs13.existsSync(chatsDir)) {
|
|
8619
8640
|
try {
|
|
8620
8641
|
total += fs13.readdirSync(chatsDir).filter((f) => f.endsWith(".json")).length;
|
|
@@ -8628,19 +8649,19 @@ function countScanFiles() {
|
|
|
8628
8649
|
} catch {
|
|
8629
8650
|
}
|
|
8630
8651
|
}
|
|
8631
|
-
const codexDir =
|
|
8652
|
+
const codexDir = path17.join(os12.homedir(), ".codex", "sessions");
|
|
8632
8653
|
if (fs13.existsSync(codexDir)) {
|
|
8633
8654
|
try {
|
|
8634
8655
|
for (const year of fs13.readdirSync(codexDir)) {
|
|
8635
|
-
const yp =
|
|
8656
|
+
const yp = path17.join(codexDir, year);
|
|
8636
8657
|
try {
|
|
8637
8658
|
if (!fs13.statSync(yp).isDirectory()) continue;
|
|
8638
8659
|
for (const month of fs13.readdirSync(yp)) {
|
|
8639
|
-
const mp =
|
|
8660
|
+
const mp = path17.join(yp, month);
|
|
8640
8661
|
try {
|
|
8641
8662
|
if (!fs13.statSync(mp).isDirectory()) continue;
|
|
8642
8663
|
for (const day of fs13.readdirSync(mp)) {
|
|
8643
|
-
const dp =
|
|
8664
|
+
const dp = path17.join(mp, day);
|
|
8644
8665
|
try {
|
|
8645
8666
|
if (!fs13.statSync(dp).isDirectory()) continue;
|
|
8646
8667
|
total += fs13.readdirSync(dp).filter((f) => f.endsWith(".jsonl")).length;
|
|
@@ -8672,7 +8693,7 @@ function renderProgressBar(done, total) {
|
|
|
8672
8693
|
);
|
|
8673
8694
|
}
|
|
8674
8695
|
function scanClaudeHistory(startDate, onProgress) {
|
|
8675
|
-
const projectsDir =
|
|
8696
|
+
const projectsDir = path17.join(os12.homedir(), ".claude", "projects");
|
|
8676
8697
|
const result = {
|
|
8677
8698
|
filesScanned: 0,
|
|
8678
8699
|
sessions: 0,
|
|
@@ -8694,7 +8715,7 @@ function scanClaudeHistory(startDate, onProgress) {
|
|
|
8694
8715
|
}
|
|
8695
8716
|
const ruleSources = buildRuleSources();
|
|
8696
8717
|
for (const proj of projDirs) {
|
|
8697
|
-
const projPath =
|
|
8718
|
+
const projPath = path17.join(projectsDir, proj);
|
|
8698
8719
|
try {
|
|
8699
8720
|
if (!fs13.statSync(projPath).isDirectory()) continue;
|
|
8700
8721
|
} catch {
|
|
@@ -8714,7 +8735,7 @@ function scanClaudeHistory(startDate, onProgress) {
|
|
|
8714
8735
|
const sessionId = file.replace(/\.jsonl$/, "");
|
|
8715
8736
|
let raw;
|
|
8716
8737
|
try {
|
|
8717
|
-
raw = fs13.readFileSync(
|
|
8738
|
+
raw = fs13.readFileSync(path17.join(projPath, file), "utf-8");
|
|
8718
8739
|
} catch {
|
|
8719
8740
|
continue;
|
|
8720
8741
|
}
|
|
@@ -8867,7 +8888,7 @@ function scanClaudeHistory(startDate, onProgress) {
|
|
|
8867
8888
|
return result;
|
|
8868
8889
|
}
|
|
8869
8890
|
function scanGeminiHistory(startDate, onProgress) {
|
|
8870
|
-
const tmpDir =
|
|
8891
|
+
const tmpDir = path17.join(os12.homedir(), ".gemini", "tmp");
|
|
8871
8892
|
const result = {
|
|
8872
8893
|
filesScanned: 0,
|
|
8873
8894
|
sessions: 0,
|
|
@@ -8889,7 +8910,7 @@ function scanGeminiHistory(startDate, onProgress) {
|
|
|
8889
8910
|
}
|
|
8890
8911
|
const ruleSources = buildRuleSources();
|
|
8891
8912
|
for (const slug of slugDirs) {
|
|
8892
|
-
const slugPath =
|
|
8913
|
+
const slugPath = path17.join(tmpDir, slug);
|
|
8893
8914
|
try {
|
|
8894
8915
|
if (!fs13.statSync(slugPath).isDirectory()) continue;
|
|
8895
8916
|
} catch {
|
|
@@ -8897,10 +8918,10 @@ function scanGeminiHistory(startDate, onProgress) {
|
|
|
8897
8918
|
}
|
|
8898
8919
|
let projLabel = slug;
|
|
8899
8920
|
try {
|
|
8900
|
-
projLabel = fs13.readFileSync(
|
|
8921
|
+
projLabel = fs13.readFileSync(path17.join(slugPath, ".project_root"), "utf-8").trim().replace(os12.homedir(), "~").slice(0, 40);
|
|
8901
8922
|
} catch {
|
|
8902
8923
|
}
|
|
8903
|
-
const chatsDir =
|
|
8924
|
+
const chatsDir = path17.join(slugPath, "chats");
|
|
8904
8925
|
if (!fs13.existsSync(chatsDir)) continue;
|
|
8905
8926
|
let chatFiles;
|
|
8906
8927
|
try {
|
|
@@ -8914,7 +8935,7 @@ function scanGeminiHistory(startDate, onProgress) {
|
|
|
8914
8935
|
const sessionId = chatFile.replace(/\.json$/, "");
|
|
8915
8936
|
let raw;
|
|
8916
8937
|
try {
|
|
8917
|
-
raw = fs13.readFileSync(
|
|
8938
|
+
raw = fs13.readFileSync(path17.join(chatsDir, chatFile), "utf-8");
|
|
8918
8939
|
} catch {
|
|
8919
8940
|
continue;
|
|
8920
8941
|
}
|
|
@@ -9063,7 +9084,7 @@ function scanGeminiHistory(startDate, onProgress) {
|
|
|
9063
9084
|
return result;
|
|
9064
9085
|
}
|
|
9065
9086
|
function scanCodexHistory(startDate, onProgress) {
|
|
9066
|
-
const sessionsBase =
|
|
9087
|
+
const sessionsBase = path17.join(os12.homedir(), ".codex", "sessions");
|
|
9067
9088
|
const result = {
|
|
9068
9089
|
filesScanned: 0,
|
|
9069
9090
|
sessions: 0,
|
|
@@ -9080,28 +9101,28 @@ function scanCodexHistory(startDate, onProgress) {
|
|
|
9080
9101
|
const jsonlFiles = [];
|
|
9081
9102
|
try {
|
|
9082
9103
|
for (const year of fs13.readdirSync(sessionsBase)) {
|
|
9083
|
-
const yearPath =
|
|
9104
|
+
const yearPath = path17.join(sessionsBase, year);
|
|
9084
9105
|
try {
|
|
9085
9106
|
if (!fs13.statSync(yearPath).isDirectory()) continue;
|
|
9086
9107
|
} catch {
|
|
9087
9108
|
continue;
|
|
9088
9109
|
}
|
|
9089
9110
|
for (const month of fs13.readdirSync(yearPath)) {
|
|
9090
|
-
const monthPath =
|
|
9111
|
+
const monthPath = path17.join(yearPath, month);
|
|
9091
9112
|
try {
|
|
9092
9113
|
if (!fs13.statSync(monthPath).isDirectory()) continue;
|
|
9093
9114
|
} catch {
|
|
9094
9115
|
continue;
|
|
9095
9116
|
}
|
|
9096
9117
|
for (const day of fs13.readdirSync(monthPath)) {
|
|
9097
|
-
const dayPath =
|
|
9118
|
+
const dayPath = path17.join(monthPath, day);
|
|
9098
9119
|
try {
|
|
9099
9120
|
if (!fs13.statSync(dayPath).isDirectory()) continue;
|
|
9100
9121
|
} catch {
|
|
9101
9122
|
continue;
|
|
9102
9123
|
}
|
|
9103
9124
|
for (const file of fs13.readdirSync(dayPath)) {
|
|
9104
|
-
if (file.endsWith(".jsonl")) jsonlFiles.push(
|
|
9125
|
+
if (file.endsWith(".jsonl")) jsonlFiles.push(path17.join(dayPath, file));
|
|
9105
9126
|
}
|
|
9106
9127
|
}
|
|
9107
9128
|
}
|
|
@@ -9343,7 +9364,7 @@ function registerScanCommand(program2) {
|
|
|
9343
9364
|
d.setHours(0, 0, 0, 0);
|
|
9344
9365
|
return d;
|
|
9345
9366
|
})();
|
|
9346
|
-
const isInstalled = fs13.existsSync(
|
|
9367
|
+
const isInstalled = fs13.existsSync(path17.join(os12.homedir(), ".node9", "audit.log"));
|
|
9347
9368
|
console.log("");
|
|
9348
9369
|
if (!isInstalled) {
|
|
9349
9370
|
console.log(
|
|
@@ -9568,7 +9589,7 @@ function registerScanCommand(program2) {
|
|
|
9568
9589
|
console.log(" " + chalk2.dim("\u2192 ") + chalk2.underline("https://node9.ai"));
|
|
9569
9590
|
}
|
|
9570
9591
|
console.log("");
|
|
9571
|
-
if (
|
|
9592
|
+
if (!isTestingMode() && isDaemonRunning()) {
|
|
9572
9593
|
const internalToken = getInternalToken();
|
|
9573
9594
|
if (internalToken) {
|
|
9574
9595
|
try {
|
|
@@ -9734,7 +9755,7 @@ var init_suggestion_tracker = __esm({
|
|
|
9734
9755
|
|
|
9735
9756
|
// src/daemon/taint-store.ts
|
|
9736
9757
|
import fs14 from "fs";
|
|
9737
|
-
import
|
|
9758
|
+
import path18 from "path";
|
|
9738
9759
|
var DEFAULT_TTL_MS, TaintStore;
|
|
9739
9760
|
var init_taint_store = __esm({
|
|
9740
9761
|
"src/daemon/taint-store.ts"() {
|
|
@@ -9803,9 +9824,9 @@ var init_taint_store = __esm({
|
|
|
9803
9824
|
/** Resolve to absolute path, falling back to path.resolve if file doesn't exist yet. */
|
|
9804
9825
|
_resolve(filePath) {
|
|
9805
9826
|
try {
|
|
9806
|
-
return fs14.realpathSync.native(
|
|
9827
|
+
return fs14.realpathSync.native(path18.resolve(filePath));
|
|
9807
9828
|
} catch {
|
|
9808
|
-
return
|
|
9829
|
+
return path18.resolve(filePath);
|
|
9809
9830
|
}
|
|
9810
9831
|
}
|
|
9811
9832
|
};
|
|
@@ -9923,7 +9944,7 @@ var init_session_history = __esm({
|
|
|
9923
9944
|
// src/daemon/state.ts
|
|
9924
9945
|
import net2 from "net";
|
|
9925
9946
|
import fs15 from "fs";
|
|
9926
|
-
import
|
|
9947
|
+
import path19 from "path";
|
|
9927
9948
|
import os13 from "os";
|
|
9928
9949
|
import { spawn as spawn3 } from "child_process";
|
|
9929
9950
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
@@ -9973,7 +9994,7 @@ function setCachedScanResult(result) {
|
|
|
9973
9994
|
cachedScanTs = Date.now();
|
|
9974
9995
|
}
|
|
9975
9996
|
function atomicWriteSync2(filePath, data, options) {
|
|
9976
|
-
const dir =
|
|
9997
|
+
const dir = path19.dirname(filePath);
|
|
9977
9998
|
if (!fs15.existsSync(dir)) fs15.mkdirSync(dir, { recursive: true });
|
|
9978
9999
|
const tmpPath = `${filePath}.${randomUUID3()}.tmp`;
|
|
9979
10000
|
try {
|
|
@@ -10013,7 +10034,7 @@ function appendAuditLog(data) {
|
|
|
10013
10034
|
decision: data.decision,
|
|
10014
10035
|
source: "daemon"
|
|
10015
10036
|
};
|
|
10016
|
-
const dir =
|
|
10037
|
+
const dir = path19.dirname(AUDIT_LOG_FILE);
|
|
10017
10038
|
if (!fs15.existsSync(dir)) fs15.mkdirSync(dir, { recursive: true });
|
|
10018
10039
|
fs15.appendFileSync(AUDIT_LOG_FILE, JSON.stringify(entry) + "\n");
|
|
10019
10040
|
} catch {
|
|
@@ -10277,13 +10298,13 @@ var init_state2 = __esm({
|
|
|
10277
10298
|
init_session_counters();
|
|
10278
10299
|
init_session_history();
|
|
10279
10300
|
homeDir = os13.homedir();
|
|
10280
|
-
DAEMON_PID_FILE =
|
|
10281
|
-
DECISIONS_FILE =
|
|
10282
|
-
AUDIT_LOG_FILE =
|
|
10283
|
-
TRUST_FILE2 =
|
|
10284
|
-
GLOBAL_CONFIG_FILE =
|
|
10285
|
-
CREDENTIALS_FILE =
|
|
10286
|
-
INSIGHT_COUNTS_FILE =
|
|
10301
|
+
DAEMON_PID_FILE = path19.join(homeDir, ".node9", "daemon.pid");
|
|
10302
|
+
DECISIONS_FILE = path19.join(homeDir, ".node9", "decisions.json");
|
|
10303
|
+
AUDIT_LOG_FILE = path19.join(homeDir, ".node9", "audit.log");
|
|
10304
|
+
TRUST_FILE2 = path19.join(homeDir, ".node9", "trust.json");
|
|
10305
|
+
GLOBAL_CONFIG_FILE = path19.join(homeDir, ".node9", "config.json");
|
|
10306
|
+
CREDENTIALS_FILE = path19.join(homeDir, ".node9", "credentials.json");
|
|
10307
|
+
INSIGHT_COUNTS_FILE = path19.join(homeDir, ".node9", "insight-counts.json");
|
|
10287
10308
|
pending = /* @__PURE__ */ new Map();
|
|
10288
10309
|
sseClients = /* @__PURE__ */ new Set();
|
|
10289
10310
|
suggestionTracker = new SuggestionTracker(3);
|
|
@@ -10301,7 +10322,7 @@ var init_state2 = __esm({
|
|
|
10301
10322
|
"2h": 2 * 60 * 6e4
|
|
10302
10323
|
};
|
|
10303
10324
|
autoStarted = process.env.NODE9_AUTO_STARTED === "1";
|
|
10304
|
-
ACTIVITY_SOCKET_PATH2 = process.platform === "win32" ? "\\\\.\\pipe\\node9-activity" :
|
|
10325
|
+
ACTIVITY_SOCKET_PATH2 = process.platform === "win32" ? "\\\\.\\pipe\\node9-activity" : path19.join(os13.tmpdir(), "node9-activity.sock");
|
|
10305
10326
|
ACTIVITY_RING_SIZE = 100;
|
|
10306
10327
|
activityRing = [];
|
|
10307
10328
|
LARGE_RESPONSE_RING_SIZE = 20;
|
|
@@ -10329,7 +10350,7 @@ var init_state2 = __esm({
|
|
|
10329
10350
|
|
|
10330
10351
|
// src/config/patch.ts
|
|
10331
10352
|
import fs16 from "fs";
|
|
10332
|
-
import
|
|
10353
|
+
import path20 from "path";
|
|
10333
10354
|
import os14 from "os";
|
|
10334
10355
|
function patchConfig(configPath, patch) {
|
|
10335
10356
|
let config = {};
|
|
@@ -10354,7 +10375,7 @@ function patchConfig(configPath, patch) {
|
|
|
10354
10375
|
ignored.push(patch.toolName);
|
|
10355
10376
|
}
|
|
10356
10377
|
}
|
|
10357
|
-
const dir =
|
|
10378
|
+
const dir = path20.dirname(configPath);
|
|
10358
10379
|
fs16.mkdirSync(dir, { recursive: true });
|
|
10359
10380
|
const tmp = configPath + ".node9-tmp";
|
|
10360
10381
|
try {
|
|
@@ -10380,13 +10401,13 @@ var GLOBAL_CONFIG_PATH;
|
|
|
10380
10401
|
var init_patch = __esm({
|
|
10381
10402
|
"src/config/patch.ts"() {
|
|
10382
10403
|
"use strict";
|
|
10383
|
-
GLOBAL_CONFIG_PATH =
|
|
10404
|
+
GLOBAL_CONFIG_PATH = path20.join(os14.homedir(), ".node9", "config.json");
|
|
10384
10405
|
}
|
|
10385
10406
|
});
|
|
10386
10407
|
|
|
10387
10408
|
// src/costSync.ts
|
|
10388
10409
|
import fs17 from "fs";
|
|
10389
|
-
import
|
|
10410
|
+
import path21 from "path";
|
|
10390
10411
|
import os15 from "os";
|
|
10391
10412
|
function normalizeModel(raw) {
|
|
10392
10413
|
return raw.replace(/-\d{8}$/, "");
|
|
@@ -10455,7 +10476,7 @@ function parseJSONLFile(filePath) {
|
|
|
10455
10476
|
return daily;
|
|
10456
10477
|
}
|
|
10457
10478
|
function collectEntries() {
|
|
10458
|
-
const projectsDir =
|
|
10479
|
+
const projectsDir = path21.join(os15.homedir(), ".claude", "projects");
|
|
10459
10480
|
if (!fs17.existsSync(projectsDir)) return [];
|
|
10460
10481
|
const combined = /* @__PURE__ */ new Map();
|
|
10461
10482
|
let dirs;
|
|
@@ -10465,7 +10486,7 @@ function collectEntries() {
|
|
|
10465
10486
|
return [];
|
|
10466
10487
|
}
|
|
10467
10488
|
for (const dir of dirs) {
|
|
10468
|
-
const dirPath =
|
|
10489
|
+
const dirPath = path21.join(projectsDir, dir);
|
|
10469
10490
|
try {
|
|
10470
10491
|
if (!fs17.statSync(dirPath).isDirectory()) continue;
|
|
10471
10492
|
} catch {
|
|
@@ -10478,7 +10499,7 @@ function collectEntries() {
|
|
|
10478
10499
|
continue;
|
|
10479
10500
|
}
|
|
10480
10501
|
for (const file of files) {
|
|
10481
|
-
const entries = parseJSONLFile(
|
|
10502
|
+
const entries = parseJSONLFile(path21.join(dirPath, file));
|
|
10482
10503
|
for (const [key, e] of entries) {
|
|
10483
10504
|
const prev = combined.get(key);
|
|
10484
10505
|
if (prev) {
|
|
@@ -10554,7 +10575,7 @@ var init_costSync = __esm({
|
|
|
10554
10575
|
import fs18 from "fs";
|
|
10555
10576
|
import https from "https";
|
|
10556
10577
|
import os16 from "os";
|
|
10557
|
-
import
|
|
10578
|
+
import path22 from "path";
|
|
10558
10579
|
function readCredentials() {
|
|
10559
10580
|
if (process.env.NODE9_API_KEY) {
|
|
10560
10581
|
return {
|
|
@@ -10563,7 +10584,7 @@ function readCredentials() {
|
|
|
10563
10584
|
};
|
|
10564
10585
|
}
|
|
10565
10586
|
try {
|
|
10566
|
-
const credPath =
|
|
10587
|
+
const credPath = path22.join(os16.homedir(), ".node9", "credentials.json");
|
|
10567
10588
|
const creds = JSON.parse(fs18.readFileSync(credPath, "utf-8"));
|
|
10568
10589
|
const profileName = process.env.NODE9_PROFILE ?? "default";
|
|
10569
10590
|
const profile = creds[profileName];
|
|
@@ -10626,7 +10647,7 @@ async function syncOnce() {
|
|
|
10626
10647
|
try {
|
|
10627
10648
|
const rules = await fetchCloudRules(creds.apiKey, creds.apiUrl);
|
|
10628
10649
|
const cache = { fetchedAt: (/* @__PURE__ */ new Date()).toISOString(), rules };
|
|
10629
|
-
const dir =
|
|
10650
|
+
const dir = path22.dirname(rulesCacheFile());
|
|
10630
10651
|
if (!fs18.existsSync(dir)) fs18.mkdirSync(dir, { recursive: true });
|
|
10631
10652
|
fs18.writeFileSync(rulesCacheFile(), JSON.stringify(cache, null, 2) + "\n", "utf-8");
|
|
10632
10653
|
} catch {
|
|
@@ -10640,7 +10661,7 @@ async function runCloudSync() {
|
|
|
10640
10661
|
try {
|
|
10641
10662
|
const rules = await fetchCloudRules(creds.apiKey, creds.apiUrl);
|
|
10642
10663
|
const cache = { fetchedAt: (/* @__PURE__ */ new Date()).toISOString(), rules };
|
|
10643
|
-
const dir =
|
|
10664
|
+
const dir = path22.dirname(rulesCacheFile());
|
|
10644
10665
|
if (!fs18.existsSync(dir)) fs18.mkdirSync(dir, { recursive: true });
|
|
10645
10666
|
fs18.writeFileSync(rulesCacheFile(), JSON.stringify(cache, null, 2) + "\n", "utf-8");
|
|
10646
10667
|
return { ok: true, rules: rules.length, fetchedAt: cache.fetchedAt };
|
|
@@ -10679,7 +10700,7 @@ var init_sync = __esm({
|
|
|
10679
10700
|
"src/daemon/sync.ts"() {
|
|
10680
10701
|
"use strict";
|
|
10681
10702
|
init_config();
|
|
10682
|
-
rulesCacheFile = () =>
|
|
10703
|
+
rulesCacheFile = () => path22.join(os16.homedir(), ".node9", "rules-cache.json");
|
|
10683
10704
|
DEFAULT_API_URL = "https://api.node9.ai/api/v1/policy";
|
|
10684
10705
|
DEFAULT_INTERVAL_HOURS = 5;
|
|
10685
10706
|
MIN_INTERVAL_HOURS = 1;
|
|
@@ -10688,7 +10709,7 @@ var init_sync = __esm({
|
|
|
10688
10709
|
|
|
10689
10710
|
// src/daemon/dlp-scanner.ts
|
|
10690
10711
|
import fs19 from "fs";
|
|
10691
|
-
import
|
|
10712
|
+
import path23 from "path";
|
|
10692
10713
|
import os17 from "os";
|
|
10693
10714
|
function loadIndex() {
|
|
10694
10715
|
try {
|
|
@@ -10720,11 +10741,11 @@ function runDlpScan() {
|
|
|
10720
10741
|
return;
|
|
10721
10742
|
}
|
|
10722
10743
|
for (const proj of projDirs) {
|
|
10723
|
-
const projPath =
|
|
10744
|
+
const projPath = path23.join(PROJECTS_DIR, proj);
|
|
10724
10745
|
try {
|
|
10725
10746
|
if (!fs19.lstatSync(projPath).isDirectory()) continue;
|
|
10726
10747
|
const real = fs19.realpathSync(projPath);
|
|
10727
|
-
if (!real.startsWith(PROJECTS_DIR +
|
|
10748
|
+
if (!real.startsWith(PROJECTS_DIR + path23.sep) && real !== PROJECTS_DIR) continue;
|
|
10728
10749
|
} catch {
|
|
10729
10750
|
continue;
|
|
10730
10751
|
}
|
|
@@ -10735,7 +10756,7 @@ function runDlpScan() {
|
|
|
10735
10756
|
continue;
|
|
10736
10757
|
}
|
|
10737
10758
|
for (const file of files) {
|
|
10738
|
-
const filePath =
|
|
10759
|
+
const filePath = path23.join(projPath, file);
|
|
10739
10760
|
const lastOffset = index[filePath] ?? 0;
|
|
10740
10761
|
let size;
|
|
10741
10762
|
try {
|
|
@@ -10831,17 +10852,17 @@ var init_dlp_scanner = __esm({
|
|
|
10831
10852
|
init_dlp();
|
|
10832
10853
|
init_native();
|
|
10833
10854
|
init_state2();
|
|
10834
|
-
INDEX_FILE =
|
|
10835
|
-
PROJECTS_DIR =
|
|
10855
|
+
INDEX_FILE = path23.join(os17.homedir(), ".node9", "dlp-index.json");
|
|
10856
|
+
PROJECTS_DIR = path23.join(os17.homedir(), ".claude", "projects");
|
|
10836
10857
|
}
|
|
10837
10858
|
});
|
|
10838
10859
|
|
|
10839
10860
|
// src/daemon/mcp-tools.ts
|
|
10840
10861
|
import fs20 from "fs";
|
|
10841
|
-
import
|
|
10862
|
+
import path24 from "path";
|
|
10842
10863
|
import os18 from "os";
|
|
10843
10864
|
function getMcpToolsFile() {
|
|
10844
|
-
return
|
|
10865
|
+
return path24.join(os18.homedir(), ".node9", "mcp-tools.json");
|
|
10845
10866
|
}
|
|
10846
10867
|
function readMcpToolsConfig() {
|
|
10847
10868
|
try {
|
|
@@ -10856,7 +10877,7 @@ function readMcpToolsConfig() {
|
|
|
10856
10877
|
function writeMcpToolsConfig(config) {
|
|
10857
10878
|
try {
|
|
10858
10879
|
const file = getMcpToolsFile();
|
|
10859
|
-
const dir =
|
|
10880
|
+
const dir = path24.dirname(file);
|
|
10860
10881
|
if (!fs20.existsSync(dir)) fs20.mkdirSync(dir, { recursive: true });
|
|
10861
10882
|
const tmpPath = `${file}.${os18.hostname()}.${process.pid}.tmp`;
|
|
10862
10883
|
fs20.writeFileSync(tmpPath, JSON.stringify(config, null, 2));
|
|
@@ -10908,7 +10929,7 @@ var init_mcp_tools = __esm({
|
|
|
10908
10929
|
// src/daemon/server.ts
|
|
10909
10930
|
import http from "http";
|
|
10910
10931
|
import fs21 from "fs";
|
|
10911
|
-
import
|
|
10932
|
+
import path25 from "path";
|
|
10912
10933
|
import os19 from "os";
|
|
10913
10934
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
10914
10935
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
@@ -11103,7 +11124,7 @@ data: ${JSON.stringify(item.data)}
|
|
|
11103
11124
|
status: "pending"
|
|
11104
11125
|
});
|
|
11105
11126
|
}
|
|
11106
|
-
const projectCwd = typeof cwd === "string" &&
|
|
11127
|
+
const projectCwd = typeof cwd === "string" && path25.isAbsolute(cwd) ? cwd : void 0;
|
|
11107
11128
|
const projectConfig = getConfig(projectCwd);
|
|
11108
11129
|
const browserEnabled = projectConfig.settings.approvers?.browser !== false;
|
|
11109
11130
|
const terminalEnabled = projectConfig.settings.approvers?.terminal !== false;
|
|
@@ -11467,7 +11488,7 @@ data: ${JSON.stringify(item.data)}
|
|
|
11467
11488
|
if (!validToken(req)) return res.writeHead(403).end();
|
|
11468
11489
|
const periodParam = reqUrl.searchParams.get("period") || "7d";
|
|
11469
11490
|
const period = ["today", "7d", "30d", "month"].includes(periodParam) ? periodParam : "7d";
|
|
11470
|
-
const logPath =
|
|
11491
|
+
const logPath = path25.join(os19.homedir(), ".node9", "audit.log");
|
|
11471
11492
|
if (!fs21.existsSync(logPath)) {
|
|
11472
11493
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
11473
11494
|
return res.end(
|
|
@@ -11661,8 +11682,8 @@ data: ${JSON.stringify(item.data)}
|
|
|
11661
11682
|
const body = await readBody(req);
|
|
11662
11683
|
const data = body ? JSON.parse(body) : {};
|
|
11663
11684
|
const configPath = data.configPath ?? GLOBAL_CONFIG_PATH;
|
|
11664
|
-
const node9Dir =
|
|
11665
|
-
if (!
|
|
11685
|
+
const node9Dir = path25.dirname(GLOBAL_CONFIG_PATH);
|
|
11686
|
+
if (!path25.resolve(configPath).startsWith(node9Dir + path25.sep)) {
|
|
11666
11687
|
res.writeHead(400, { "Content-Type": "application/json" });
|
|
11667
11688
|
return res.end(
|
|
11668
11689
|
JSON.stringify({ error: "configPath must be within the node9 config directory" })
|
|
@@ -11781,6 +11802,11 @@ data: ${JSON.stringify(item.data)}
|
|
|
11781
11802
|
return;
|
|
11782
11803
|
}
|
|
11783
11804
|
approveServer(serverKey, disabledTools);
|
|
11805
|
+
appendAuditLog({
|
|
11806
|
+
toolName: `mcp-server:${serverKey}`,
|
|
11807
|
+
args: { disabledTools },
|
|
11808
|
+
decision: "allow"
|
|
11809
|
+
});
|
|
11784
11810
|
broadcast("mcp-tools-updated", { serverKey, disabledTools });
|
|
11785
11811
|
res.writeHead(200).end();
|
|
11786
11812
|
return;
|
|
@@ -11799,6 +11825,11 @@ data: ${JSON.stringify(item.data)}
|
|
|
11799
11825
|
}
|
|
11800
11826
|
const status = updateServerDiscovery(serverKey, tools);
|
|
11801
11827
|
if (status === "new" || status === "drift") {
|
|
11828
|
+
appendAuditLog({
|
|
11829
|
+
toolName: `mcp-server:${serverKey}`,
|
|
11830
|
+
args: { toolCount: tools.length, status },
|
|
11831
|
+
decision: "mcp-discovered"
|
|
11832
|
+
});
|
|
11802
11833
|
const id = randomUUID4();
|
|
11803
11834
|
const entry = {
|
|
11804
11835
|
id,
|
|
@@ -11867,6 +11898,11 @@ data: ${JSON.stringify(item.data)}
|
|
|
11867
11898
|
}
|
|
11868
11899
|
clearTimeout(entry.timer);
|
|
11869
11900
|
approveServer(serverKey, disabledTools);
|
|
11901
|
+
appendAuditLog({
|
|
11902
|
+
toolName: `mcp-server:${serverKey}`,
|
|
11903
|
+
args: { disabledTools },
|
|
11904
|
+
decision: "allow"
|
|
11905
|
+
});
|
|
11870
11906
|
pending.delete(id);
|
|
11871
11907
|
broadcast("remove", { id, decision: "allow" });
|
|
11872
11908
|
res.writeHead(200).end();
|
|
@@ -11976,13 +12012,13 @@ var init_server = __esm({
|
|
|
11976
12012
|
|
|
11977
12013
|
// src/daemon/service.ts
|
|
11978
12014
|
import fs22 from "fs";
|
|
11979
|
-
import
|
|
12015
|
+
import path26 from "path";
|
|
11980
12016
|
import os20 from "os";
|
|
11981
12017
|
import { spawnSync as spawnSync3, execFileSync } from "child_process";
|
|
11982
12018
|
function resolveNode9Binary() {
|
|
11983
12019
|
try {
|
|
11984
12020
|
const script = process.argv[1];
|
|
11985
|
-
if (typeof script === "string" &&
|
|
12021
|
+
if (typeof script === "string" && path26.isAbsolute(script) && fs22.existsSync(script)) {
|
|
11986
12022
|
return fs22.realpathSync(script);
|
|
11987
12023
|
}
|
|
11988
12024
|
} catch {
|
|
@@ -12001,11 +12037,11 @@ function xmlEscape(s) {
|
|
|
12001
12037
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
12002
12038
|
}
|
|
12003
12039
|
function launchdPlist(binaryPath) {
|
|
12004
|
-
const logDir =
|
|
12040
|
+
const logDir = path26.join(os20.homedir(), ".node9");
|
|
12005
12041
|
const nodePath = xmlEscape(process.execPath);
|
|
12006
12042
|
const scriptPath = xmlEscape(binaryPath);
|
|
12007
|
-
const outLog = xmlEscape(
|
|
12008
|
-
const errLog = xmlEscape(
|
|
12043
|
+
const outLog = xmlEscape(path26.join(logDir, "daemon.log"));
|
|
12044
|
+
const errLog = xmlEscape(path26.join(logDir, "daemon-error.log"));
|
|
12009
12045
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
12010
12046
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
12011
12047
|
<plist version="1.0">
|
|
@@ -12040,7 +12076,7 @@ function launchdPlist(binaryPath) {
|
|
|
12040
12076
|
`;
|
|
12041
12077
|
}
|
|
12042
12078
|
function installLaunchd(binaryPath) {
|
|
12043
|
-
const dir =
|
|
12079
|
+
const dir = path26.dirname(LAUNCHD_PLIST);
|
|
12044
12080
|
if (!fs22.existsSync(dir)) fs22.mkdirSync(dir, { recursive: true });
|
|
12045
12081
|
fs22.writeFileSync(LAUNCHD_PLIST, launchdPlist(binaryPath), "utf-8");
|
|
12046
12082
|
spawnSync3("launchctl", ["unload", LAUNCHD_PLIST], { encoding: "utf8" });
|
|
@@ -12117,7 +12153,7 @@ function isSystemdInstalled() {
|
|
|
12117
12153
|
return fs22.existsSync(SYSTEMD_UNIT);
|
|
12118
12154
|
}
|
|
12119
12155
|
function stopRunningDaemon() {
|
|
12120
|
-
const pidFile =
|
|
12156
|
+
const pidFile = path26.join(os20.homedir(), ".node9", "daemon.pid");
|
|
12121
12157
|
if (!fs22.existsSync(pidFile)) return;
|
|
12122
12158
|
try {
|
|
12123
12159
|
const data = JSON.parse(fs22.readFileSync(pidFile, "utf-8"));
|
|
@@ -12215,9 +12251,9 @@ var init_service = __esm({
|
|
|
12215
12251
|
"src/daemon/service.ts"() {
|
|
12216
12252
|
"use strict";
|
|
12217
12253
|
LAUNCHD_LABEL = "ai.node9.daemon";
|
|
12218
|
-
LAUNCHD_PLIST =
|
|
12219
|
-
SYSTEMD_UNIT_DIR =
|
|
12220
|
-
SYSTEMD_UNIT =
|
|
12254
|
+
LAUNCHD_PLIST = path26.join(os20.homedir(), "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`);
|
|
12255
|
+
SYSTEMD_UNIT_DIR = path26.join(os20.homedir(), ".config", "systemd", "user");
|
|
12256
|
+
SYSTEMD_UNIT = path26.join(SYSTEMD_UNIT_DIR, "node9-daemon.service");
|
|
12221
12257
|
}
|
|
12222
12258
|
});
|
|
12223
12259
|
|
|
@@ -12303,7 +12339,7 @@ import http2 from "http";
|
|
|
12303
12339
|
import chalk25 from "chalk";
|
|
12304
12340
|
import fs38 from "fs";
|
|
12305
12341
|
import os35 from "os";
|
|
12306
|
-
import
|
|
12342
|
+
import path42 from "path";
|
|
12307
12343
|
import readline5 from "readline";
|
|
12308
12344
|
import { spawn as spawn10, execSync as execSync3 } from "child_process";
|
|
12309
12345
|
function getIcon(tool) {
|
|
@@ -12321,18 +12357,18 @@ function getModelContextLimit(model) {
|
|
|
12321
12357
|
return 2e5;
|
|
12322
12358
|
}
|
|
12323
12359
|
function readSessionUsage() {
|
|
12324
|
-
const projectsDir =
|
|
12360
|
+
const projectsDir = path42.join(os35.homedir(), ".claude", "projects");
|
|
12325
12361
|
if (!fs38.existsSync(projectsDir)) return null;
|
|
12326
12362
|
let latestFile = null;
|
|
12327
12363
|
let latestMtime = 0;
|
|
12328
12364
|
try {
|
|
12329
12365
|
for (const dir of fs38.readdirSync(projectsDir)) {
|
|
12330
|
-
const dirPath =
|
|
12366
|
+
const dirPath = path42.join(projectsDir, dir);
|
|
12331
12367
|
try {
|
|
12332
12368
|
if (!fs38.statSync(dirPath).isDirectory()) continue;
|
|
12333
12369
|
for (const file of fs38.readdirSync(dirPath)) {
|
|
12334
12370
|
if (!file.endsWith(".jsonl") || file.startsWith("agent-")) continue;
|
|
12335
|
-
const filePath =
|
|
12371
|
+
const filePath = path42.join(dirPath, file);
|
|
12336
12372
|
try {
|
|
12337
12373
|
const mtime = fs38.statSync(filePath).mtimeMs;
|
|
12338
12374
|
if (mtime > latestMtime) {
|
|
@@ -12593,7 +12629,7 @@ function buildRecoveryCardLines(req) {
|
|
|
12593
12629
|
];
|
|
12594
12630
|
}
|
|
12595
12631
|
function readApproversFromDisk() {
|
|
12596
|
-
const configPath =
|
|
12632
|
+
const configPath = path42.join(os35.homedir(), ".node9", "config.json");
|
|
12597
12633
|
try {
|
|
12598
12634
|
const raw = JSON.parse(fs38.readFileSync(configPath, "utf-8"));
|
|
12599
12635
|
const settings = raw.settings ?? {};
|
|
@@ -12611,7 +12647,7 @@ function approverStatusLine() {
|
|
|
12611
12647
|
return `${fmt("native", "native")} ${fmt("browser", "browser")} ${fmt("cloud", "cloud")} ${fmt("terminal", "terminal")}`;
|
|
12612
12648
|
}
|
|
12613
12649
|
function toggleApprover(channel) {
|
|
12614
|
-
const configPath =
|
|
12650
|
+
const configPath = path42.join(os35.homedir(), ".node9", "config.json");
|
|
12615
12651
|
try {
|
|
12616
12652
|
const raw = JSON.parse(fs38.readFileSync(configPath, "utf-8"));
|
|
12617
12653
|
const settings = raw.settings ?? {};
|
|
@@ -12790,7 +12826,7 @@ async function startTail(options = {}) {
|
|
|
12790
12826
|
postDecisionHttp(req2.id, httpDecision, csrfToken, port, httpOpts).catch((err2) => {
|
|
12791
12827
|
try {
|
|
12792
12828
|
fs38.appendFileSync(
|
|
12793
|
-
|
|
12829
|
+
path42.join(os35.homedir(), ".node9", "hook-debug.log"),
|
|
12794
12830
|
`[tail] POST /decision failed: ${String(err2)}
|
|
12795
12831
|
`
|
|
12796
12832
|
);
|
|
@@ -12871,7 +12907,7 @@ async function startTail(options = {}) {
|
|
|
12871
12907
|
}
|
|
12872
12908
|
} catch {
|
|
12873
12909
|
}
|
|
12874
|
-
const auditLog =
|
|
12910
|
+
const auditLog = path42.join(os35.homedir(), ".node9", "audit.log");
|
|
12875
12911
|
try {
|
|
12876
12912
|
const unackedDlp = fs38.readFileSync(auditLog, "utf-8").split("\n").filter((l) => l.includes('"response-dlp"')).length;
|
|
12877
12913
|
if (unackedDlp > 0) {
|
|
@@ -13065,7 +13101,7 @@ var init_tail = __esm({
|
|
|
13065
13101
|
init_daemon2();
|
|
13066
13102
|
init_daemon();
|
|
13067
13103
|
init_core();
|
|
13068
|
-
PID_FILE =
|
|
13104
|
+
PID_FILE = path42.join(os35.homedir(), ".node9", "daemon.pid");
|
|
13069
13105
|
ICONS = {
|
|
13070
13106
|
bash: "\u{1F4BB}",
|
|
13071
13107
|
shell: "\u{1F4BB}",
|
|
@@ -13114,7 +13150,7 @@ __export(hud_exports, {
|
|
|
13114
13150
|
renderEnvironmentLine: () => renderEnvironmentLine
|
|
13115
13151
|
});
|
|
13116
13152
|
import fs39 from "fs";
|
|
13117
|
-
import
|
|
13153
|
+
import path43 from "path";
|
|
13118
13154
|
import os36 from "os";
|
|
13119
13155
|
import http3 from "http";
|
|
13120
13156
|
async function readStdin() {
|
|
@@ -13219,7 +13255,7 @@ function countRulesInDir(rulesDir) {
|
|
|
13219
13255
|
try {
|
|
13220
13256
|
for (const entry of fs39.readdirSync(rulesDir, { withFileTypes: true })) {
|
|
13221
13257
|
if (entry.isDirectory()) {
|
|
13222
|
-
count += countRulesInDir(
|
|
13258
|
+
count += countRulesInDir(path43.join(rulesDir, entry.name));
|
|
13223
13259
|
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
13224
13260
|
count++;
|
|
13225
13261
|
}
|
|
@@ -13230,46 +13266,46 @@ function countRulesInDir(rulesDir) {
|
|
|
13230
13266
|
}
|
|
13231
13267
|
function isSamePath(a, b) {
|
|
13232
13268
|
try {
|
|
13233
|
-
return
|
|
13269
|
+
return path43.resolve(a) === path43.resolve(b);
|
|
13234
13270
|
} catch {
|
|
13235
13271
|
return false;
|
|
13236
13272
|
}
|
|
13237
13273
|
}
|
|
13238
13274
|
function countConfigs(cwd) {
|
|
13239
13275
|
const homeDir2 = os36.homedir();
|
|
13240
|
-
const claudeDir =
|
|
13276
|
+
const claudeDir = path43.join(homeDir2, ".claude");
|
|
13241
13277
|
let claudeMdCount = 0;
|
|
13242
13278
|
let rulesCount = 0;
|
|
13243
13279
|
let hooksCount = 0;
|
|
13244
13280
|
const userMcpServers = /* @__PURE__ */ new Set();
|
|
13245
13281
|
const projectMcpServers = /* @__PURE__ */ new Set();
|
|
13246
|
-
if (fs39.existsSync(
|
|
13247
|
-
rulesCount += countRulesInDir(
|
|
13248
|
-
const userSettings =
|
|
13282
|
+
if (fs39.existsSync(path43.join(claudeDir, "CLAUDE.md"))) claudeMdCount++;
|
|
13283
|
+
rulesCount += countRulesInDir(path43.join(claudeDir, "rules"));
|
|
13284
|
+
const userSettings = path43.join(claudeDir, "settings.json");
|
|
13249
13285
|
for (const name of getMcpServerNames(userSettings)) userMcpServers.add(name);
|
|
13250
13286
|
hooksCount += countHooksInFile(userSettings);
|
|
13251
|
-
const userClaudeJson =
|
|
13287
|
+
const userClaudeJson = path43.join(homeDir2, ".claude.json");
|
|
13252
13288
|
for (const name of getMcpServerNames(userClaudeJson)) userMcpServers.add(name);
|
|
13253
13289
|
for (const name of getDisabledMcpServers(userClaudeJson, "disabledMcpServers")) {
|
|
13254
13290
|
userMcpServers.delete(name);
|
|
13255
13291
|
}
|
|
13256
13292
|
if (cwd) {
|
|
13257
|
-
if (fs39.existsSync(
|
|
13258
|
-
if (fs39.existsSync(
|
|
13259
|
-
const projectClaudeDir =
|
|
13293
|
+
if (fs39.existsSync(path43.join(cwd, "CLAUDE.md"))) claudeMdCount++;
|
|
13294
|
+
if (fs39.existsSync(path43.join(cwd, "CLAUDE.local.md"))) claudeMdCount++;
|
|
13295
|
+
const projectClaudeDir = path43.join(cwd, ".claude");
|
|
13260
13296
|
const overlapsUserScope = isSamePath(projectClaudeDir, claudeDir);
|
|
13261
13297
|
if (!overlapsUserScope) {
|
|
13262
|
-
if (fs39.existsSync(
|
|
13263
|
-
rulesCount += countRulesInDir(
|
|
13264
|
-
const projSettings =
|
|
13298
|
+
if (fs39.existsSync(path43.join(projectClaudeDir, "CLAUDE.md"))) claudeMdCount++;
|
|
13299
|
+
rulesCount += countRulesInDir(path43.join(projectClaudeDir, "rules"));
|
|
13300
|
+
const projSettings = path43.join(projectClaudeDir, "settings.json");
|
|
13265
13301
|
for (const name of getMcpServerNames(projSettings)) projectMcpServers.add(name);
|
|
13266
13302
|
hooksCount += countHooksInFile(projSettings);
|
|
13267
13303
|
}
|
|
13268
|
-
if (fs39.existsSync(
|
|
13269
|
-
const localSettings =
|
|
13304
|
+
if (fs39.existsSync(path43.join(projectClaudeDir, "CLAUDE.local.md"))) claudeMdCount++;
|
|
13305
|
+
const localSettings = path43.join(projectClaudeDir, "settings.local.json");
|
|
13270
13306
|
for (const name of getMcpServerNames(localSettings)) projectMcpServers.add(name);
|
|
13271
13307
|
hooksCount += countHooksInFile(localSettings);
|
|
13272
|
-
const mcpJsonServers = getMcpServerNames(
|
|
13308
|
+
const mcpJsonServers = getMcpServerNames(path43.join(cwd, ".mcp.json"));
|
|
13273
13309
|
const disabledMcpJson = getDisabledMcpServers(localSettings, "disabledMcpjsonServers");
|
|
13274
13310
|
for (const name of disabledMcpJson) mcpJsonServers.delete(name);
|
|
13275
13311
|
for (const name of mcpJsonServers) projectMcpServers.add(name);
|
|
@@ -13302,7 +13338,7 @@ function readActiveShieldsHud() {
|
|
|
13302
13338
|
return shieldsCache.value;
|
|
13303
13339
|
}
|
|
13304
13340
|
try {
|
|
13305
|
-
const shieldsPath =
|
|
13341
|
+
const shieldsPath = path43.join(os36.homedir(), ".node9", "shields.json");
|
|
13306
13342
|
if (!fs39.existsSync(shieldsPath)) {
|
|
13307
13343
|
shieldsCache = { value: [], ts: now };
|
|
13308
13344
|
return [];
|
|
@@ -13409,9 +13445,9 @@ function renderContextLine(stdin) {
|
|
|
13409
13445
|
async function main() {
|
|
13410
13446
|
try {
|
|
13411
13447
|
const [stdin, daemonStatus2] = await Promise.all([readStdin(), queryDaemon()]);
|
|
13412
|
-
if (fs39.existsSync(
|
|
13448
|
+
if (fs39.existsSync(path43.join(os36.homedir(), ".node9", "hud-debug"))) {
|
|
13413
13449
|
try {
|
|
13414
|
-
const logPath =
|
|
13450
|
+
const logPath = path43.join(os36.homedir(), ".node9", "hud-debug.log");
|
|
13415
13451
|
const MAX_LOG_SIZE = 10 * 1024 * 1024;
|
|
13416
13452
|
let size = 0;
|
|
13417
13453
|
try {
|
|
@@ -13440,8 +13476,8 @@ async function main() {
|
|
|
13440
13476
|
try {
|
|
13441
13477
|
const cwd = stdin.cwd ?? process.cwd();
|
|
13442
13478
|
for (const configPath of [
|
|
13443
|
-
|
|
13444
|
-
|
|
13479
|
+
path43.join(cwd, "node9.config.json"),
|
|
13480
|
+
path43.join(os36.homedir(), ".node9", "config.json")
|
|
13445
13481
|
]) {
|
|
13446
13482
|
if (!fs39.existsSync(configPath)) continue;
|
|
13447
13483
|
const cfg = JSON.parse(fs39.readFileSync(configPath, "utf-8"));
|
|
@@ -14513,7 +14549,7 @@ function getAgentsStatus(homeDir2 = os11.homedir()) {
|
|
|
14513
14549
|
init_daemon2();
|
|
14514
14550
|
import chalk26 from "chalk";
|
|
14515
14551
|
import fs40 from "fs";
|
|
14516
|
-
import
|
|
14552
|
+
import path44 from "path";
|
|
14517
14553
|
import os37 from "os";
|
|
14518
14554
|
import { confirm as confirm2 } from "@inquirer/prompts";
|
|
14519
14555
|
|
|
@@ -14705,7 +14741,7 @@ init_policy();
|
|
|
14705
14741
|
import chalk6 from "chalk";
|
|
14706
14742
|
import fs26 from "fs";
|
|
14707
14743
|
import { spawn as spawn6 } from "child_process";
|
|
14708
|
-
import
|
|
14744
|
+
import path29 from "path";
|
|
14709
14745
|
import os23 from "os";
|
|
14710
14746
|
|
|
14711
14747
|
// src/undo.ts
|
|
@@ -14713,9 +14749,9 @@ import { spawnSync as spawnSync5, spawn as spawn5 } from "child_process";
|
|
|
14713
14749
|
import crypto3 from "crypto";
|
|
14714
14750
|
import fs24 from "fs";
|
|
14715
14751
|
import net3 from "net";
|
|
14716
|
-
import
|
|
14752
|
+
import path27 from "path";
|
|
14717
14753
|
import os21 from "os";
|
|
14718
|
-
var ACTIVITY_SOCKET_PATH3 = process.platform === "win32" ? "\\\\.\\pipe\\node9-activity" :
|
|
14754
|
+
var ACTIVITY_SOCKET_PATH3 = process.platform === "win32" ? "\\\\.\\pipe\\node9-activity" : path27.join(os21.tmpdir(), "node9-activity.sock");
|
|
14719
14755
|
function notifySnapshotTaken(hash, tool, argsSummary, fileCount) {
|
|
14720
14756
|
try {
|
|
14721
14757
|
const payload = JSON.stringify({
|
|
@@ -14735,8 +14771,8 @@ function notifySnapshotTaken(hash, tool, argsSummary, fileCount) {
|
|
|
14735
14771
|
} catch {
|
|
14736
14772
|
}
|
|
14737
14773
|
}
|
|
14738
|
-
var SNAPSHOT_STACK_PATH =
|
|
14739
|
-
var UNDO_LATEST_PATH =
|
|
14774
|
+
var SNAPSHOT_STACK_PATH = path27.join(os21.homedir(), ".node9", "snapshots.json");
|
|
14775
|
+
var UNDO_LATEST_PATH = path27.join(os21.homedir(), ".node9", "undo_latest.txt");
|
|
14740
14776
|
var MAX_SNAPSHOTS = 10;
|
|
14741
14777
|
var GIT_TIMEOUT = 15e3;
|
|
14742
14778
|
function readStack() {
|
|
@@ -14748,7 +14784,7 @@ function readStack() {
|
|
|
14748
14784
|
return [];
|
|
14749
14785
|
}
|
|
14750
14786
|
function writeStack(stack) {
|
|
14751
|
-
const dir =
|
|
14787
|
+
const dir = path27.dirname(SNAPSHOT_STACK_PATH);
|
|
14752
14788
|
if (!fs24.existsSync(dir)) fs24.mkdirSync(dir, { recursive: true });
|
|
14753
14789
|
fs24.writeFileSync(SNAPSHOT_STACK_PATH, JSON.stringify(stack, null, 2));
|
|
14754
14790
|
}
|
|
@@ -14770,12 +14806,12 @@ function buildArgsSummary(tool, args) {
|
|
|
14770
14806
|
return "";
|
|
14771
14807
|
}
|
|
14772
14808
|
function findProjectRoot(filePath) {
|
|
14773
|
-
let dir =
|
|
14809
|
+
let dir = path27.dirname(filePath);
|
|
14774
14810
|
while (true) {
|
|
14775
|
-
if (fs24.existsSync(
|
|
14811
|
+
if (fs24.existsSync(path27.join(dir, ".git")) || fs24.existsSync(path27.join(dir, "package.json"))) {
|
|
14776
14812
|
return dir;
|
|
14777
14813
|
}
|
|
14778
|
-
const parent =
|
|
14814
|
+
const parent = path27.dirname(dir);
|
|
14779
14815
|
if (parent === dir) return process.cwd();
|
|
14780
14816
|
dir = parent;
|
|
14781
14817
|
}
|
|
@@ -14793,14 +14829,14 @@ function normalizeCwdForHash(cwd) {
|
|
|
14793
14829
|
}
|
|
14794
14830
|
function getShadowRepoDir(cwd) {
|
|
14795
14831
|
const hash = crypto3.createHash("sha256").update(normalizeCwdForHash(cwd)).digest("hex").slice(0, 16);
|
|
14796
|
-
return
|
|
14832
|
+
return path27.join(os21.homedir(), ".node9", "snapshots", hash);
|
|
14797
14833
|
}
|
|
14798
14834
|
function cleanOrphanedIndexFiles(shadowDir) {
|
|
14799
14835
|
try {
|
|
14800
14836
|
const cutoff = Date.now() - 6e4;
|
|
14801
14837
|
for (const f of fs24.readdirSync(shadowDir)) {
|
|
14802
14838
|
if (f.startsWith("index_")) {
|
|
14803
|
-
const fp =
|
|
14839
|
+
const fp = path27.join(shadowDir, f);
|
|
14804
14840
|
try {
|
|
14805
14841
|
if (fs24.statSync(fp).mtimeMs < cutoff) fs24.unlinkSync(fp);
|
|
14806
14842
|
} catch {
|
|
@@ -14814,7 +14850,7 @@ function writeShadowExcludes(shadowDir, ignorePaths) {
|
|
|
14814
14850
|
const hardcoded = [".git", ".node9"];
|
|
14815
14851
|
const lines = [...hardcoded, ...ignorePaths].join("\n");
|
|
14816
14852
|
try {
|
|
14817
|
-
fs24.writeFileSync(
|
|
14853
|
+
fs24.writeFileSync(path27.join(shadowDir, "info", "exclude"), lines + "\n", "utf8");
|
|
14818
14854
|
} catch {
|
|
14819
14855
|
}
|
|
14820
14856
|
}
|
|
@@ -14827,7 +14863,7 @@ function ensureShadowRepo(shadowDir, cwd) {
|
|
|
14827
14863
|
timeout: 3e3
|
|
14828
14864
|
});
|
|
14829
14865
|
if (check.status === 0) {
|
|
14830
|
-
const ptPath =
|
|
14866
|
+
const ptPath = path27.join(shadowDir, "project-path.txt");
|
|
14831
14867
|
try {
|
|
14832
14868
|
const stored = fs24.readFileSync(ptPath, "utf8").trim();
|
|
14833
14869
|
if (stored === normalizedCwd) return true;
|
|
@@ -14854,7 +14890,7 @@ function ensureShadowRepo(shadowDir, cwd) {
|
|
|
14854
14890
|
if (process.env.NODE9_DEBUG === "1") console.error("[Node9] git init --bare failed:", reason);
|
|
14855
14891
|
return false;
|
|
14856
14892
|
}
|
|
14857
|
-
const configFile =
|
|
14893
|
+
const configFile = path27.join(shadowDir, "config");
|
|
14858
14894
|
spawnSync5("git", ["config", "--file", configFile, "core.untrackedCache", "true"], {
|
|
14859
14895
|
timeout: 3e3
|
|
14860
14896
|
});
|
|
@@ -14862,7 +14898,7 @@ function ensureShadowRepo(shadowDir, cwd) {
|
|
|
14862
14898
|
timeout: 3e3
|
|
14863
14899
|
});
|
|
14864
14900
|
try {
|
|
14865
|
-
fs24.writeFileSync(
|
|
14901
|
+
fs24.writeFileSync(path27.join(shadowDir, "project-path.txt"), normalizedCwd, "utf8");
|
|
14866
14902
|
} catch {
|
|
14867
14903
|
}
|
|
14868
14904
|
return true;
|
|
@@ -14882,12 +14918,12 @@ async function createShadowSnapshot(tool = "unknown", args = {}, ignorePaths = [
|
|
|
14882
14918
|
let indexFile = null;
|
|
14883
14919
|
try {
|
|
14884
14920
|
const rawFilePath = extractFilePath(args);
|
|
14885
|
-
const absFilePath = rawFilePath &&
|
|
14921
|
+
const absFilePath = rawFilePath && path27.isAbsolute(rawFilePath) ? rawFilePath : null;
|
|
14886
14922
|
const cwd = absFilePath ? findProjectRoot(absFilePath) : process.cwd();
|
|
14887
14923
|
const shadowDir = getShadowRepoDir(cwd);
|
|
14888
14924
|
if (!ensureShadowRepo(shadowDir, cwd)) return null;
|
|
14889
14925
|
writeShadowExcludes(shadowDir, ignorePaths);
|
|
14890
|
-
indexFile =
|
|
14926
|
+
indexFile = path27.join(shadowDir, `index_${process.pid}_${Date.now()}`);
|
|
14891
14927
|
const shadowEnv = {
|
|
14892
14928
|
...process.env,
|
|
14893
14929
|
GIT_DIR: shadowDir,
|
|
@@ -15046,7 +15082,7 @@ function applyUndo(hash, cwd) {
|
|
|
15046
15082
|
timeout: GIT_TIMEOUT
|
|
15047
15083
|
}).stdout?.toString().trim().split("\n").filter(Boolean) ?? [];
|
|
15048
15084
|
for (const file of [...tracked, ...untracked]) {
|
|
15049
|
-
const fullPath =
|
|
15085
|
+
const fullPath = path27.join(dir, file);
|
|
15050
15086
|
if (!snapshotFiles.has(file) && fs24.existsSync(fullPath)) {
|
|
15051
15087
|
fs24.unlinkSync(fullPath);
|
|
15052
15088
|
}
|
|
@@ -15062,11 +15098,11 @@ init_daemon_starter();
|
|
|
15062
15098
|
|
|
15063
15099
|
// src/skill-pin.ts
|
|
15064
15100
|
import fs25 from "fs";
|
|
15065
|
-
import
|
|
15101
|
+
import path28 from "path";
|
|
15066
15102
|
import os22 from "os";
|
|
15067
15103
|
import crypto4 from "crypto";
|
|
15068
15104
|
function getPinsFilePath() {
|
|
15069
|
-
return
|
|
15105
|
+
return path28.join(os22.homedir(), ".node9", "skill-pins.json");
|
|
15070
15106
|
}
|
|
15071
15107
|
var MAX_FILES = 5e3;
|
|
15072
15108
|
var MAX_TOTAL_BYTES = 50 * 1024 * 1024;
|
|
@@ -15087,8 +15123,8 @@ function walkDir(root) {
|
|
|
15087
15123
|
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
15088
15124
|
for (const entry of entries) {
|
|
15089
15125
|
if (out.length >= MAX_FILES) return;
|
|
15090
|
-
const full =
|
|
15091
|
-
const rel = relDir ?
|
|
15126
|
+
const full = path28.join(dir, entry.name);
|
|
15127
|
+
const rel = relDir ? path28.posix.join(relDir, entry.name) : entry.name;
|
|
15092
15128
|
let lst;
|
|
15093
15129
|
try {
|
|
15094
15130
|
lst = fs25.lstatSync(full);
|
|
@@ -15162,7 +15198,7 @@ function readSkillPins() {
|
|
|
15162
15198
|
}
|
|
15163
15199
|
function writeSkillPins(data) {
|
|
15164
15200
|
const filePath = getPinsFilePath();
|
|
15165
|
-
fs25.mkdirSync(
|
|
15201
|
+
fs25.mkdirSync(path28.dirname(filePath), { recursive: true });
|
|
15166
15202
|
const tmp = `${filePath}.${crypto4.randomBytes(6).toString("hex")}.tmp`;
|
|
15167
15203
|
fs25.writeFileSync(tmp, JSON.stringify(data, null, 2), { mode: 384 });
|
|
15168
15204
|
fs25.renameSync(tmp, filePath);
|
|
@@ -15209,7 +15245,7 @@ function verifyAndPinRoots(roots) {
|
|
|
15209
15245
|
return { kind: "verified" };
|
|
15210
15246
|
}
|
|
15211
15247
|
function defaultSkillRoots(_cwd) {
|
|
15212
|
-
const marketplaces =
|
|
15248
|
+
const marketplaces = path28.join(os22.homedir(), ".claude", "plugins", "marketplaces");
|
|
15213
15249
|
const roots = [];
|
|
15214
15250
|
let registries;
|
|
15215
15251
|
try {
|
|
@@ -15219,7 +15255,7 @@ function defaultSkillRoots(_cwd) {
|
|
|
15219
15255
|
}
|
|
15220
15256
|
for (const registry of registries) {
|
|
15221
15257
|
if (!registry.isDirectory()) continue;
|
|
15222
|
-
const pluginsDir =
|
|
15258
|
+
const pluginsDir = path28.join(marketplaces, registry.name, "plugins");
|
|
15223
15259
|
let plugins;
|
|
15224
15260
|
try {
|
|
15225
15261
|
plugins = fs25.readdirSync(pluginsDir, { withFileTypes: true });
|
|
@@ -15228,17 +15264,17 @@ function defaultSkillRoots(_cwd) {
|
|
|
15228
15264
|
}
|
|
15229
15265
|
for (const plugin of plugins) {
|
|
15230
15266
|
if (!plugin.isDirectory()) continue;
|
|
15231
|
-
roots.push(
|
|
15267
|
+
roots.push(path28.join(pluginsDir, plugin.name));
|
|
15232
15268
|
}
|
|
15233
15269
|
}
|
|
15234
15270
|
return roots;
|
|
15235
15271
|
}
|
|
15236
15272
|
function resolveUserSkillRoot(entry, cwd) {
|
|
15237
15273
|
if (!entry) return null;
|
|
15238
|
-
if (entry.startsWith("~/") || entry === "~") return
|
|
15239
|
-
if (
|
|
15240
|
-
if (!cwd || !
|
|
15241
|
-
return
|
|
15274
|
+
if (entry.startsWith("~/") || entry === "~") return path28.join(os22.homedir(), entry.slice(1));
|
|
15275
|
+
if (path28.isAbsolute(entry)) return entry;
|
|
15276
|
+
if (!cwd || !path28.isAbsolute(cwd)) return null;
|
|
15277
|
+
return path28.join(cwd, entry);
|
|
15242
15278
|
}
|
|
15243
15279
|
|
|
15244
15280
|
// src/cli/commands/check.ts
|
|
@@ -15256,7 +15292,7 @@ function registerCheckCommand(program2) {
|
|
|
15256
15292
|
} catch (err2) {
|
|
15257
15293
|
const tempConfig = getConfig();
|
|
15258
15294
|
if (process.env.NODE9_DEBUG === "1" || tempConfig.settings.enableHookLogDebug) {
|
|
15259
|
-
const logPath =
|
|
15295
|
+
const logPath = path29.join(os23.homedir(), ".node9", "hook-debug.log");
|
|
15260
15296
|
const errMsg = err2 instanceof Error ? err2.message : String(err2);
|
|
15261
15297
|
fs26.appendFileSync(
|
|
15262
15298
|
logPath,
|
|
@@ -15271,11 +15307,11 @@ RAW: ${raw}
|
|
|
15271
15307
|
if (config.settings.autoStartDaemon && !isDaemonRunning() && !process.env.NODE9_NO_AUTO_DAEMON) {
|
|
15272
15308
|
try {
|
|
15273
15309
|
const scriptPath = process.argv[1];
|
|
15274
|
-
if (typeof scriptPath !== "string" || !
|
|
15310
|
+
if (typeof scriptPath !== "string" || !path29.isAbsolute(scriptPath))
|
|
15275
15311
|
throw new Error("node9: argv[1] is not an absolute path");
|
|
15276
15312
|
const resolvedScript = fs26.realpathSync(scriptPath);
|
|
15277
|
-
const packageDist = fs26.realpathSync(
|
|
15278
|
-
if (!resolvedScript.startsWith(packageDist +
|
|
15313
|
+
const packageDist = fs26.realpathSync(path29.resolve(__dirname, "../.."));
|
|
15314
|
+
if (!resolvedScript.startsWith(packageDist + path29.sep) && resolvedScript !== packageDist)
|
|
15279
15315
|
throw new Error(
|
|
15280
15316
|
`node9: daemon spawn aborted \u2014 argv[1] (${resolvedScript}) is outside package dist (${packageDist})`
|
|
15281
15317
|
);
|
|
@@ -15297,7 +15333,7 @@ RAW: ${raw}
|
|
|
15297
15333
|
});
|
|
15298
15334
|
d.unref();
|
|
15299
15335
|
} catch (spawnErr) {
|
|
15300
|
-
const logPath =
|
|
15336
|
+
const logPath = path29.join(os23.homedir(), ".node9", "hook-debug.log");
|
|
15301
15337
|
const msg = spawnErr instanceof Error ? spawnErr.message : String(spawnErr);
|
|
15302
15338
|
try {
|
|
15303
15339
|
fs26.appendFileSync(
|
|
@@ -15310,9 +15346,9 @@ RAW: ${raw}
|
|
|
15310
15346
|
}
|
|
15311
15347
|
}
|
|
15312
15348
|
if (process.env.NODE9_DEBUG === "1" || config.settings.enableHookLogDebug) {
|
|
15313
|
-
const logPath =
|
|
15314
|
-
if (!fs26.existsSync(
|
|
15315
|
-
fs26.mkdirSync(
|
|
15349
|
+
const logPath = path29.join(os23.homedir(), ".node9", "hook-debug.log");
|
|
15350
|
+
if (!fs26.existsSync(path29.dirname(logPath)))
|
|
15351
|
+
fs26.mkdirSync(path29.dirname(logPath), { recursive: true });
|
|
15316
15352
|
fs26.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] STDIN: ${raw}
|
|
15317
15353
|
`);
|
|
15318
15354
|
}
|
|
@@ -15380,8 +15416,8 @@ RAW: ${raw}
|
|
|
15380
15416
|
const safeSessionId = /^[A-Za-z0-9_\-]{1,128}$/.test(rawSessionId) ? rawSessionId : "";
|
|
15381
15417
|
if (skillPinCfg.enabled && safeSessionId) {
|
|
15382
15418
|
try {
|
|
15383
|
-
const sessionsDir =
|
|
15384
|
-
const flagPath =
|
|
15419
|
+
const sessionsDir = path29.join(os23.homedir(), ".node9", "skill-sessions");
|
|
15420
|
+
const flagPath = path29.join(sessionsDir, `${safeSessionId}.json`);
|
|
15385
15421
|
let flag = null;
|
|
15386
15422
|
try {
|
|
15387
15423
|
flag = JSON.parse(fs26.readFileSync(flagPath, "utf-8"));
|
|
@@ -15433,7 +15469,7 @@ RAW: ${raw}
|
|
|
15433
15469
|
return;
|
|
15434
15470
|
}
|
|
15435
15471
|
if (!flag || flag.state !== "verified" && flag.state !== "warned") {
|
|
15436
|
-
const absoluteCwd = typeof payload.cwd === "string" &&
|
|
15472
|
+
const absoluteCwd = typeof payload.cwd === "string" && path29.isAbsolute(payload.cwd) ? payload.cwd : void 0;
|
|
15437
15473
|
const extraRoots = skillPinCfg.roots;
|
|
15438
15474
|
const resolvedExtra = extraRoots.map((r) => resolveUserSkillRoot(r, absoluteCwd)).filter((r) => typeof r === "string");
|
|
15439
15475
|
const roots = [...defaultSkillRoots(absoluteCwd), ...resolvedExtra];
|
|
@@ -15475,7 +15511,7 @@ RAW: ${raw}
|
|
|
15475
15511
|
try {
|
|
15476
15512
|
const cutoff = Date.now() - 7 * 24 * 60 * 60 * 1e3;
|
|
15477
15513
|
for (const name of fs26.readdirSync(sessionsDir)) {
|
|
15478
|
-
const p =
|
|
15514
|
+
const p = path29.join(sessionsDir, name);
|
|
15479
15515
|
try {
|
|
15480
15516
|
if (fs26.statSync(p).mtimeMs < cutoff) fs26.unlinkSync(p);
|
|
15481
15517
|
} catch {
|
|
@@ -15487,7 +15523,7 @@ RAW: ${raw}
|
|
|
15487
15523
|
} catch (err2) {
|
|
15488
15524
|
if (process.env.NODE9_DEBUG === "1") {
|
|
15489
15525
|
try {
|
|
15490
|
-
const dbg =
|
|
15526
|
+
const dbg = path29.join(os23.homedir(), ".node9", "hook-debug.log");
|
|
15491
15527
|
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
15492
15528
|
fs26.appendFileSync(dbg, `[${(/* @__PURE__ */ new Date()).toISOString()}] SKILL_PIN_ERROR: ${msg}
|
|
15493
15529
|
`);
|
|
@@ -15499,7 +15535,7 @@ RAW: ${raw}
|
|
|
15499
15535
|
if (shouldSnapshot(toolName, toolInput, config)) {
|
|
15500
15536
|
await createShadowSnapshot(toolName, toolInput, config.policy.snapshot.ignorePaths);
|
|
15501
15537
|
}
|
|
15502
|
-
const safeCwdForAuth = typeof payload.cwd === "string" &&
|
|
15538
|
+
const safeCwdForAuth = typeof payload.cwd === "string" && path29.isAbsolute(payload.cwd) ? payload.cwd : void 0;
|
|
15503
15539
|
const result = await authorizeHeadless(toolName, toolInput, meta, {
|
|
15504
15540
|
cwd: safeCwdForAuth
|
|
15505
15541
|
});
|
|
@@ -15543,7 +15579,7 @@ RAW: ${raw}
|
|
|
15543
15579
|
});
|
|
15544
15580
|
} catch (err2) {
|
|
15545
15581
|
if (process.env.NODE9_DEBUG === "1") {
|
|
15546
|
-
const logPath =
|
|
15582
|
+
const logPath = path29.join(os23.homedir(), ".node9", "hook-debug.log");
|
|
15547
15583
|
const errMsg = err2 instanceof Error ? err2.message : String(err2);
|
|
15548
15584
|
fs26.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] ERROR: ${errMsg}
|
|
15549
15585
|
`);
|
|
@@ -15582,7 +15618,7 @@ RAW: ${raw}
|
|
|
15582
15618
|
init_audit();
|
|
15583
15619
|
init_config();
|
|
15584
15620
|
import fs27 from "fs";
|
|
15585
|
-
import
|
|
15621
|
+
import path30 from "path";
|
|
15586
15622
|
import os24 from "os";
|
|
15587
15623
|
init_daemon();
|
|
15588
15624
|
|
|
@@ -15656,9 +15692,9 @@ function registerLogCommand(program2) {
|
|
|
15656
15692
|
decision: "allowed",
|
|
15657
15693
|
source: "post-hook"
|
|
15658
15694
|
};
|
|
15659
|
-
const logPath =
|
|
15660
|
-
if (!fs27.existsSync(
|
|
15661
|
-
fs27.mkdirSync(
|
|
15695
|
+
const logPath = path30.join(os24.homedir(), ".node9", "audit.log");
|
|
15696
|
+
if (!fs27.existsSync(path30.dirname(logPath)))
|
|
15697
|
+
fs27.mkdirSync(path30.dirname(logPath), { recursive: true });
|
|
15662
15698
|
fs27.appendFileSync(logPath, JSON.stringify(entry) + "\n");
|
|
15663
15699
|
if ((tool === "Bash" || tool === "bash") && isDaemonRunning()) {
|
|
15664
15700
|
const command = typeof rawInput === "object" && rawInput !== null && "command" in rawInput && typeof rawInput.command === "string" ? rawInput.command : null;
|
|
@@ -15692,7 +15728,7 @@ function registerLogCommand(program2) {
|
|
|
15692
15728
|
}
|
|
15693
15729
|
}
|
|
15694
15730
|
}
|
|
15695
|
-
const safeCwd = typeof payload.cwd === "string" &&
|
|
15731
|
+
const safeCwd = typeof payload.cwd === "string" && path30.isAbsolute(payload.cwd) ? payload.cwd : void 0;
|
|
15696
15732
|
const config = getConfig(safeCwd);
|
|
15697
15733
|
if ((tool === "Bash" || tool === "bash") && config.settings.enableUndo !== false) {
|
|
15698
15734
|
const bashCommand = typeof rawInput === "object" && rawInput !== null && "command" in rawInput && typeof rawInput.command === "string" ? rawInput.command : null;
|
|
@@ -15713,7 +15749,7 @@ function registerLogCommand(program2) {
|
|
|
15713
15749
|
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
15714
15750
|
process.stderr.write(`[Node9] audit log error: ${msg}
|
|
15715
15751
|
`);
|
|
15716
|
-
const debugPath =
|
|
15752
|
+
const debugPath = path30.join(os24.homedir(), ".node9", "hook-debug.log");
|
|
15717
15753
|
try {
|
|
15718
15754
|
fs27.appendFileSync(debugPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] LOG_ERROR: ${msg}
|
|
15719
15755
|
`);
|
|
@@ -16117,7 +16153,7 @@ function registerConfigShowCommand(program2) {
|
|
|
16117
16153
|
init_daemon();
|
|
16118
16154
|
import chalk8 from "chalk";
|
|
16119
16155
|
import fs28 from "fs";
|
|
16120
|
-
import
|
|
16156
|
+
import path31 from "path";
|
|
16121
16157
|
import os25 from "os";
|
|
16122
16158
|
import { execSync as execSync2 } from "child_process";
|
|
16123
16159
|
function registerDoctorCommand(program2, version2) {
|
|
@@ -16171,7 +16207,7 @@ function registerDoctorCommand(program2, version2) {
|
|
|
16171
16207
|
);
|
|
16172
16208
|
}
|
|
16173
16209
|
section("Configuration");
|
|
16174
|
-
const globalConfigPath =
|
|
16210
|
+
const globalConfigPath = path31.join(homeDir2, ".node9", "config.json");
|
|
16175
16211
|
if (fs28.existsSync(globalConfigPath)) {
|
|
16176
16212
|
try {
|
|
16177
16213
|
JSON.parse(fs28.readFileSync(globalConfigPath, "utf-8"));
|
|
@@ -16182,7 +16218,7 @@ function registerDoctorCommand(program2, version2) {
|
|
|
16182
16218
|
} else {
|
|
16183
16219
|
warn("~/.node9/config.json not found (using defaults)", "Run: node9 init");
|
|
16184
16220
|
}
|
|
16185
|
-
const projectConfigPath =
|
|
16221
|
+
const projectConfigPath = path31.join(process.cwd(), "node9.config.json");
|
|
16186
16222
|
if (fs28.existsSync(projectConfigPath)) {
|
|
16187
16223
|
try {
|
|
16188
16224
|
JSON.parse(fs28.readFileSync(projectConfigPath, "utf-8"));
|
|
@@ -16194,7 +16230,7 @@ function registerDoctorCommand(program2, version2) {
|
|
|
16194
16230
|
);
|
|
16195
16231
|
}
|
|
16196
16232
|
}
|
|
16197
|
-
const credsPath =
|
|
16233
|
+
const credsPath = path31.join(homeDir2, ".node9", "credentials.json");
|
|
16198
16234
|
if (fs28.existsSync(credsPath)) {
|
|
16199
16235
|
pass("Cloud credentials found (~/.node9/credentials.json)");
|
|
16200
16236
|
} else {
|
|
@@ -16204,7 +16240,7 @@ function registerDoctorCommand(program2, version2) {
|
|
|
16204
16240
|
);
|
|
16205
16241
|
}
|
|
16206
16242
|
section("Agent Hooks");
|
|
16207
|
-
const claudeSettingsPath =
|
|
16243
|
+
const claudeSettingsPath = path31.join(homeDir2, ".claude", "settings.json");
|
|
16208
16244
|
if (fs28.existsSync(claudeSettingsPath)) {
|
|
16209
16245
|
try {
|
|
16210
16246
|
const cs = JSON.parse(fs28.readFileSync(claudeSettingsPath, "utf-8"));
|
|
@@ -16223,7 +16259,7 @@ function registerDoctorCommand(program2, version2) {
|
|
|
16223
16259
|
} else {
|
|
16224
16260
|
warn("Claude Code \u2014 not configured", "Run: node9 setup claude");
|
|
16225
16261
|
}
|
|
16226
|
-
const geminiSettingsPath =
|
|
16262
|
+
const geminiSettingsPath = path31.join(homeDir2, ".gemini", "settings.json");
|
|
16227
16263
|
if (fs28.existsSync(geminiSettingsPath)) {
|
|
16228
16264
|
try {
|
|
16229
16265
|
const gs = JSON.parse(fs28.readFileSync(geminiSettingsPath, "utf-8"));
|
|
@@ -16242,7 +16278,7 @@ function registerDoctorCommand(program2, version2) {
|
|
|
16242
16278
|
} else {
|
|
16243
16279
|
warn("Gemini CLI \u2014 not configured", "Run: node9 setup gemini (skip if not using Gemini)");
|
|
16244
16280
|
}
|
|
16245
|
-
const cursorHooksPath =
|
|
16281
|
+
const cursorHooksPath = path31.join(homeDir2, ".cursor", "hooks.json");
|
|
16246
16282
|
if (fs28.existsSync(cursorHooksPath)) {
|
|
16247
16283
|
try {
|
|
16248
16284
|
const cur = JSON.parse(fs28.readFileSync(cursorHooksPath, "utf-8"));
|
|
@@ -16284,7 +16320,7 @@ function registerDoctorCommand(program2, version2) {
|
|
|
16284
16320
|
// src/cli/commands/audit.ts
|
|
16285
16321
|
import chalk9 from "chalk";
|
|
16286
16322
|
import fs29 from "fs";
|
|
16287
|
-
import
|
|
16323
|
+
import path32 from "path";
|
|
16288
16324
|
import os26 from "os";
|
|
16289
16325
|
function formatRelativeTime(timestamp) {
|
|
16290
16326
|
const diff = Date.now() - new Date(timestamp).getTime();
|
|
@@ -16298,7 +16334,7 @@ function formatRelativeTime(timestamp) {
|
|
|
16298
16334
|
}
|
|
16299
16335
|
function registerAuditCommand(program2) {
|
|
16300
16336
|
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) => {
|
|
16301
|
-
const logPath =
|
|
16337
|
+
const logPath = path32.join(os26.homedir(), ".node9", "audit.log");
|
|
16302
16338
|
if (!fs29.existsSync(logPath)) {
|
|
16303
16339
|
console.log(
|
|
16304
16340
|
chalk9.yellow("No audit logs found. Run node9 with an agent to generate entries.")
|
|
@@ -16360,7 +16396,7 @@ function registerAuditCommand(program2) {
|
|
|
16360
16396
|
// src/cli/commands/report.ts
|
|
16361
16397
|
import chalk10 from "chalk";
|
|
16362
16398
|
import fs30 from "fs";
|
|
16363
|
-
import
|
|
16399
|
+
import path33 from "path";
|
|
16364
16400
|
import os27 from "os";
|
|
16365
16401
|
var TEST_COMMAND_RE3 = /(?:^|\s)(npm\s+(?:run\s+)?test|npx\s+(?:vitest|jest|mocha)|yarn\s+(?:run\s+)?test|pnpm\s+(?:run\s+)?test|vitest|jest|mocha|pytest|py\.test|cargo\s+test|go\s+test|bundle\s+exec\s+rspec|rspec|phpunit|dotnet\s+test)\b/i;
|
|
16366
16402
|
function buildTestTimestamps(allEntries) {
|
|
@@ -16488,7 +16524,7 @@ function loadClaudeCost(start, end) {
|
|
|
16488
16524
|
cacheWriteTokens: 0,
|
|
16489
16525
|
cacheReadTokens: 0
|
|
16490
16526
|
};
|
|
16491
|
-
const projectsDir =
|
|
16527
|
+
const projectsDir = path33.join(os27.homedir(), ".claude", "projects");
|
|
16492
16528
|
if (!fs30.existsSync(projectsDir)) return empty;
|
|
16493
16529
|
let dirs;
|
|
16494
16530
|
try {
|
|
@@ -16504,7 +16540,7 @@ function loadClaudeCost(start, end) {
|
|
|
16504
16540
|
const byDay = /* @__PURE__ */ new Map();
|
|
16505
16541
|
const byModel = /* @__PURE__ */ new Map();
|
|
16506
16542
|
for (const proj of dirs) {
|
|
16507
|
-
const projPath =
|
|
16543
|
+
const projPath = path33.join(projectsDir, proj);
|
|
16508
16544
|
let files;
|
|
16509
16545
|
try {
|
|
16510
16546
|
const stat = fs30.statSync(projPath);
|
|
@@ -16515,7 +16551,7 @@ function loadClaudeCost(start, end) {
|
|
|
16515
16551
|
}
|
|
16516
16552
|
for (const file of files) {
|
|
16517
16553
|
try {
|
|
16518
|
-
const raw = fs30.readFileSync(
|
|
16554
|
+
const raw = fs30.readFileSync(path33.join(projPath, file), "utf-8");
|
|
16519
16555
|
for (const line of raw.split("\n")) {
|
|
16520
16556
|
if (!line.trim()) continue;
|
|
16521
16557
|
let entry;
|
|
@@ -16556,7 +16592,7 @@ function loadClaudeCost(start, end) {
|
|
|
16556
16592
|
return { total, byDay, byModel, inputTokens, outputTokens, cacheWriteTokens, cacheReadTokens };
|
|
16557
16593
|
}
|
|
16558
16594
|
function loadCodexCost(start, end) {
|
|
16559
|
-
const sessionsBase =
|
|
16595
|
+
const sessionsBase = path33.join(os27.homedir(), ".codex", "sessions");
|
|
16560
16596
|
const byDay = /* @__PURE__ */ new Map();
|
|
16561
16597
|
let total = 0;
|
|
16562
16598
|
let toolCalls = 0;
|
|
@@ -16564,28 +16600,28 @@ function loadCodexCost(start, end) {
|
|
|
16564
16600
|
const jsonlFiles = [];
|
|
16565
16601
|
try {
|
|
16566
16602
|
for (const year of fs30.readdirSync(sessionsBase)) {
|
|
16567
|
-
const yearPath =
|
|
16603
|
+
const yearPath = path33.join(sessionsBase, year);
|
|
16568
16604
|
try {
|
|
16569
16605
|
if (!fs30.statSync(yearPath).isDirectory()) continue;
|
|
16570
16606
|
} catch {
|
|
16571
16607
|
continue;
|
|
16572
16608
|
}
|
|
16573
16609
|
for (const month of fs30.readdirSync(yearPath)) {
|
|
16574
|
-
const monthPath =
|
|
16610
|
+
const monthPath = path33.join(yearPath, month);
|
|
16575
16611
|
try {
|
|
16576
16612
|
if (!fs30.statSync(monthPath).isDirectory()) continue;
|
|
16577
16613
|
} catch {
|
|
16578
16614
|
continue;
|
|
16579
16615
|
}
|
|
16580
16616
|
for (const day of fs30.readdirSync(monthPath)) {
|
|
16581
|
-
const dayPath =
|
|
16617
|
+
const dayPath = path33.join(monthPath, day);
|
|
16582
16618
|
try {
|
|
16583
16619
|
if (!fs30.statSync(dayPath).isDirectory()) continue;
|
|
16584
16620
|
} catch {
|
|
16585
16621
|
continue;
|
|
16586
16622
|
}
|
|
16587
16623
|
for (const file of fs30.readdirSync(dayPath)) {
|
|
16588
|
-
if (file.endsWith(".jsonl")) jsonlFiles.push(
|
|
16624
|
+
if (file.endsWith(".jsonl")) jsonlFiles.push(path33.join(dayPath, file));
|
|
16589
16625
|
}
|
|
16590
16626
|
}
|
|
16591
16627
|
}
|
|
@@ -16646,7 +16682,7 @@ function registerReportCommand(program2) {
|
|
|
16646
16682
|
const period = ["today", "7d", "30d", "month"].includes(
|
|
16647
16683
|
options.period
|
|
16648
16684
|
) ? options.period : "7d";
|
|
16649
|
-
const logPath =
|
|
16685
|
+
const logPath = path33.join(os27.homedir(), ".node9", "audit.log");
|
|
16650
16686
|
const allEntries = parseAuditLog(logPath);
|
|
16651
16687
|
const unackedDlp = allEntries.filter((e) => e.source === "response-dlp");
|
|
16652
16688
|
if (unackedDlp.length > 0) {
|
|
@@ -17154,7 +17190,7 @@ init_core();
|
|
|
17154
17190
|
init_daemon();
|
|
17155
17191
|
import chalk12 from "chalk";
|
|
17156
17192
|
import fs31 from "fs";
|
|
17157
|
-
import
|
|
17193
|
+
import path34 from "path";
|
|
17158
17194
|
import os28 from "os";
|
|
17159
17195
|
function readJson2(filePath) {
|
|
17160
17196
|
try {
|
|
@@ -17223,8 +17259,8 @@ function registerStatusCommand(program2) {
|
|
|
17223
17259
|
console.log("");
|
|
17224
17260
|
const modeLabel = settings.mode === "audit" ? chalk12.blue("audit") : settings.mode === "strict" ? chalk12.red("strict") : chalk12.white("standard");
|
|
17225
17261
|
console.log(` Mode: ${modeLabel}`);
|
|
17226
|
-
const projectConfig =
|
|
17227
|
-
const globalConfig =
|
|
17262
|
+
const projectConfig = path34.join(process.cwd(), "node9.config.json");
|
|
17263
|
+
const globalConfig = path34.join(os28.homedir(), ".node9", "config.json");
|
|
17228
17264
|
console.log(
|
|
17229
17265
|
` Local: ${fs31.existsSync(projectConfig) ? chalk12.green("Active (node9.config.json)") : chalk12.gray("Not present")}`
|
|
17230
17266
|
);
|
|
@@ -17238,13 +17274,13 @@ function registerStatusCommand(program2) {
|
|
|
17238
17274
|
}
|
|
17239
17275
|
const homeDir2 = os28.homedir();
|
|
17240
17276
|
const claudeSettings = readJson2(
|
|
17241
|
-
|
|
17277
|
+
path34.join(homeDir2, ".claude", "settings.json")
|
|
17242
17278
|
);
|
|
17243
|
-
const claudeConfig = readJson2(
|
|
17279
|
+
const claudeConfig = readJson2(path34.join(homeDir2, ".claude.json"));
|
|
17244
17280
|
const geminiSettings = readJson2(
|
|
17245
|
-
|
|
17281
|
+
path34.join(homeDir2, ".gemini", "settings.json")
|
|
17246
17282
|
);
|
|
17247
|
-
const cursorConfig = readJson2(
|
|
17283
|
+
const cursorConfig = readJson2(path34.join(homeDir2, ".cursor", "mcp.json"));
|
|
17248
17284
|
const agentFound = claudeSettings || claudeConfig || geminiSettings || cursorConfig;
|
|
17249
17285
|
if (agentFound) {
|
|
17250
17286
|
console.log("");
|
|
@@ -17305,7 +17341,7 @@ function registerStatusCommand(program2) {
|
|
|
17305
17341
|
init_core();
|
|
17306
17342
|
import chalk13 from "chalk";
|
|
17307
17343
|
import fs32 from "fs";
|
|
17308
|
-
import
|
|
17344
|
+
import path35 from "path";
|
|
17309
17345
|
import os29 from "os";
|
|
17310
17346
|
import https3 from "https";
|
|
17311
17347
|
init_shields();
|
|
@@ -17366,7 +17402,7 @@ function registerInitCommand(program2) {
|
|
|
17366
17402
|
}
|
|
17367
17403
|
console.log("");
|
|
17368
17404
|
}
|
|
17369
|
-
const configPath =
|
|
17405
|
+
const configPath = path35.join(os29.homedir(), ".node9", "config.json");
|
|
17370
17406
|
if (fs32.existsSync(configPath) && !options.force) {
|
|
17371
17407
|
try {
|
|
17372
17408
|
const existing = JSON.parse(fs32.readFileSync(configPath, "utf-8"));
|
|
@@ -17387,7 +17423,7 @@ function registerInitCommand(program2) {
|
|
|
17387
17423
|
...DEFAULT_CONFIG,
|
|
17388
17424
|
settings: { ...DEFAULT_CONFIG.settings, mode: chosenMode }
|
|
17389
17425
|
};
|
|
17390
|
-
const dir =
|
|
17426
|
+
const dir = path35.dirname(configPath);
|
|
17391
17427
|
if (!fs32.existsSync(dir)) fs32.mkdirSync(dir, { recursive: true });
|
|
17392
17428
|
fs32.writeFileSync(configPath, JSON.stringify(configToSave, null, 2) + "\n");
|
|
17393
17429
|
console.log(chalk13.green(`\u2705 Config created: ${configPath}`));
|
|
@@ -17474,7 +17510,7 @@ function registerInitCommand(program2) {
|
|
|
17474
17510
|
}
|
|
17475
17511
|
|
|
17476
17512
|
// src/cli/commands/undo.ts
|
|
17477
|
-
import
|
|
17513
|
+
import path36 from "path";
|
|
17478
17514
|
import chalk15 from "chalk";
|
|
17479
17515
|
|
|
17480
17516
|
// src/tui/undo-navigator.ts
|
|
@@ -17633,7 +17669,7 @@ function findMatchingCwd(startDir, history) {
|
|
|
17633
17669
|
let dir = startDir;
|
|
17634
17670
|
while (true) {
|
|
17635
17671
|
if (cwds.has(dir)) return dir;
|
|
17636
|
-
const parent =
|
|
17672
|
+
const parent = path36.dirname(dir);
|
|
17637
17673
|
if (parent === dir) return null;
|
|
17638
17674
|
dir = parent;
|
|
17639
17675
|
}
|
|
@@ -17830,11 +17866,11 @@ init_provenance();
|
|
|
17830
17866
|
|
|
17831
17867
|
// src/mcp-pin.ts
|
|
17832
17868
|
import fs33 from "fs";
|
|
17833
|
-
import
|
|
17869
|
+
import path37 from "path";
|
|
17834
17870
|
import os30 from "os";
|
|
17835
17871
|
import crypto5 from "crypto";
|
|
17836
17872
|
function getPinsFilePath2() {
|
|
17837
|
-
return
|
|
17873
|
+
return path37.join(os30.homedir(), ".node9", "mcp-pins.json");
|
|
17838
17874
|
}
|
|
17839
17875
|
function hashToolDefinitions(tools) {
|
|
17840
17876
|
const sorted = [...tools].sort((a, b) => {
|
|
@@ -17875,7 +17911,7 @@ function readMcpPins() {
|
|
|
17875
17911
|
}
|
|
17876
17912
|
function writeMcpPins(data) {
|
|
17877
17913
|
const filePath = getPinsFilePath2();
|
|
17878
|
-
fs33.mkdirSync(
|
|
17914
|
+
fs33.mkdirSync(path37.dirname(filePath), { recursive: true });
|
|
17879
17915
|
const tmp = `${filePath}.${crypto5.randomBytes(6).toString("hex")}.tmp`;
|
|
17880
17916
|
fs33.writeFileSync(tmp, JSON.stringify(data, null, 2), { mode: 384 });
|
|
17881
17917
|
fs33.renameSync(tmp, filePath);
|
|
@@ -18328,7 +18364,7 @@ function registerMcpGatewayCommand(program2) {
|
|
|
18328
18364
|
import readline4 from "readline";
|
|
18329
18365
|
import fs34 from "fs";
|
|
18330
18366
|
import os31 from "os";
|
|
18331
|
-
import
|
|
18367
|
+
import path38 from "path";
|
|
18332
18368
|
import { spawnSync as spawnSync7 } from "child_process";
|
|
18333
18369
|
init_core();
|
|
18334
18370
|
init_daemon();
|
|
@@ -18579,8 +18615,8 @@ function handleStatus() {
|
|
|
18579
18615
|
lines.push(`Active shields: ${activeShields.length > 0 ? activeShields.join(", ") : "none"}`);
|
|
18580
18616
|
lines.push(`Smart rules: ${config.policy.smartRules.length} loaded`);
|
|
18581
18617
|
lines.push(`DLP: ${config.policy.dlp?.enabled !== false ? "enabled" : "disabled"}`);
|
|
18582
|
-
const projectConfig =
|
|
18583
|
-
const globalConfig =
|
|
18618
|
+
const projectConfig = path38.join(process.cwd(), "node9.config.json");
|
|
18619
|
+
const globalConfig = path38.join(os31.homedir(), ".node9", "config.json");
|
|
18584
18620
|
lines.push(
|
|
18585
18621
|
`Project config (node9.config.json): ${fs34.existsSync(projectConfig) ? "present" : "not found"}`
|
|
18586
18622
|
);
|
|
@@ -18659,7 +18695,7 @@ function handleShieldDisable(args) {
|
|
|
18659
18695
|
writeActiveShields(active.filter((s) => s !== name));
|
|
18660
18696
|
return `Shield "${name}" disabled.`;
|
|
18661
18697
|
}
|
|
18662
|
-
var GLOBAL_CONFIG_PATH2 =
|
|
18698
|
+
var GLOBAL_CONFIG_PATH2 = path38.join(os31.homedir(), ".node9", "config.json");
|
|
18663
18699
|
var APPROVER_CHANNELS = ["native", "browser", "cloud", "terminal"];
|
|
18664
18700
|
function readGlobalConfigRaw() {
|
|
18665
18701
|
try {
|
|
@@ -18671,7 +18707,7 @@ function readGlobalConfigRaw() {
|
|
|
18671
18707
|
return {};
|
|
18672
18708
|
}
|
|
18673
18709
|
function writeGlobalConfigRaw(data) {
|
|
18674
|
-
const dir =
|
|
18710
|
+
const dir = path38.dirname(GLOBAL_CONFIG_PATH2);
|
|
18675
18711
|
if (!fs34.existsSync(dir)) fs34.mkdirSync(dir, { recursive: true });
|
|
18676
18712
|
fs34.writeFileSync(GLOBAL_CONFIG_PATH2, JSON.stringify(data, null, 2) + "\n");
|
|
18677
18713
|
}
|
|
@@ -18717,7 +18753,7 @@ function handleApproverSet(args) {
|
|
|
18717
18753
|
function handleAuditGet(args) {
|
|
18718
18754
|
const limit = Math.min(typeof args.limit === "number" ? args.limit : 20, 100);
|
|
18719
18755
|
const filter = typeof args.filter === "string" && args.filter !== "all" ? args.filter : null;
|
|
18720
|
-
const auditPath =
|
|
18756
|
+
const auditPath = path38.join(os31.homedir(), ".node9", "audit.log");
|
|
18721
18757
|
if (!fs34.existsSync(auditPath)) return "No audit log found.";
|
|
18722
18758
|
const rawLines = fs34.readFileSync(auditPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
18723
18759
|
const parsed = [];
|
|
@@ -19274,7 +19310,7 @@ init_scan();
|
|
|
19274
19310
|
// src/cli/commands/sessions.ts
|
|
19275
19311
|
import chalk22 from "chalk";
|
|
19276
19312
|
import fs35 from "fs";
|
|
19277
|
-
import
|
|
19313
|
+
import path39 from "path";
|
|
19278
19314
|
import os32 from "os";
|
|
19279
19315
|
var CLAUDE_PRICING3 = {
|
|
19280
19316
|
"claude-opus-4-6": { i: 5e-6, o: 25e-6, cw: 625e-8, cr: 5e-7 },
|
|
@@ -19316,7 +19352,7 @@ function encodeProjectPath(projectPath) {
|
|
|
19316
19352
|
}
|
|
19317
19353
|
function sessionJsonlPath(projectPath, sessionId) {
|
|
19318
19354
|
const encoded = encodeProjectPath(projectPath);
|
|
19319
|
-
return
|
|
19355
|
+
return path39.join(os32.homedir(), ".claude", "projects", encoded, `${sessionId}.jsonl`);
|
|
19320
19356
|
}
|
|
19321
19357
|
function projectLabel(projectPath) {
|
|
19322
19358
|
return projectPath.replace(os32.homedir(), "~");
|
|
@@ -19388,7 +19424,7 @@ function parseSessionLines(lines) {
|
|
|
19388
19424
|
return { toolCalls, costUSD, hasSnapshot, modifiedFiles };
|
|
19389
19425
|
}
|
|
19390
19426
|
function loadAuditEntries(auditPath) {
|
|
19391
|
-
const aPath = auditPath ??
|
|
19427
|
+
const aPath = auditPath ?? path39.join(os32.homedir(), ".node9", "audit.log");
|
|
19392
19428
|
let raw;
|
|
19393
19429
|
try {
|
|
19394
19430
|
raw = fs35.readFileSync(aPath, "utf-8");
|
|
@@ -19427,7 +19463,7 @@ function auditEntriesInWindow(entries, windowStart, windowEnd) {
|
|
|
19427
19463
|
return result;
|
|
19428
19464
|
}
|
|
19429
19465
|
function buildGeminiSessions(days, allAuditEntries) {
|
|
19430
|
-
const tmpDir =
|
|
19466
|
+
const tmpDir = path39.join(os32.homedir(), ".gemini", "tmp");
|
|
19431
19467
|
if (!fs35.existsSync(tmpDir)) return [];
|
|
19432
19468
|
const cutoff = days !== null ? (() => {
|
|
19433
19469
|
const d = /* @__PURE__ */ new Date();
|
|
@@ -19443,18 +19479,18 @@ function buildGeminiSessions(days, allAuditEntries) {
|
|
|
19443
19479
|
}
|
|
19444
19480
|
const summaries = [];
|
|
19445
19481
|
for (const slug of slugDirs) {
|
|
19446
|
-
const slugPath =
|
|
19482
|
+
const slugPath = path39.join(tmpDir, slug);
|
|
19447
19483
|
try {
|
|
19448
19484
|
if (!fs35.statSync(slugPath).isDirectory()) continue;
|
|
19449
19485
|
} catch {
|
|
19450
19486
|
continue;
|
|
19451
19487
|
}
|
|
19452
|
-
let projectRoot =
|
|
19488
|
+
let projectRoot = path39.join(os32.homedir(), slug);
|
|
19453
19489
|
try {
|
|
19454
|
-
projectRoot = fs35.readFileSync(
|
|
19490
|
+
projectRoot = fs35.readFileSync(path39.join(slugPath, ".project_root"), "utf-8").trim();
|
|
19455
19491
|
} catch {
|
|
19456
19492
|
}
|
|
19457
|
-
const chatsDir =
|
|
19493
|
+
const chatsDir = path39.join(slugPath, "chats");
|
|
19458
19494
|
if (!fs35.existsSync(chatsDir)) continue;
|
|
19459
19495
|
let chatFiles;
|
|
19460
19496
|
try {
|
|
@@ -19465,7 +19501,7 @@ function buildGeminiSessions(days, allAuditEntries) {
|
|
|
19465
19501
|
for (const chatFile of chatFiles) {
|
|
19466
19502
|
let raw;
|
|
19467
19503
|
try {
|
|
19468
|
-
raw = fs35.readFileSync(
|
|
19504
|
+
raw = fs35.readFileSync(path39.join(chatsDir, chatFile), "utf-8");
|
|
19469
19505
|
} catch {
|
|
19470
19506
|
continue;
|
|
19471
19507
|
}
|
|
@@ -19545,7 +19581,7 @@ function buildGeminiSessions(days, allAuditEntries) {
|
|
|
19545
19581
|
return summaries;
|
|
19546
19582
|
}
|
|
19547
19583
|
function buildCodexSessions(days, allAuditEntries) {
|
|
19548
|
-
const sessionsBase =
|
|
19584
|
+
const sessionsBase = path39.join(os32.homedir(), ".codex", "sessions");
|
|
19549
19585
|
if (!fs35.existsSync(sessionsBase)) return [];
|
|
19550
19586
|
const cutoff = days !== null ? (() => {
|
|
19551
19587
|
const d = /* @__PURE__ */ new Date();
|
|
@@ -19556,28 +19592,28 @@ function buildCodexSessions(days, allAuditEntries) {
|
|
|
19556
19592
|
const jsonlFiles = [];
|
|
19557
19593
|
try {
|
|
19558
19594
|
for (const year of fs35.readdirSync(sessionsBase)) {
|
|
19559
|
-
const yearPath =
|
|
19595
|
+
const yearPath = path39.join(sessionsBase, year);
|
|
19560
19596
|
try {
|
|
19561
19597
|
if (!fs35.statSync(yearPath).isDirectory()) continue;
|
|
19562
19598
|
} catch {
|
|
19563
19599
|
continue;
|
|
19564
19600
|
}
|
|
19565
19601
|
for (const month of fs35.readdirSync(yearPath)) {
|
|
19566
|
-
const monthPath =
|
|
19602
|
+
const monthPath = path39.join(yearPath, month);
|
|
19567
19603
|
try {
|
|
19568
19604
|
if (!fs35.statSync(monthPath).isDirectory()) continue;
|
|
19569
19605
|
} catch {
|
|
19570
19606
|
continue;
|
|
19571
19607
|
}
|
|
19572
19608
|
for (const day of fs35.readdirSync(monthPath)) {
|
|
19573
|
-
const dayPath =
|
|
19609
|
+
const dayPath = path39.join(monthPath, day);
|
|
19574
19610
|
try {
|
|
19575
19611
|
if (!fs35.statSync(dayPath).isDirectory()) continue;
|
|
19576
19612
|
} catch {
|
|
19577
19613
|
continue;
|
|
19578
19614
|
}
|
|
19579
19615
|
for (const file of fs35.readdirSync(dayPath)) {
|
|
19580
|
-
if (file.endsWith(".jsonl")) jsonlFiles.push(
|
|
19616
|
+
if (file.endsWith(".jsonl")) jsonlFiles.push(path39.join(dayPath, file));
|
|
19581
19617
|
}
|
|
19582
19618
|
}
|
|
19583
19619
|
}
|
|
@@ -19667,7 +19703,7 @@ function buildCodexSessions(days, allAuditEntries) {
|
|
|
19667
19703
|
return summaries;
|
|
19668
19704
|
}
|
|
19669
19705
|
function buildSessions(days, historyPath) {
|
|
19670
|
-
const hPath = historyPath ??
|
|
19706
|
+
const hPath = historyPath ?? path39.join(os32.homedir(), ".claude", "history.jsonl");
|
|
19671
19707
|
let historyRaw;
|
|
19672
19708
|
try {
|
|
19673
19709
|
historyRaw = fs35.readFileSync(hPath, "utf-8");
|
|
@@ -19961,7 +19997,7 @@ function registerSessionsCommand(program2) {
|
|
|
19961
19997
|
console.log("");
|
|
19962
19998
|
console.log(chalk22.cyan.bold("\u{1F4CB} node9 sessions") + chalk22.dim(" \u2014 what your AI agent did"));
|
|
19963
19999
|
console.log("");
|
|
19964
|
-
const historyPath =
|
|
20000
|
+
const historyPath = path39.join(os32.homedir(), ".claude", "history.jsonl");
|
|
19965
20001
|
if (!fs35.existsSync(historyPath)) {
|
|
19966
20002
|
console.log(chalk22.yellow(" No Claude session history found at ~/.claude/history.jsonl"));
|
|
19967
20003
|
console.log(chalk22.gray(" Install Claude Code, run a few sessions, then try again.\n"));
|
|
@@ -20001,10 +20037,10 @@ function registerSessionsCommand(program2) {
|
|
|
20001
20037
|
import chalk23 from "chalk";
|
|
20002
20038
|
import fs36 from "fs";
|
|
20003
20039
|
import os33 from "os";
|
|
20004
|
-
import
|
|
20040
|
+
import path40 from "path";
|
|
20005
20041
|
function wipeSkillSessions() {
|
|
20006
20042
|
try {
|
|
20007
|
-
fs36.rmSync(
|
|
20043
|
+
fs36.rmSync(path40.join(os33.homedir(), ".node9", "skill-sessions"), {
|
|
20008
20044
|
recursive: true,
|
|
20009
20045
|
force: true
|
|
20010
20046
|
});
|
|
@@ -20088,10 +20124,10 @@ function registerSkillPinCommand(program2) {
|
|
|
20088
20124
|
// src/cli/commands/dlp.ts
|
|
20089
20125
|
import chalk24 from "chalk";
|
|
20090
20126
|
import fs37 from "fs";
|
|
20091
|
-
import
|
|
20127
|
+
import path41 from "path";
|
|
20092
20128
|
import os34 from "os";
|
|
20093
|
-
var AUDIT_LOG =
|
|
20094
|
-
var RESOLVED_FILE =
|
|
20129
|
+
var AUDIT_LOG = path41.join(os34.homedir(), ".node9", "audit.log");
|
|
20130
|
+
var RESOLVED_FILE = path41.join(os34.homedir(), ".node9", "dlp-resolved.json");
|
|
20095
20131
|
var ANSI_RE = /\x1b(?:\[[0-9;?]*[a-zA-Z]|\][^\x07\x1b]*(?:\x07|\x1b\\)|[@-_])/g;
|
|
20096
20132
|
function stripAnsi(s) {
|
|
20097
20133
|
return s.replace(ANSI_RE, "");
|
|
@@ -20210,15 +20246,15 @@ function registerDlpCommand(program2) {
|
|
|
20210
20246
|
|
|
20211
20247
|
// src/cli.ts
|
|
20212
20248
|
var { version } = JSON.parse(
|
|
20213
|
-
fs40.readFileSync(
|
|
20249
|
+
fs40.readFileSync(path44.join(__dirname, "../package.json"), "utf-8")
|
|
20214
20250
|
);
|
|
20215
20251
|
var program = new Command();
|
|
20216
20252
|
program.name("node9").description("The Sudo Command for AI Agents").version(version);
|
|
20217
20253
|
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) => {
|
|
20218
20254
|
const DEFAULT_API_URL2 = "https://api.node9.ai/api/v1/intercept";
|
|
20219
|
-
const credPath =
|
|
20220
|
-
if (!fs40.existsSync(
|
|
20221
|
-
fs40.mkdirSync(
|
|
20255
|
+
const credPath = path44.join(os37.homedir(), ".node9", "credentials.json");
|
|
20256
|
+
if (!fs40.existsSync(path44.dirname(credPath)))
|
|
20257
|
+
fs40.mkdirSync(path44.dirname(credPath), { recursive: true });
|
|
20222
20258
|
const profileName = options.profile || "default";
|
|
20223
20259
|
let existingCreds = {};
|
|
20224
20260
|
try {
|
|
@@ -20237,7 +20273,7 @@ program.command("login").argument("<apiKey>").option("--local", "Save key for au
|
|
|
20237
20273
|
existingCreds[profileName] = { apiKey, apiUrl: DEFAULT_API_URL2 };
|
|
20238
20274
|
fs40.writeFileSync(credPath, JSON.stringify(existingCreds, null, 2), { mode: 384 });
|
|
20239
20275
|
if (profileName === "default") {
|
|
20240
|
-
const configPath =
|
|
20276
|
+
const configPath = path44.join(os37.homedir(), ".node9", "config.json");
|
|
20241
20277
|
let config = {};
|
|
20242
20278
|
try {
|
|
20243
20279
|
if (fs40.existsSync(configPath))
|
|
@@ -20256,8 +20292,8 @@ program.command("login").argument("<apiKey>").option("--local", "Save key for au
|
|
|
20256
20292
|
approvers.cloud = false;
|
|
20257
20293
|
}
|
|
20258
20294
|
s.approvers = approvers;
|
|
20259
|
-
if (!fs40.existsSync(
|
|
20260
|
-
fs40.mkdirSync(
|
|
20295
|
+
if (!fs40.existsSync(path44.dirname(configPath)))
|
|
20296
|
+
fs40.mkdirSync(path44.dirname(configPath), { recursive: true });
|
|
20261
20297
|
fs40.writeFileSync(configPath, JSON.stringify(config, null, 2), { mode: 384 });
|
|
20262
20298
|
}
|
|
20263
20299
|
if (options.profile && profileName !== "default") {
|
|
@@ -20395,7 +20431,7 @@ program.command("uninstall").description("Remove all Node9 hooks and optionally
|
|
|
20395
20431
|
}
|
|
20396
20432
|
}
|
|
20397
20433
|
if (options.purge) {
|
|
20398
|
-
const node9Dir =
|
|
20434
|
+
const node9Dir = path44.join(os37.homedir(), ".node9");
|
|
20399
20435
|
if (fs40.existsSync(node9Dir)) {
|
|
20400
20436
|
const confirmed = await confirm2({
|
|
20401
20437
|
message: `Permanently delete ${node9Dir} (config, audit log, credentials)?`,
|
|
@@ -20545,9 +20581,9 @@ Claude Code spawns this command every ~300ms and writes a JSON payload to stdin.
|
|
|
20545
20581
|
Run "node9 addto claude" to register it as the statusLine.`
|
|
20546
20582
|
).argument("[subcommand]", 'Optional: "debug on" / "debug off" to toggle stdin logging').argument("[state]", 'on|off \u2014 used with "debug" subcommand').action(async (subcommand, state) => {
|
|
20547
20583
|
if (subcommand === "debug") {
|
|
20548
|
-
const flagFile =
|
|
20584
|
+
const flagFile = path44.join(os37.homedir(), ".node9", "hud-debug");
|
|
20549
20585
|
if (state === "on") {
|
|
20550
|
-
fs40.mkdirSync(
|
|
20586
|
+
fs40.mkdirSync(path44.dirname(flagFile), { recursive: true });
|
|
20551
20587
|
fs40.writeFileSync(flagFile, "");
|
|
20552
20588
|
console.log("HUD debug logging enabled \u2192 ~/.node9/hud-debug.log");
|
|
20553
20589
|
console.log("Tail it with: tail -f ~/.node9/hud-debug.log");
|
|
@@ -20664,7 +20700,7 @@ if (process.argv[2] !== "daemon") {
|
|
|
20664
20700
|
const isCheckHook = process.argv[2] === "check";
|
|
20665
20701
|
if (isCheckHook) {
|
|
20666
20702
|
if (process.env.NODE9_DEBUG === "1" || getConfig().settings.enableHookLogDebug) {
|
|
20667
|
-
const logPath =
|
|
20703
|
+
const logPath = path44.join(os37.homedir(), ".node9", "hook-debug.log");
|
|
20668
20704
|
const msg = reason instanceof Error ? reason.message : String(reason);
|
|
20669
20705
|
fs40.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] UNHANDLED: ${msg}
|
|
20670
20706
|
`);
|