@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.
@@ -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, path12) {
231
+ function getNestedValue(obj, path13) {
232
232
  if (!obj || typeof obj !== "object") return null;
233
- const segments = path12.split(".");
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 path12 = issue.path.length > 0 ? issue.path.join(".") : "root";
2337
- return ` \u2022 ${path12}: ${issue.message}`;
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 path12 = typeof jp?.path === "string" ? jp.path.trim() : "";
3217
- if (!path12) continue;
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(path12, verdict, "org-managed jail")) {
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: path12, verdict });
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 < 0 || ageMs > TTL_MS) return null;
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 fs6 from "fs";
4067
+ import fs7 from "fs";
4035
4068
  import os7 from "os";
4036
- import path7 from "path";
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 (!fs6.existsSync(logPath)) return [];
4118
- const raw = fs6.readFileSync(logPath, "utf-8");
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 = path7.join(projectsDir, proj);
4205
+ const projPath = path8.join(projectsDir, proj);
4173
4206
  let files;
4174
4207
  try {
4175
- const stat = fs6.statSync(projPath);
4208
+ const stat = fs7.statSync(projPath);
4176
4209
  if (!stat.isDirectory()) return;
4177
- files = fs6.readdirSync(projPath).filter((f) => f.endsWith(".jsonl") && !f.startsWith("agent-"));
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 = path7.join(projPath, file);
4216
+ const filePath = path8.join(projPath, file);
4184
4217
  try {
4185
- if (fs6.statSync(filePath).mtimeMs < startMs) continue;
4218
+ if (fs7.statSync(filePath).mtimeMs < startMs) continue;
4186
4219
  } catch {
4187
4220
  continue;
4188
4221
  }
4189
4222
  try {
4190
- const raw = fs6.readFileSync(filePath, "utf-8");
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 (!fs6.existsSync(projectsDir)) return freezeClaudeCost(acc);
4273
+ if (!fs7.existsSync(projectsDir)) return freezeClaudeCost(acc);
4241
4274
  let dirs;
4242
4275
  try {
4243
- dirs = fs6.readdirSync(projectsDir);
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 (!fs6.existsSync(projectsDir)) return freezeClaudeCost(acc);
4287
+ if (!fs7.existsSync(projectsDir)) return freezeClaudeCost(acc);
4255
4288
  let dirs;
4256
4289
  try {
4257
- dirs = fs6.readdirSync(projectsDir);
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 = fs6.readFileSync(filePath, "utf-8").split("\n");
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 (!fs6.existsSync(sessionsBase)) return jsonlFiles;
4358
+ if (!fs7.existsSync(sessionsBase)) return jsonlFiles;
4326
4359
  try {
4327
- for (const year of fs6.readdirSync(sessionsBase)) {
4328
- const yearPath = path7.join(sessionsBase, year);
4360
+ for (const year of fs7.readdirSync(sessionsBase)) {
4361
+ const yearPath = path8.join(sessionsBase, year);
4329
4362
  try {
4330
- if (!fs6.statSync(yearPath).isDirectory()) continue;
4363
+ if (!fs7.statSync(yearPath).isDirectory()) continue;
4331
4364
  } catch {
4332
4365
  continue;
4333
4366
  }
4334
- for (const month of fs6.readdirSync(yearPath)) {
4335
- const monthPath = path7.join(yearPath, month);
4367
+ for (const month of fs7.readdirSync(yearPath)) {
4368
+ const monthPath = path8.join(yearPath, month);
4336
4369
  try {
4337
- if (!fs6.statSync(monthPath).isDirectory()) continue;
4370
+ if (!fs7.statSync(monthPath).isDirectory()) continue;
4338
4371
  } catch {
4339
4372
  continue;
4340
4373
  }
4341
- for (const day of fs6.readdirSync(monthPath)) {
4342
- const dayPath = path7.join(monthPath, day);
4374
+ for (const day of fs7.readdirSync(monthPath)) {
4375
+ const dayPath = path8.join(monthPath, day);
4343
4376
  try {
4344
- if (!fs6.statSync(dayPath).isDirectory()) continue;
4377
+ if (!fs7.statSync(dayPath).isDirectory()) continue;
4345
4378
  } catch {
4346
4379
  continue;
4347
4380
  }
4348
- for (const file of fs6.readdirSync(dayPath)) {
4349
- if (file.endsWith(".jsonl")) jsonlFiles.push(path7.join(dayPath, file));
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 (fs6.statSync(filePath).mtimeMs < startMs) return;
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 = fs6.readFileSync(filePath, "utf-8");
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 (!fs6.statSync(geminiTmpDir).isDirectory()) return out;
4486
- dirs = fs6.readdirSync(geminiTmpDir);
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 = path7.join(geminiTmpDir, proj, "chats");
4524
+ const chatsDir = path8.join(geminiTmpDir, proj, "chats");
4492
4525
  let files;
4493
4526
  try {
4494
- if (!fs6.statSync(chatsDir).isDirectory()) continue;
4495
- files = fs6.readdirSync(chatsDir);
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: path7.join(chatsDir, f) });
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 (!fs6.existsSync(geminiTmpDir)) return freezeGeminiCost(acc);
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 (!fs6.existsSync(geminiTmpDir)) return freezeGeminiCost(acc);
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 ?? path7.join(os7.homedir(), ".node9", "audit.log");
4540
- const claudeProjectsDir = opts.claudeProjectsDir ?? path7.join(os7.homedir(), ".claude", "projects");
4541
- const codexSessionsDir = opts.codexSessionsDir ?? path7.join(os7.homedir(), ".codex", "sessions");
4542
- const geminiTmpDir = opts.geminiTmpDir ?? path7.join(os7.homedir(), ".gemini", "tmp");
4543
- const hasAuditFile = fs6.existsSync(auditLogPath2);
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 path8 from "path";
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
- path8.join(os8.homedir(), "bin"),
4788
- path8.join(os8.homedir(), ".local", "bin"),
4789
- path8.join(os8.homedir(), ".cargo", "bin"),
4790
- path8.join(os8.homedir(), ".npm-global", "bin"),
4791
- path8.join(os8.homedir(), ".volta", "bin")
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 path9 from "path";
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 = path9.join(os9.homedir(), ".node9", "hooks-baseline.json");
4842
- NOTIFIED_FILE = path9.join(os9.homedir(), ".node9", "hook-heal-notified.json");
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 fs7 from "fs";
4902
- import path10 from "path";
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.replace(/\.jsonl$/, "");
5083
+ const sessionId = sessionIdOf(file);
5050
5084
  const session = { sessionId, costUSD: 0, toolCalls: 0 };
5051
5085
  let raw;
5052
5086
  try {
5053
- raw = fs7.readFileSync(path10.join(projPath, file), "utf-8");
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 = path10.extname(filePath).toLowerCase();
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 ? path10.extname(inputFilePath).toLowerCase() : "";
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 = path10.join(projectsDir, proj);
5297
+ const projPath = path11.join(projectsDir, proj);
5264
5298
  try {
5265
- if (!fs7.statSync(projPath).isDirectory()) return;
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 = fs7.readdirSync(projPath).filter((f) => f.endsWith(".jsonl") && !f.startsWith("agent-"));
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 = path10.join(os10.homedir(), ".claude", "projects");
5348
+ const projectsDir = path11.join(os10.homedir(), ".claude", "projects");
5315
5349
  const result = emptyClaudeScan();
5316
- if (!fs7.existsSync(projectsDir)) return result;
5350
+ if (!fs8.existsSync(projectsDir)) return result;
5317
5351
  let projDirs;
5318
5352
  try {
5319
- projDirs = fs7.readdirSync(projectsDir);
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 = path10.join(os10.homedir(), ".gemini", "tmp");
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 (!fs7.existsSync(tmpDir)) return result;
5390
+ if (!fs8.existsSync(tmpDir)) return result;
5357
5391
  let slugDirs;
5358
5392
  try {
5359
- slugDirs = fs7.readdirSync(tmpDir);
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 = path10.join(tmpDir, slug2);
5399
+ const slugPath = path11.join(tmpDir, slug2);
5366
5400
  try {
5367
- if (!fs7.statSync(slugPath).isDirectory()) continue;
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
- fs7.readFileSync(path10.join(slugPath, ".project_root"), "utf-8").trim()
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 = path10.join(slugPath, "chats");
5379
- if (!fs7.existsSync(chatsDir)) continue;
5412
+ const chatsDir = path11.join(slugPath, "chats");
5413
+ if (!fs8.existsSync(chatsDir)) continue;
5380
5414
  let chatFiles;
5381
5415
  try {
5382
- chatFiles = fs7.readdirSync(chatsDir).filter((f) => f.endsWith(".json") || f.endsWith(".jsonl")).sort((a, b) => Number(b.endsWith(".jsonl")) - Number(a.endsWith(".jsonl")));
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 = fs7.readFileSync(path10.join(chatsDir, chatFile), "utf-8");
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 = path10.join(os10.homedir(), ".codex", "sessions");
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 (!fs7.existsSync(sessionsBase)) return result;
5618
+ if (!fs8.existsSync(sessionsBase)) return result;
5585
5619
  const jsonlFiles = [];
5586
5620
  try {
5587
- for (const year of fs7.readdirSync(sessionsBase)) {
5588
- const yearPath = path10.join(sessionsBase, year);
5621
+ for (const year of fs8.readdirSync(sessionsBase)) {
5622
+ const yearPath = path11.join(sessionsBase, year);
5589
5623
  try {
5590
- if (!fs7.statSync(yearPath).isDirectory()) continue;
5624
+ if (!fs8.statSync(yearPath).isDirectory()) continue;
5591
5625
  } catch {
5592
5626
  continue;
5593
5627
  }
5594
- for (const month of fs7.readdirSync(yearPath)) {
5595
- const monthPath = path10.join(yearPath, month);
5628
+ for (const month of fs8.readdirSync(yearPath)) {
5629
+ const monthPath = path11.join(yearPath, month);
5596
5630
  try {
5597
- if (!fs7.statSync(monthPath).isDirectory()) continue;
5631
+ if (!fs8.statSync(monthPath).isDirectory()) continue;
5598
5632
  } catch {
5599
5633
  continue;
5600
5634
  }
5601
- for (const day of fs7.readdirSync(monthPath)) {
5602
- const dayPath = path10.join(monthPath, day);
5635
+ for (const day of fs8.readdirSync(monthPath)) {
5636
+ const dayPath = path11.join(monthPath, day);
5603
5637
  try {
5604
- if (!fs7.statSync(dayPath).isDirectory()) continue;
5638
+ if (!fs8.statSync(dayPath).isDirectory()) continue;
5605
5639
  } catch {
5606
5640
  continue;
5607
5641
  }
5608
- for (const file of fs7.readdirSync(dayPath)) {
5609
- if (file.endsWith(".jsonl")) jsonlFiles.push(path10.join(dayPath, file));
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 = fs7.readFileSync(filePath, "utf-8").split("\n");
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 fs8 from "fs";
5927
+ import fs9 from "fs";
5893
5928
  import os11 from "os";
5894
- import path11 from "path";
5929
+ import path12 from "path";
5895
5930
  import http from "http";
5896
5931
  function auditLogPath() {
5897
- return path11.join(os11.homedir(), ".node9", "audit.log");
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 (!fs8.existsSync(p)) {
5937
+ if (!fs9.existsSync(p)) {
5903
5938
  resolve([]);
5904
5939
  return;
5905
5940
  }
5906
5941
  let raw;
5907
5942
  try {
5908
- raw = fs8.readFileSync(p, "utf8");
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 = path11.join(os11.homedir(), ".claude", "projects");
6045
- const codexSessionsDir = path11.join(os11.homedir(), ".codex", "sessions");
6046
- const geminiTmpDir = path11.join(os11.homedir(), ".gemini", "tmp");
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(([path12, r]) => ({
7128
- name: basenameOf(path12),
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 [path12, count] = [...map.entries()].sort((a, b) => b[1] - a[1])[0];
7566
- return { path: path12, count };
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.0",
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",