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