@node9/proxy 2.7.0 → 2.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +155 -119
- package/dist/cli.mjs +943 -908
- package/dist/dashboard.mjs +146 -111
- package/package.json +1 -1
package/dist/dashboard.mjs
CHANGED
|
@@ -228,9 +228,9 @@ function matchesPattern(text, patterns) {
|
|
|
228
228
|
const withoutDotSlash = text.replace(/^\.\//, "");
|
|
229
229
|
return isMatch(withoutDotSlash) || isMatch(`./${withoutDotSlash}`);
|
|
230
230
|
}
|
|
231
|
-
function getNestedValue(obj,
|
|
231
|
+
function getNestedValue(obj, path13) {
|
|
232
232
|
if (!obj || typeof obj !== "object") return null;
|
|
233
|
-
const segments =
|
|
233
|
+
const segments = path13.split(".");
|
|
234
234
|
for (const seg of segments) {
|
|
235
235
|
if (FORBIDDEN_PATH_SEGMENTS.has(seg)) return null;
|
|
236
236
|
}
|
|
@@ -2333,8 +2333,8 @@ function sanitizeConfig(raw) {
|
|
|
2333
2333
|
}
|
|
2334
2334
|
}
|
|
2335
2335
|
const lines = result.error.issues.map((issue) => {
|
|
2336
|
-
const
|
|
2337
|
-
return ` \u2022 ${
|
|
2336
|
+
const path13 = issue.path.length > 0 ? issue.path.join(".") : "root";
|
|
2337
|
+
return ` \u2022 ${path13}: ${issue.message}`;
|
|
2338
2338
|
});
|
|
2339
2339
|
return {
|
|
2340
2340
|
sanitized,
|
|
@@ -3213,13 +3213,13 @@ function getConfig(cwd) {
|
|
|
3213
3213
|
}
|
|
3214
3214
|
if (Array.isArray(mc.jailPaths)) {
|
|
3215
3215
|
for (const jp of mc.jailPaths) {
|
|
3216
|
-
const
|
|
3217
|
-
if (!
|
|
3216
|
+
const path13 = typeof jp?.path === "string" ? jp.path.trim() : "";
|
|
3217
|
+
if (!path13) continue;
|
|
3218
3218
|
const verdict = jp?.verdict === "review" ? "review" : "block";
|
|
3219
|
-
for (const r of pathRules(
|
|
3219
|
+
for (const r of pathRules(path13, verdict, "org-managed jail")) {
|
|
3220
3220
|
mergedPolicy.smartRules.push({ ...r, name: `org:${r.name}` });
|
|
3221
3221
|
}
|
|
3222
|
-
mergedPolicy.managedJailPaths.push({ path:
|
|
3222
|
+
mergedPolicy.managedJailPaths.push({ path: path13, verdict });
|
|
3223
3223
|
}
|
|
3224
3224
|
}
|
|
3225
3225
|
if (Array.isArray(mc.trustedHosts)) {
|
|
@@ -3718,14 +3718,15 @@ import os6 from "os";
|
|
|
3718
3718
|
function normalizeModel(raw) {
|
|
3719
3719
|
return raw.replace(/-\d{8}$/, "").toLowerCase();
|
|
3720
3720
|
}
|
|
3721
|
-
function readCache() {
|
|
3721
|
+
function readCache(opts) {
|
|
3722
3722
|
try {
|
|
3723
3723
|
const raw = JSON.parse(fs5.readFileSync(CACHE_FILE(), "utf-8"));
|
|
3724
3724
|
if (typeof raw.fetchedAt !== "string" || typeof raw.prices !== "object" || raw.prices === null) {
|
|
3725
3725
|
return null;
|
|
3726
3726
|
}
|
|
3727
3727
|
const ageMs = Date.now() - new Date(raw.fetchedAt).getTime();
|
|
3728
|
-
if (ageMs
|
|
3728
|
+
if (!Number.isFinite(ageMs) || ageMs < 0) return null;
|
|
3729
|
+
if (opts.requireFresh && ageMs > TTL_MS) return null;
|
|
3729
3730
|
return raw.prices;
|
|
3730
3731
|
} catch {
|
|
3731
3732
|
return null;
|
|
@@ -3791,7 +3792,7 @@ async function fetchLiteLLMPricing() {
|
|
|
3791
3792
|
}
|
|
3792
3793
|
async function ensurePricingLoaded() {
|
|
3793
3794
|
if (memCache !== null && Date.now() - memCacheAt < TTL_MS) return;
|
|
3794
|
-
const fromDisk = readCache();
|
|
3795
|
+
const fromDisk = readCache({ requireFresh: true });
|
|
3795
3796
|
if (fromDisk && Object.keys(fromDisk).length > 0) {
|
|
3796
3797
|
memCache = fromDisk;
|
|
3797
3798
|
memCacheAt = Date.now();
|
|
@@ -3816,7 +3817,7 @@ function pricingFor(model) {
|
|
|
3816
3817
|
if (cached !== void 0) return cached;
|
|
3817
3818
|
if (memCache === null && !diskChecked) {
|
|
3818
3819
|
diskChecked = true;
|
|
3819
|
-
const disk = readCache();
|
|
3820
|
+
const disk = readCache({ requireFresh: false });
|
|
3820
3821
|
if (disk && Object.keys(disk).length > 0) {
|
|
3821
3822
|
memCache = disk;
|
|
3822
3823
|
memCacheAt = Date.now();
|
|
@@ -3945,6 +3946,37 @@ var init_cost_copilot = __esm({
|
|
|
3945
3946
|
}
|
|
3946
3947
|
});
|
|
3947
3948
|
|
|
3949
|
+
// src/session-files.ts
|
|
3950
|
+
import * as fs6 from "fs";
|
|
3951
|
+
import * as path7 from "path";
|
|
3952
|
+
function listSessionFiles(dir, maxDepth = 6) {
|
|
3953
|
+
const out = [];
|
|
3954
|
+
const walk = (d, rel, depth) => {
|
|
3955
|
+
if (depth > maxDepth) return;
|
|
3956
|
+
let entries;
|
|
3957
|
+
try {
|
|
3958
|
+
entries = fs6.readdirSync(d, { withFileTypes: true });
|
|
3959
|
+
} catch {
|
|
3960
|
+
return;
|
|
3961
|
+
}
|
|
3962
|
+
for (const e of entries) {
|
|
3963
|
+
const childRel = rel ? path7.join(rel, e.name) : e.name;
|
|
3964
|
+
if (e.isDirectory()) walk(path7.join(d, e.name), childRel, depth + 1);
|
|
3965
|
+
else if (e.name.endsWith(".jsonl")) out.push(childRel);
|
|
3966
|
+
}
|
|
3967
|
+
};
|
|
3968
|
+
walk(dir, "", 0);
|
|
3969
|
+
return out;
|
|
3970
|
+
}
|
|
3971
|
+
function sessionIdOf(relPath) {
|
|
3972
|
+
return path7.basename(relPath).replace(/\.jsonl$/, "");
|
|
3973
|
+
}
|
|
3974
|
+
var init_session_files = __esm({
|
|
3975
|
+
"src/session-files.ts"() {
|
|
3976
|
+
"use strict";
|
|
3977
|
+
}
|
|
3978
|
+
});
|
|
3979
|
+
|
|
3948
3980
|
// src/costSync.ts
|
|
3949
3981
|
function decodeProjectDirName(dirName) {
|
|
3950
3982
|
return dirName.replace(/-/g, "/");
|
|
@@ -3959,6 +3991,7 @@ var init_costSync = __esm({
|
|
|
3959
3991
|
init_cost_codex();
|
|
3960
3992
|
init_cost_gemini();
|
|
3961
3993
|
init_cost_copilot();
|
|
3994
|
+
init_session_files();
|
|
3962
3995
|
SYNC_INTERVAL_MS = 10 * 60 * 1e3;
|
|
3963
3996
|
}
|
|
3964
3997
|
});
|
|
@@ -4031,9 +4064,9 @@ var init_scan_watermark = __esm({
|
|
|
4031
4064
|
});
|
|
4032
4065
|
|
|
4033
4066
|
// src/cli/aggregate/report-audit.ts
|
|
4034
|
-
import
|
|
4067
|
+
import fs7 from "fs";
|
|
4035
4068
|
import os7 from "os";
|
|
4036
|
-
import
|
|
4069
|
+
import path8 from "path";
|
|
4037
4070
|
function buildTestTimestamps(allEntries) {
|
|
4038
4071
|
const testTs = /* @__PURE__ */ new Set();
|
|
4039
4072
|
for (const e of allEntries) {
|
|
@@ -4114,8 +4147,8 @@ function getDateRange(period, now) {
|
|
|
4114
4147
|
}
|
|
4115
4148
|
}
|
|
4116
4149
|
function parseAuditLog(logPath) {
|
|
4117
|
-
if (!
|
|
4118
|
-
const raw =
|
|
4150
|
+
if (!fs7.existsSync(logPath)) return [];
|
|
4151
|
+
const raw = fs7.readFileSync(logPath, "utf-8");
|
|
4119
4152
|
return raw.split("\n").flatMap((line) => {
|
|
4120
4153
|
if (!line.trim()) return [];
|
|
4121
4154
|
try {
|
|
@@ -4169,25 +4202,25 @@ function freezeClaudeCost(acc) {
|
|
|
4169
4202
|
};
|
|
4170
4203
|
}
|
|
4171
4204
|
function processClaudeCostProject(proj, projectsDir, start, end, acc) {
|
|
4172
|
-
const projPath =
|
|
4205
|
+
const projPath = path8.join(projectsDir, proj);
|
|
4173
4206
|
let files;
|
|
4174
4207
|
try {
|
|
4175
|
-
const stat =
|
|
4208
|
+
const stat = fs7.statSync(projPath);
|
|
4176
4209
|
if (!stat.isDirectory()) return;
|
|
4177
|
-
files =
|
|
4210
|
+
files = listSessionFiles(projPath);
|
|
4178
4211
|
} catch {
|
|
4179
4212
|
return;
|
|
4180
4213
|
}
|
|
4181
4214
|
const startMs = start.getTime();
|
|
4182
4215
|
for (const file of files) {
|
|
4183
|
-
const filePath =
|
|
4216
|
+
const filePath = path8.join(projPath, file);
|
|
4184
4217
|
try {
|
|
4185
|
-
if (
|
|
4218
|
+
if (fs7.statSync(filePath).mtimeMs < startMs) continue;
|
|
4186
4219
|
} catch {
|
|
4187
4220
|
continue;
|
|
4188
4221
|
}
|
|
4189
4222
|
try {
|
|
4190
|
-
const raw =
|
|
4223
|
+
const raw = fs7.readFileSync(filePath, "utf-8");
|
|
4191
4224
|
for (const line of raw.split("\n")) {
|
|
4192
4225
|
if (!line.trim()) continue;
|
|
4193
4226
|
let entry;
|
|
@@ -4237,10 +4270,10 @@ function processClaudeCostProject(proj, projectsDir, start, end, acc) {
|
|
|
4237
4270
|
}
|
|
4238
4271
|
function loadClaudeCost(start, end, projectsDir) {
|
|
4239
4272
|
const acc = emptyClaudeCostAccumulator();
|
|
4240
|
-
if (!
|
|
4273
|
+
if (!fs7.existsSync(projectsDir)) return freezeClaudeCost(acc);
|
|
4241
4274
|
let dirs;
|
|
4242
4275
|
try {
|
|
4243
|
-
dirs =
|
|
4276
|
+
dirs = fs7.readdirSync(projectsDir);
|
|
4244
4277
|
} catch {
|
|
4245
4278
|
return freezeClaudeCost(acc);
|
|
4246
4279
|
}
|
|
@@ -4251,10 +4284,10 @@ function loadClaudeCost(start, end, projectsDir) {
|
|
|
4251
4284
|
}
|
|
4252
4285
|
async function loadClaudeCostAsync(start, end, projectsDir) {
|
|
4253
4286
|
const acc = emptyClaudeCostAccumulator();
|
|
4254
|
-
if (!
|
|
4287
|
+
if (!fs7.existsSync(projectsDir)) return freezeClaudeCost(acc);
|
|
4255
4288
|
let dirs;
|
|
4256
4289
|
try {
|
|
4257
|
-
dirs =
|
|
4290
|
+
dirs = fs7.readdirSync(projectsDir);
|
|
4258
4291
|
} catch {
|
|
4259
4292
|
return freezeClaudeCost(acc);
|
|
4260
4293
|
}
|
|
@@ -4267,7 +4300,7 @@ async function loadClaudeCostAsync(start, end, projectsDir) {
|
|
|
4267
4300
|
function processCodexCostFile(filePath, start, end, acc) {
|
|
4268
4301
|
let lines;
|
|
4269
4302
|
try {
|
|
4270
|
-
lines =
|
|
4303
|
+
lines = fs7.readFileSync(filePath, "utf-8").split("\n");
|
|
4271
4304
|
} catch {
|
|
4272
4305
|
return;
|
|
4273
4306
|
}
|
|
@@ -4322,31 +4355,31 @@ function processCodexCostFile(filePath, start, end, acc) {
|
|
|
4322
4355
|
}
|
|
4323
4356
|
function listCodexSessionFiles(sessionsBase) {
|
|
4324
4357
|
const jsonlFiles = [];
|
|
4325
|
-
if (!
|
|
4358
|
+
if (!fs7.existsSync(sessionsBase)) return jsonlFiles;
|
|
4326
4359
|
try {
|
|
4327
|
-
for (const year of
|
|
4328
|
-
const yearPath =
|
|
4360
|
+
for (const year of fs7.readdirSync(sessionsBase)) {
|
|
4361
|
+
const yearPath = path8.join(sessionsBase, year);
|
|
4329
4362
|
try {
|
|
4330
|
-
if (!
|
|
4363
|
+
if (!fs7.statSync(yearPath).isDirectory()) continue;
|
|
4331
4364
|
} catch {
|
|
4332
4365
|
continue;
|
|
4333
4366
|
}
|
|
4334
|
-
for (const month of
|
|
4335
|
-
const monthPath =
|
|
4367
|
+
for (const month of fs7.readdirSync(yearPath)) {
|
|
4368
|
+
const monthPath = path8.join(yearPath, month);
|
|
4336
4369
|
try {
|
|
4337
|
-
if (!
|
|
4370
|
+
if (!fs7.statSync(monthPath).isDirectory()) continue;
|
|
4338
4371
|
} catch {
|
|
4339
4372
|
continue;
|
|
4340
4373
|
}
|
|
4341
|
-
for (const day of
|
|
4342
|
-
const dayPath =
|
|
4374
|
+
for (const day of fs7.readdirSync(monthPath)) {
|
|
4375
|
+
const dayPath = path8.join(monthPath, day);
|
|
4343
4376
|
try {
|
|
4344
|
-
if (!
|
|
4377
|
+
if (!fs7.statSync(dayPath).isDirectory()) continue;
|
|
4345
4378
|
} catch {
|
|
4346
4379
|
continue;
|
|
4347
4380
|
}
|
|
4348
|
-
for (const file of
|
|
4349
|
-
if (file.endsWith(".jsonl")) jsonlFiles.push(
|
|
4381
|
+
for (const file of fs7.readdirSync(dayPath)) {
|
|
4382
|
+
if (file.endsWith(".jsonl")) jsonlFiles.push(path8.join(dayPath, file));
|
|
4350
4383
|
}
|
|
4351
4384
|
}
|
|
4352
4385
|
}
|
|
@@ -4427,13 +4460,13 @@ function freezeGeminiCost(acc) {
|
|
|
4427
4460
|
function processGeminiCostFile(filePath, projectKey, start, end, acc) {
|
|
4428
4461
|
const startMs = start.getTime();
|
|
4429
4462
|
try {
|
|
4430
|
-
if (
|
|
4463
|
+
if (fs7.statSync(filePath).mtimeMs < startMs) return;
|
|
4431
4464
|
} catch {
|
|
4432
4465
|
return;
|
|
4433
4466
|
}
|
|
4434
4467
|
let raw;
|
|
4435
4468
|
try {
|
|
4436
|
-
raw =
|
|
4469
|
+
raw = fs7.readFileSync(filePath, "utf-8");
|
|
4437
4470
|
} catch {
|
|
4438
4471
|
return;
|
|
4439
4472
|
}
|
|
@@ -4482,30 +4515,30 @@ function listGeminiSessionFiles(geminiTmpDir) {
|
|
|
4482
4515
|
const out = [];
|
|
4483
4516
|
let dirs;
|
|
4484
4517
|
try {
|
|
4485
|
-
if (!
|
|
4486
|
-
dirs =
|
|
4518
|
+
if (!fs7.statSync(geminiTmpDir).isDirectory()) return out;
|
|
4519
|
+
dirs = fs7.readdirSync(geminiTmpDir);
|
|
4487
4520
|
} catch {
|
|
4488
4521
|
return out;
|
|
4489
4522
|
}
|
|
4490
4523
|
for (const proj of dirs) {
|
|
4491
|
-
const chatsDir =
|
|
4524
|
+
const chatsDir = path8.join(geminiTmpDir, proj, "chats");
|
|
4492
4525
|
let files;
|
|
4493
4526
|
try {
|
|
4494
|
-
if (!
|
|
4495
|
-
files =
|
|
4527
|
+
if (!fs7.statSync(chatsDir).isDirectory()) continue;
|
|
4528
|
+
files = fs7.readdirSync(chatsDir);
|
|
4496
4529
|
} catch {
|
|
4497
4530
|
continue;
|
|
4498
4531
|
}
|
|
4499
4532
|
for (const f of files) {
|
|
4500
4533
|
if (!f.endsWith(".jsonl")) continue;
|
|
4501
|
-
out.push({ projectKey: proj, file:
|
|
4534
|
+
out.push({ projectKey: proj, file: path8.join(chatsDir, f) });
|
|
4502
4535
|
}
|
|
4503
4536
|
}
|
|
4504
4537
|
return out;
|
|
4505
4538
|
}
|
|
4506
4539
|
function loadGeminiCost(start, end, geminiTmpDir) {
|
|
4507
4540
|
const acc = emptyGeminiAccumulator();
|
|
4508
|
-
if (!
|
|
4541
|
+
if (!fs7.existsSync(geminiTmpDir)) return freezeGeminiCost(acc);
|
|
4509
4542
|
for (const { projectKey, file } of listGeminiSessionFiles(geminiTmpDir)) {
|
|
4510
4543
|
processGeminiCostFile(file, projectKey, start, end, acc);
|
|
4511
4544
|
}
|
|
@@ -4513,7 +4546,7 @@ function loadGeminiCost(start, end, geminiTmpDir) {
|
|
|
4513
4546
|
}
|
|
4514
4547
|
async function loadGeminiCostAsync(start, end, geminiTmpDir) {
|
|
4515
4548
|
const acc = emptyGeminiAccumulator();
|
|
4516
|
-
if (!
|
|
4549
|
+
if (!fs7.existsSync(geminiTmpDir)) return freezeGeminiCost(acc);
|
|
4517
4550
|
const files = listGeminiSessionFiles(geminiTmpDir);
|
|
4518
4551
|
const CHUNK_SIZE = 5;
|
|
4519
4552
|
for (let i = 0; i < files.length; i++) {
|
|
@@ -4536,11 +4569,11 @@ function dimensionOfBlock(checkedBy, ruleName) {
|
|
|
4536
4569
|
}
|
|
4537
4570
|
function aggregateReportFromAudit(period, opts = {}) {
|
|
4538
4571
|
const now = opts.now ?? /* @__PURE__ */ new Date();
|
|
4539
|
-
const auditLogPath2 = opts.auditLogPath ??
|
|
4540
|
-
const claudeProjectsDir = opts.claudeProjectsDir ??
|
|
4541
|
-
const codexSessionsDir = opts.codexSessionsDir ??
|
|
4542
|
-
const geminiTmpDir = opts.geminiTmpDir ??
|
|
4543
|
-
const hasAuditFile =
|
|
4572
|
+
const auditLogPath2 = opts.auditLogPath ?? path8.join(os7.homedir(), ".node9", "audit.log");
|
|
4573
|
+
const claudeProjectsDir = opts.claudeProjectsDir ?? path8.join(os7.homedir(), ".claude", "projects");
|
|
4574
|
+
const codexSessionsDir = opts.codexSessionsDir ?? path8.join(os7.homedir(), ".codex", "sessions");
|
|
4575
|
+
const geminiTmpDir = opts.geminiTmpDir ?? path8.join(os7.homedir(), ".gemini", "tmp");
|
|
4576
|
+
const hasAuditFile = fs7.existsSync(auditLogPath2);
|
|
4544
4577
|
const allEntries = opts.preloadedAuditEntries ?? parseAuditLog(auditLogPath2);
|
|
4545
4578
|
const unackedDlp = allEntries.filter((e) => e.source === "response-dlp");
|
|
4546
4579
|
const { start, end } = getDateRange(period, now);
|
|
@@ -4770,6 +4803,7 @@ var init_report_audit = __esm({
|
|
|
4770
4803
|
init_litellm();
|
|
4771
4804
|
init_cost_codex();
|
|
4772
4805
|
init_decision();
|
|
4806
|
+
init_session_files();
|
|
4773
4807
|
TEST_COMMAND_RE = /(?:^|\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;
|
|
4774
4808
|
SUPERSEDE_WINDOW_MS = 6e4;
|
|
4775
4809
|
GEMINI_FALLBACK_MODELS2 = ["gemini-2.5-flash", "gemini-2.0-flash"];
|
|
@@ -4777,18 +4811,18 @@ var init_report_audit = __esm({
|
|
|
4777
4811
|
});
|
|
4778
4812
|
|
|
4779
4813
|
// src/utils/provenance.ts
|
|
4780
|
-
import
|
|
4814
|
+
import path9 from "path";
|
|
4781
4815
|
import os8 from "os";
|
|
4782
4816
|
var USER_PREFIXES;
|
|
4783
4817
|
var init_provenance = __esm({
|
|
4784
4818
|
"src/utils/provenance.ts"() {
|
|
4785
4819
|
"use strict";
|
|
4786
4820
|
USER_PREFIXES = [
|
|
4787
|
-
|
|
4788
|
-
|
|
4789
|
-
|
|
4790
|
-
|
|
4791
|
-
|
|
4821
|
+
path9.join(os8.homedir(), "bin"),
|
|
4822
|
+
path9.join(os8.homedir(), ".local", "bin"),
|
|
4823
|
+
path9.join(os8.homedir(), ".cargo", "bin"),
|
|
4824
|
+
path9.join(os8.homedir(), ".npm-global", "bin"),
|
|
4825
|
+
path9.join(os8.homedir(), ".volta", "bin")
|
|
4792
4826
|
];
|
|
4793
4827
|
}
|
|
4794
4828
|
});
|
|
@@ -4832,14 +4866,14 @@ var init_mcp_pin = __esm({
|
|
|
4832
4866
|
});
|
|
4833
4867
|
|
|
4834
4868
|
// src/daemon/hook-baseline.ts
|
|
4835
|
-
import
|
|
4869
|
+
import path10 from "path";
|
|
4836
4870
|
import os9 from "os";
|
|
4837
4871
|
var BASELINE_FILE, NOTIFIED_FILE;
|
|
4838
4872
|
var init_hook_baseline = __esm({
|
|
4839
4873
|
"src/daemon/hook-baseline.ts"() {
|
|
4840
4874
|
"use strict";
|
|
4841
|
-
BASELINE_FILE =
|
|
4842
|
-
NOTIFIED_FILE =
|
|
4875
|
+
BASELINE_FILE = path10.join(os9.homedir(), ".node9", "hooks-baseline.json");
|
|
4876
|
+
NOTIFIED_FILE = path10.join(os9.homedir(), ".node9", "hook-heal-notified.json");
|
|
4843
4877
|
}
|
|
4844
4878
|
});
|
|
4845
4879
|
|
|
@@ -4898,8 +4932,8 @@ var init_scan_history = __esm({
|
|
|
4898
4932
|
|
|
4899
4933
|
// src/cli/commands/scan.ts
|
|
4900
4934
|
import chalk4 from "chalk";
|
|
4901
|
-
import
|
|
4902
|
-
import
|
|
4935
|
+
import fs8 from "fs";
|
|
4936
|
+
import path11 from "path";
|
|
4903
4937
|
import os10 from "os";
|
|
4904
4938
|
import stringWidth2 from "string-width";
|
|
4905
4939
|
function claudeModelPrice2(model) {
|
|
@@ -5046,11 +5080,11 @@ function processClaudeFile(file, projPath, projLabel, ruleSources, startDate, re
|
|
|
5046
5080
|
result.filesScanned++;
|
|
5047
5081
|
result.sessions++;
|
|
5048
5082
|
onProgress?.(result.filesScanned);
|
|
5049
|
-
const sessionId = file
|
|
5083
|
+
const sessionId = sessionIdOf(file);
|
|
5050
5084
|
const session = { sessionId, costUSD: 0, toolCalls: 0 };
|
|
5051
5085
|
let raw;
|
|
5052
5086
|
try {
|
|
5053
|
-
raw =
|
|
5087
|
+
raw = fs8.readFileSync(path11.join(projPath, file), "utf-8");
|
|
5054
5088
|
} catch {
|
|
5055
5089
|
return;
|
|
5056
5090
|
}
|
|
@@ -5102,7 +5136,7 @@ function processClaudeFile(file, projPath, projLabel, ruleSources, startDate, re
|
|
|
5102
5136
|
if (block.type !== "tool_result") continue;
|
|
5103
5137
|
const filePath = block.tool_use_id ? toolUseFilePaths.get(block.tool_use_id) : void 0;
|
|
5104
5138
|
if (filePath) {
|
|
5105
|
-
const ext =
|
|
5139
|
+
const ext = path11.extname(filePath).toLowerCase();
|
|
5106
5140
|
if (CODE_EXTENSIONS.has(ext)) continue;
|
|
5107
5141
|
}
|
|
5108
5142
|
const resultText = typeof block.content === "string" ? block.content : Array.isArray(block.content) ? block.content.map((c) => c.text ?? "").join("\n") : null;
|
|
@@ -5162,7 +5196,7 @@ function processClaudeFile(file, projPath, projLabel, ruleSources, startDate, re
|
|
|
5162
5196
|
const rawCmd = String(input.command ?? "").trimStart();
|
|
5163
5197
|
if (/^node9\s+(scan|explain|report|tail|dlp|status|sessions|audit)\b/.test(rawCmd)) continue;
|
|
5164
5198
|
const inputFilePath = typeof input.file_path === "string" ? input.file_path : "";
|
|
5165
|
-
const inputFileExt = inputFilePath ?
|
|
5199
|
+
const inputFileExt = inputFilePath ? path11.extname(inputFilePath).toLowerCase() : "";
|
|
5166
5200
|
if (CODE_EXTENSIONS.has(inputFileExt)) continue;
|
|
5167
5201
|
const dlpMatch = scanArgs(input);
|
|
5168
5202
|
if (dlpMatch) {
|
|
@@ -5260,9 +5294,9 @@ function processClaudeFile(file, projPath, projLabel, ruleSources, startDate, re
|
|
|
5260
5294
|
result.perSession.push(session);
|
|
5261
5295
|
}
|
|
5262
5296
|
async function processClaudeProjectAsync(proj, projectsDir, ruleSources, startDate, result, dedup, onProgress, onLine) {
|
|
5263
|
-
const projPath =
|
|
5297
|
+
const projPath = path11.join(projectsDir, proj);
|
|
5264
5298
|
try {
|
|
5265
|
-
if (!
|
|
5299
|
+
if (!fs8.statSync(projPath).isDirectory()) return;
|
|
5266
5300
|
} catch {
|
|
5267
5301
|
return;
|
|
5268
5302
|
}
|
|
@@ -5272,7 +5306,7 @@ async function processClaudeProjectAsync(proj, projectsDir, ruleSources, startDa
|
|
|
5272
5306
|
);
|
|
5273
5307
|
let files;
|
|
5274
5308
|
try {
|
|
5275
|
-
files =
|
|
5309
|
+
files = listSessionFiles(projPath);
|
|
5276
5310
|
} catch {
|
|
5277
5311
|
return;
|
|
5278
5312
|
}
|
|
@@ -5311,12 +5345,12 @@ function emptyClaudeScan() {
|
|
|
5311
5345
|
};
|
|
5312
5346
|
}
|
|
5313
5347
|
async function scanClaudeHistoryAsync(startDate, onProgress, onLine) {
|
|
5314
|
-
const projectsDir =
|
|
5348
|
+
const projectsDir = path11.join(os10.homedir(), ".claude", "projects");
|
|
5315
5349
|
const result = emptyClaudeScan();
|
|
5316
|
-
if (!
|
|
5350
|
+
if (!fs8.existsSync(projectsDir)) return result;
|
|
5317
5351
|
let projDirs;
|
|
5318
5352
|
try {
|
|
5319
|
-
projDirs =
|
|
5353
|
+
projDirs = fs8.readdirSync(projectsDir);
|
|
5320
5354
|
} catch {
|
|
5321
5355
|
return result;
|
|
5322
5356
|
}
|
|
@@ -5337,7 +5371,7 @@ async function scanClaudeHistoryAsync(startDate, onProgress, onLine) {
|
|
|
5337
5371
|
return result;
|
|
5338
5372
|
}
|
|
5339
5373
|
function scanGeminiHistory(startDate, onProgress, onLine) {
|
|
5340
|
-
const tmpDir =
|
|
5374
|
+
const tmpDir = path11.join(os10.homedir(), ".gemini", "tmp");
|
|
5341
5375
|
const result = {
|
|
5342
5376
|
filesScanned: 0,
|
|
5343
5377
|
sessions: 0,
|
|
@@ -5353,33 +5387,33 @@ function scanGeminiHistory(startDate, onProgress, onLine) {
|
|
|
5353
5387
|
perSession: []
|
|
5354
5388
|
};
|
|
5355
5389
|
const dedup = emptyScanDedup();
|
|
5356
|
-
if (!
|
|
5390
|
+
if (!fs8.existsSync(tmpDir)) return result;
|
|
5357
5391
|
let slugDirs;
|
|
5358
5392
|
try {
|
|
5359
|
-
slugDirs =
|
|
5393
|
+
slugDirs = fs8.readdirSync(tmpDir);
|
|
5360
5394
|
} catch {
|
|
5361
5395
|
return result;
|
|
5362
5396
|
}
|
|
5363
5397
|
const ruleSources = buildRuleSources();
|
|
5364
5398
|
for (const slug2 of slugDirs) {
|
|
5365
|
-
const slugPath =
|
|
5399
|
+
const slugPath = path11.join(tmpDir, slug2);
|
|
5366
5400
|
try {
|
|
5367
|
-
if (!
|
|
5401
|
+
if (!fs8.statSync(slugPath).isDirectory()) continue;
|
|
5368
5402
|
} catch {
|
|
5369
5403
|
continue;
|
|
5370
5404
|
}
|
|
5371
5405
|
let projLabel = stripTerminalEscapes(slug2).slice(0, 40);
|
|
5372
5406
|
try {
|
|
5373
5407
|
projLabel = stripTerminalEscapes(
|
|
5374
|
-
|
|
5408
|
+
fs8.readFileSync(path11.join(slugPath, ".project_root"), "utf-8").trim()
|
|
5375
5409
|
).replace(os10.homedir(), "~").slice(0, 40);
|
|
5376
5410
|
} catch {
|
|
5377
5411
|
}
|
|
5378
|
-
const chatsDir =
|
|
5379
|
-
if (!
|
|
5412
|
+
const chatsDir = path11.join(slugPath, "chats");
|
|
5413
|
+
if (!fs8.existsSync(chatsDir)) continue;
|
|
5380
5414
|
let chatFiles;
|
|
5381
5415
|
try {
|
|
5382
|
-
chatFiles =
|
|
5416
|
+
chatFiles = fs8.readdirSync(chatsDir).filter((f) => f.endsWith(".json") || f.endsWith(".jsonl")).sort((a, b) => Number(b.endsWith(".jsonl")) - Number(a.endsWith(".jsonl")));
|
|
5383
5417
|
} catch {
|
|
5384
5418
|
continue;
|
|
5385
5419
|
}
|
|
@@ -5392,7 +5426,7 @@ function scanGeminiHistory(startDate, onProgress, onLine) {
|
|
|
5392
5426
|
onProgress?.(result.filesScanned);
|
|
5393
5427
|
let raw;
|
|
5394
5428
|
try {
|
|
5395
|
-
raw =
|
|
5429
|
+
raw = fs8.readFileSync(path11.join(chatsDir, chatFile), "utf-8");
|
|
5396
5430
|
} catch {
|
|
5397
5431
|
continue;
|
|
5398
5432
|
}
|
|
@@ -5565,7 +5599,7 @@ function scanGeminiHistory(startDate, onProgress, onLine) {
|
|
|
5565
5599
|
return result;
|
|
5566
5600
|
}
|
|
5567
5601
|
function scanCodexHistory(startDate, onProgress, onLine) {
|
|
5568
|
-
const sessionsBase =
|
|
5602
|
+
const sessionsBase = path11.join(os10.homedir(), ".codex", "sessions");
|
|
5569
5603
|
const result = {
|
|
5570
5604
|
filesScanned: 0,
|
|
5571
5605
|
sessions: 0,
|
|
@@ -5581,32 +5615,32 @@ function scanCodexHistory(startDate, onProgress, onLine) {
|
|
|
5581
5615
|
perSession: []
|
|
5582
5616
|
};
|
|
5583
5617
|
const dedup = emptyScanDedup();
|
|
5584
|
-
if (!
|
|
5618
|
+
if (!fs8.existsSync(sessionsBase)) return result;
|
|
5585
5619
|
const jsonlFiles = [];
|
|
5586
5620
|
try {
|
|
5587
|
-
for (const year of
|
|
5588
|
-
const yearPath =
|
|
5621
|
+
for (const year of fs8.readdirSync(sessionsBase)) {
|
|
5622
|
+
const yearPath = path11.join(sessionsBase, year);
|
|
5589
5623
|
try {
|
|
5590
|
-
if (!
|
|
5624
|
+
if (!fs8.statSync(yearPath).isDirectory()) continue;
|
|
5591
5625
|
} catch {
|
|
5592
5626
|
continue;
|
|
5593
5627
|
}
|
|
5594
|
-
for (const month of
|
|
5595
|
-
const monthPath =
|
|
5628
|
+
for (const month of fs8.readdirSync(yearPath)) {
|
|
5629
|
+
const monthPath = path11.join(yearPath, month);
|
|
5596
5630
|
try {
|
|
5597
|
-
if (!
|
|
5631
|
+
if (!fs8.statSync(monthPath).isDirectory()) continue;
|
|
5598
5632
|
} catch {
|
|
5599
5633
|
continue;
|
|
5600
5634
|
}
|
|
5601
|
-
for (const day of
|
|
5602
|
-
const dayPath =
|
|
5635
|
+
for (const day of fs8.readdirSync(monthPath)) {
|
|
5636
|
+
const dayPath = path11.join(monthPath, day);
|
|
5603
5637
|
try {
|
|
5604
|
-
if (!
|
|
5638
|
+
if (!fs8.statSync(dayPath).isDirectory()) continue;
|
|
5605
5639
|
} catch {
|
|
5606
5640
|
continue;
|
|
5607
5641
|
}
|
|
5608
|
-
for (const file of
|
|
5609
|
-
if (file.endsWith(".jsonl")) jsonlFiles.push(
|
|
5642
|
+
for (const file of fs8.readdirSync(dayPath)) {
|
|
5643
|
+
if (file.endsWith(".jsonl")) jsonlFiles.push(path11.join(dayPath, file));
|
|
5610
5644
|
}
|
|
5611
5645
|
}
|
|
5612
5646
|
}
|
|
@@ -5620,7 +5654,7 @@ function scanCodexHistory(startDate, onProgress, onLine) {
|
|
|
5620
5654
|
onProgress?.(result.filesScanned);
|
|
5621
5655
|
let lines;
|
|
5622
5656
|
try {
|
|
5623
|
-
lines =
|
|
5657
|
+
lines = fs8.readFileSync(filePath, "utf-8").split("\n");
|
|
5624
5658
|
} catch {
|
|
5625
5659
|
continue;
|
|
5626
5660
|
}
|
|
@@ -5825,6 +5859,7 @@ var init_scan = __esm({
|
|
|
5825
5859
|
init_scan_derive();
|
|
5826
5860
|
init_protection();
|
|
5827
5861
|
init_scan_json();
|
|
5862
|
+
init_session_files();
|
|
5828
5863
|
init_scan_history();
|
|
5829
5864
|
toolInspectionMap = DEFAULT_CONFIG.policy.toolInspection;
|
|
5830
5865
|
CODE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
@@ -5889,23 +5924,23 @@ var init_scan = __esm({
|
|
|
5889
5924
|
});
|
|
5890
5925
|
|
|
5891
5926
|
// src/tui/dashboard/data.ts
|
|
5892
|
-
import
|
|
5927
|
+
import fs9 from "fs";
|
|
5893
5928
|
import os11 from "os";
|
|
5894
|
-
import
|
|
5929
|
+
import path12 from "path";
|
|
5895
5930
|
import http from "http";
|
|
5896
5931
|
function auditLogPath() {
|
|
5897
|
-
return
|
|
5932
|
+
return path12.join(os11.homedir(), ".node9", "audit.log");
|
|
5898
5933
|
}
|
|
5899
5934
|
function readAuditEntriesAsync(chunkSize = 1e3, customPath) {
|
|
5900
5935
|
return new Promise((resolve) => {
|
|
5901
5936
|
const p = customPath ?? auditLogPath();
|
|
5902
|
-
if (!
|
|
5937
|
+
if (!fs9.existsSync(p)) {
|
|
5903
5938
|
resolve([]);
|
|
5904
5939
|
return;
|
|
5905
5940
|
}
|
|
5906
5941
|
let raw;
|
|
5907
5942
|
try {
|
|
5908
|
-
raw =
|
|
5943
|
+
raw = fs9.readFileSync(p, "utf8");
|
|
5909
5944
|
} catch {
|
|
5910
5945
|
resolve([]);
|
|
5911
5946
|
return;
|
|
@@ -6041,9 +6076,9 @@ function shortenPath(p) {
|
|
|
6041
6076
|
return p.startsWith(home) ? p.replace(home, "~") : p;
|
|
6042
6077
|
}
|
|
6043
6078
|
async function loadReportAuditAsync(period) {
|
|
6044
|
-
const claudeProjectsDir =
|
|
6045
|
-
const codexSessionsDir =
|
|
6046
|
-
const geminiTmpDir =
|
|
6079
|
+
const claudeProjectsDir = path12.join(os11.homedir(), ".claude", "projects");
|
|
6080
|
+
const codexSessionsDir = path12.join(os11.homedir(), ".codex", "sessions");
|
|
6081
|
+
const geminiTmpDir = path12.join(os11.homedir(), ".gemini", "tmp");
|
|
6047
6082
|
const { start, end } = getDateRange(period, /* @__PURE__ */ new Date());
|
|
6048
6083
|
const entries = await readAuditEntriesAsync();
|
|
6049
6084
|
void ensurePricingLoaded();
|
|
@@ -7124,8 +7159,8 @@ import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-run
|
|
|
7124
7159
|
function TopToolsProjects({ audit }) {
|
|
7125
7160
|
const data = audit?.data;
|
|
7126
7161
|
const tools = data ? [...data.toolMap.entries()].sort(([, a], [, b]) => b.calls - a.calls).slice(0, ROW_LIMIT) : [];
|
|
7127
|
-
const projects = data ? [...data.cost.byProject.entries()].map(([
|
|
7128
|
-
name: basenameOf(
|
|
7162
|
+
const projects = data ? [...data.cost.byProject.entries()].map(([path13, r]) => ({
|
|
7163
|
+
name: basenameOf(path13),
|
|
7129
7164
|
cost: r.cost,
|
|
7130
7165
|
tokens: r.inputTokens + r.outputTokens
|
|
7131
7166
|
})).sort((a, b) => b.cost - a.cost).slice(0, ROW_LIMIT) : [];
|
|
@@ -7562,8 +7597,8 @@ function pickTopLoopFile(loops) {
|
|
|
7562
7597
|
map.set(k, (map.get(k) ?? 0) + (l.count ?? 0));
|
|
7563
7598
|
}
|
|
7564
7599
|
if (map.size === 0) return void 0;
|
|
7565
|
-
const [
|
|
7566
|
-
return { path:
|
|
7600
|
+
const [path13, count] = [...map.entries()].sort((a, b) => b[1] - a[1])[0];
|
|
7601
|
+
return { path: path13, count };
|
|
7567
7602
|
}
|
|
7568
7603
|
var EMPTY_FILTERED_SCAN;
|
|
7569
7604
|
var init_derive = __esm({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@node9/proxy",
|
|
3
|
-
"version": "2.7.
|
|
3
|
+
"version": "2.7.1",
|
|
4
4
|
"description": "The Sudo Command for AI Agents. Execution Security for Claude Code, Codex, Gemini, Cursor, Opencode, Pi, and any MCP server.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|