ahp-inspector 1.4.1 → 1.4.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/index.js CHANGED
@@ -2,48 +2,156 @@
2
2
 
3
3
  // src/index.ts
4
4
  import { existsSync as existsSync2, readFileSync, statSync as statSync3 } from "fs";
5
- import { dirname as dirname3, join as join7, resolve as resolvePath } from "path";
5
+ import { dirname as dirname5, join as join7, resolve as resolvePath } from "path";
6
6
  import { fileURLToPath } from "url";
7
7
 
8
8
  // ../host-node/src/discovery.ts
9
9
  import { createHash } from "crypto";
10
- import { readdir, stat } from "fs/promises";
11
10
  import { homedir } from "os";
12
- import { basename, join, sep } from "path";
11
+ import { basename as basename2, dirname as dirname2, isAbsolute, join as join2, relative, sep } from "path";
12
+
13
+ // ../host-node/src/bounded-log-discovery.ts
14
+ import { opendir, stat } from "fs/promises";
15
+ import { basename, dirname, join } from "path";
16
+ async function scanConfiguredRoots(options) {
17
+ const now = options.now ?? Date.now;
18
+ const maxDepthBelowLaunch = options.maxDepthBelowLaunch ?? 3;
19
+ const rootResults = [];
20
+ for (const [rootIndex, root] of options.roots.entries()) {
21
+ const state = {
22
+ stats: 0,
23
+ immediateEntries: 0,
24
+ truncated: false,
25
+ startedAt: now(),
26
+ files: []
27
+ };
28
+ const launchEntries = [];
29
+ let rootDirectory;
30
+ try {
31
+ rootDirectory = await opendir(root.dir);
32
+ while (true) {
33
+ if (rootScanOverBudget(state, options, now, true)) break;
34
+ const entry = await rootDirectory.read();
35
+ if (!entry) break;
36
+ state.immediateEntries++;
37
+ const absPath = join(root.dir, entry.name);
38
+ const entryStat = await boundedStat(absPath, state, options, now);
39
+ if (!entryStat) continue;
40
+ if (entryStat.isDirectory()) {
41
+ launchEntries.push({ absPath, mtimeMs: entryStat.mtimeMs });
42
+ } else if (entryStat.isFile() && options.matchesFilename(entry.name)) {
43
+ state.files.push(toScannedFile(absPath, root.dir, entryStat.mtimeMs, entryStat.size));
44
+ }
45
+ }
46
+ } catch {
47
+ } finally {
48
+ await rootDirectory?.close().catch(() => {
49
+ });
50
+ }
51
+ launchEntries.sort((left, right) => right.mtimeMs - left.mtimeMs);
52
+ if (launchEntries.length > options.topLaunchDirs) state.truncated = true;
53
+ for (const launch of launchEntries.slice(0, options.topLaunchDirs)) {
54
+ if (rootScanOverBudget(state, options, now, false)) break;
55
+ await walkLaunchDirectory(launch.absPath, launch.absPath, maxDepthBelowLaunch, state, options, now);
56
+ }
57
+ rootResults.push({
58
+ rootIndex,
59
+ files: state.files,
60
+ truncated: state.truncated,
61
+ statsAttempted: state.stats,
62
+ immediateEntriesExamined: state.immediateEntries
63
+ });
64
+ }
65
+ return { roots: rootResults, truncated: rootResults.some((root) => root.truncated) };
66
+ }
67
+ async function walkLaunchDirectory(absDir, launchDir, depthLeft, state, options, now) {
68
+ if (depthLeft < 0 || rootScanOverBudget(state, options, now, false)) return;
69
+ let directory;
70
+ try {
71
+ directory = await opendir(absDir);
72
+ while (true) {
73
+ if (rootScanOverBudget(state, options, now, false)) return;
74
+ const entry = await directory.read();
75
+ if (!entry) return;
76
+ const absPath = join(absDir, entry.name);
77
+ const entryStat = await boundedStat(absPath, state, options, now);
78
+ if (!entryStat) continue;
79
+ if (entryStat.isDirectory()) {
80
+ if (depthLeft === 0) {
81
+ state.truncated = true;
82
+ } else {
83
+ await walkLaunchDirectory(absPath, launchDir, depthLeft - 1, state, options, now);
84
+ }
85
+ } else if (entryStat.isFile() && options.matchesFilename(entry.name)) {
86
+ state.files.push(toScannedFile(absPath, launchDir, entryStat.mtimeMs, entryStat.size));
87
+ }
88
+ }
89
+ } catch {
90
+ } finally {
91
+ await directory?.close().catch(() => {
92
+ });
93
+ }
94
+ }
95
+ async function boundedStat(absPath, state, options, now) {
96
+ if (rootScanOverBudget(state, options, now, false)) return void 0;
97
+ state.stats++;
98
+ try {
99
+ return await stat(absPath);
100
+ } catch {
101
+ return void 0;
102
+ }
103
+ }
104
+ function rootScanOverBudget(state, options, now, includeImmediateEntries) {
105
+ const overBudget = state.stats >= options.maxStats || now() - state.startedAt >= options.timeBudgetMs || includeImmediateEntries && state.immediateEntries >= options.maxImmediateEntries;
106
+ if (overBudget) state.truncated = true;
107
+ return overBudget;
108
+ }
109
+ function toScannedFile(absPath, launchDir, mtimeMs, sizeBytes) {
110
+ return {
111
+ absPath,
112
+ name: basename(absPath),
113
+ parentDir: dirname(absPath),
114
+ launchDir,
115
+ mtimeMs,
116
+ sizeBytes
117
+ };
118
+ }
119
+
120
+ // ../host-node/src/discovery.ts
13
121
  var DEFAULT_TIME_BUDGET_MS = 1500;
14
122
  var DEFAULT_MAX_STATS = 5e3;
123
+ var DEFAULT_MAX_IMMEDIATE_ENTRIES = 5e3;
15
124
  var DEFAULT_TOP_LAUNCH_DIRS = 10;
16
- var MAX_LAUNCH_LIST = 50;
17
125
  var MAX_RESULTS = 200;
18
126
  var MAX_DEPTH_BELOW_LAUNCH = 3;
19
127
  function defaultRoots() {
20
128
  const home = homedir();
21
129
  const platform = process.platform;
22
130
  const ossDevRoots = [
23
- { origin: "vscode-oss-dev", dir: join(home, ".vscode-oss-dev", "logs") },
24
- { origin: "vscode-oss-dev", dir: join(home, ".vscode-oss-agents-dev", "logs") }
131
+ { origin: "vscode-oss-dev", dir: join2(home, ".vscode-oss-dev", "logs") },
132
+ { origin: "vscode-oss-dev", dir: join2(home, ".vscode-oss-agents-dev", "logs") }
25
133
  ];
26
134
  if (platform === "darwin") {
27
135
  return [
28
- { origin: "vscode", dir: join(home, "Library", "Application Support", "Code", "logs") },
136
+ { origin: "vscode", dir: join2(home, "Library", "Application Support", "Code", "logs") },
29
137
  {
30
138
  origin: "vscode-insiders",
31
- dir: join(home, "Library", "Application Support", "Code - Insiders", "logs")
139
+ dir: join2(home, "Library", "Application Support", "Code - Insiders", "logs")
32
140
  },
33
141
  ...ossDevRoots
34
142
  ];
35
143
  }
36
144
  if (platform === "win32") {
37
- const appData = process.env.APPDATA ?? join(home, "AppData", "Roaming");
145
+ const appData = process.env.APPDATA ?? join2(home, "AppData", "Roaming");
38
146
  return [
39
- { origin: "vscode", dir: join(appData, "Code", "logs") },
40
- { origin: "vscode-insiders", dir: join(appData, "Code - Insiders", "logs") },
147
+ { origin: "vscode", dir: join2(appData, "Code", "logs") },
148
+ { origin: "vscode-insiders", dir: join2(appData, "Code - Insiders", "logs") },
41
149
  ...ossDevRoots
42
150
  ];
43
151
  }
44
152
  return [
45
- { origin: "vscode", dir: join(home, ".config", "Code", "logs") },
46
- { origin: "vscode-insiders", dir: join(home, ".config", "Code - Insiders", "logs") },
153
+ { origin: "vscode", dir: join2(home, ".config", "Code", "logs") },
154
+ { origin: "vscode-insiders", dir: join2(home, ".config", "Code - Insiders", "logs") },
47
155
  ...ossDevRoots
48
156
  ];
49
157
  }
@@ -70,132 +178,97 @@ function makeId(absPath) {
70
178
  return createHash("sha256").update(absPath).digest("hex").slice(0, 32);
71
179
  }
72
180
  function makeContextLabel(absPath, launchDir) {
73
- const idx = absPath.indexOf(launchDir);
74
- if (idx < 0) return "";
75
- const tail = absPath.slice(idx).split(sep).filter(Boolean);
76
- tail.pop();
77
- return tail.join(" / ");
181
+ const relativeParent = relative(launchDir, dirname2(absPath));
182
+ if (relativeParent === "" || relativeParent === ".") return "";
183
+ if (isAbsolute(relativeParent) || relativeParent === ".." || relativeParent.startsWith(`..${sep}`)) return "";
184
+ return [basename2(launchDir), ...relativeParent.split(sep).filter(Boolean)].join(" / ");
78
185
  }
79
186
  var idToPath = /* @__PURE__ */ new Map();
187
+ var discoveryGeneration = 0;
80
188
  function resolveCandidateId(id) {
81
189
  return idToPath.get(id) ?? null;
82
190
  }
83
191
  async function discoverVsCodeLogs(opts = {}) {
84
192
  const roots = opts.roots ?? defaultRoots();
85
- const timeBudget = opts.timeBudgetMs ?? DEFAULT_TIME_BUDGET_MS;
86
- const maxStats = opts.maxStats ?? DEFAULT_MAX_STATS;
87
- const topLaunch = opts.topLaunchDirs ?? DEFAULT_TOP_LAUNCH_DIRS;
88
- const now = opts.now ?? Date.now;
89
- const startedAt = now();
90
- let stats = 0;
91
- let truncated = false;
92
- const collected = [];
193
+ const generation = ++discoveryGeneration;
93
194
  idToPath.clear();
94
- const overBudget = () => stats >= maxStats || now() - startedAt >= timeBudget;
95
- for (const root of roots) {
96
- if (overBudget()) {
97
- truncated = true;
98
- break;
99
- }
100
- const launchEntries = [];
101
- try {
102
- const names = await readdir(root.dir);
103
- const limited = names.slice(0, MAX_LAUNCH_LIST);
104
- for (const name of limited) {
105
- if (overBudget()) {
106
- truncated = true;
107
- break;
108
- }
109
- try {
110
- const st = await stat(join(root.dir, name));
111
- stats++;
112
- if (st.isDirectory()) launchEntries.push({ name, mtimeMs: st.mtimeMs });
113
- } catch {
114
- }
115
- }
116
- } catch {
117
- continue;
118
- }
119
- launchEntries.sort((a, b) => b.mtimeMs - a.mtimeMs);
120
- const topEntries = launchEntries.slice(0, topLaunch);
121
- for (const launch of topEntries) {
122
- if (overBudget()) {
123
- truncated = true;
124
- break;
125
- }
126
- const launchDir = join(root.dir, launch.name);
127
- await walkBounded(
128
- launchDir,
129
- launchDir,
130
- MAX_DEPTH_BELOW_LAUNCH,
131
- root.origin,
132
- collected,
133
- () => {
134
- stats++;
135
- return overBudget();
136
- }
137
- );
138
- }
139
- }
140
- const out = collected.map((c) => c).sort((a, b) => {
141
- const order = { high: 0, medium: 1, low: 2 };
142
- const av = order[a.confidence];
143
- const bv = order[b.confidence];
144
- if (av !== bv) return av - bv;
145
- return b.mtimeMs - a.mtimeMs;
146
- }).slice(0, MAX_RESULTS);
147
- return { candidates: out, truncated };
148
- async function walkBounded(absDir, launchDir, depthLeft, origin, sink, tickAndCheck) {
149
- if (depthLeft < 0) return;
150
- let names;
151
- try {
152
- names = await readdir(absDir);
153
- } catch {
154
- return;
155
- }
156
- for (const name of names) {
157
- if (tickAndCheck()) {
158
- truncated = true;
159
- return;
160
- }
161
- const abs = join(absDir, name);
162
- let st;
163
- try {
164
- st = await stat(abs);
165
- } catch {
166
- continue;
167
- }
168
- if (st.isDirectory()) {
169
- await walkBounded(abs, launchDir, depthLeft - 1, origin, sink, tickAndCheck);
170
- continue;
171
- }
172
- if (!st.isFile()) continue;
173
- const ok = FILENAME_RE_AHP_JSONL.test(name) || FILENAME_RE_AHP_NAMED_JSONL.test(name);
174
- if (!ok) continue;
175
- const sc = score(name, st.mtimeMs, st.size, absDir);
176
- const id = makeId(abs);
177
- idToPath.set(id, abs);
178
- const confidence = tier(sc);
179
- sink.push({
180
- id,
181
- label: basename(abs),
182
- mtimeMs: st.mtimeMs,
183
- sizeBytes: st.size,
184
- origin,
185
- confidence,
186
- contextLabel: makeContextLabel(abs, launchDir)
187
- });
188
- if (sink.length >= MAX_RESULTS * 4) {
189
- truncated = true;
190
- return;
191
- }
195
+ const scan = await scanConfiguredRoots({
196
+ roots,
197
+ matchesFilename: matchesAhpFilename,
198
+ timeBudgetMs: opts.timeBudgetMs ?? DEFAULT_TIME_BUDGET_MS,
199
+ maxStats: opts.maxStats ?? DEFAULT_MAX_STATS,
200
+ maxImmediateEntries: opts.maxImmediateEntries ?? DEFAULT_MAX_IMMEDIATE_ENTRIES,
201
+ topLaunchDirs: opts.topLaunchDirs ?? DEFAULT_TOP_LAUNCH_DIRS,
202
+ maxDepthBelowLaunch: MAX_DEPTH_BELOW_LAUNCH,
203
+ now: opts.now ?? Date.now
204
+ });
205
+ const populatedRoots = scan.roots.map((scannedRoot) => {
206
+ const root = roots[scannedRoot.rootIndex];
207
+ if (!root) return [];
208
+ return scannedRoot.files.map((file) => toPickerCandidate(file, root.origin)).sort(comparePickerCandidates);
209
+ }).filter((candidates) => candidates.length > 0);
210
+ const effectiveResultCap = Math.max(MAX_RESULTS, populatedRoots.length);
211
+ const retained = [];
212
+ const retainedPaths = /* @__PURE__ */ new Set();
213
+ for (const candidates of populatedRoots) {
214
+ const candidate = candidates[0];
215
+ if (!candidate || retainedPaths.has(candidate.absPath)) continue;
216
+ retained.push(candidate);
217
+ retainedPaths.add(candidate.absPath);
218
+ }
219
+ const remainingCapacity = effectiveResultCap - retained.length;
220
+ const extraQuota = populatedRoots.length > 0 ? Math.floor(remainingCapacity / populatedRoots.length) : 0;
221
+ for (const candidates of populatedRoots) {
222
+ for (const candidate of candidates.slice(1, 1 + extraQuota)) {
223
+ if (retainedPaths.has(candidate.absPath)) continue;
224
+ retained.push(candidate);
225
+ retainedPaths.add(candidate.absPath);
226
+ }
227
+ }
228
+ const fillCandidates = populatedRoots.flat().filter((candidate) => !retainedPaths.has(candidate.absPath)).sort(comparePickerCandidates);
229
+ for (const candidate of fillCandidates) {
230
+ if (retained.length >= effectiveResultCap) break;
231
+ if (retainedPaths.has(candidate.absPath)) continue;
232
+ retained.push(candidate);
233
+ retainedPaths.add(candidate.absPath);
234
+ }
235
+ retained.sort(comparePickerCandidates);
236
+ if (generation === discoveryGeneration) {
237
+ idToPath.clear();
238
+ for (const candidate of retained) idToPath.set(candidate.safe.id, candidate.absPath);
239
+ }
240
+ const totalCandidateCount = new Set(populatedRoots.flat().map((candidate) => candidate.absPath)).size;
241
+ return {
242
+ candidates: retained.map((candidate) => candidate.safe),
243
+ truncated: scan.truncated || retained.length < totalCandidateCount
244
+ };
245
+ }
246
+ function toPickerCandidate(file, origin) {
247
+ const confidence = tier(score(file.name, file.mtimeMs, file.sizeBytes, file.parentDir));
248
+ return {
249
+ absPath: file.absPath,
250
+ safe: {
251
+ id: makeId(file.absPath),
252
+ label: file.name,
253
+ mtimeMs: file.mtimeMs,
254
+ sizeBytes: file.sizeBytes,
255
+ origin,
256
+ confidence,
257
+ contextLabel: makeContextLabel(file.absPath, file.launchDir)
192
258
  }
193
- }
259
+ };
260
+ }
261
+ function comparePickerCandidates(left, right) {
262
+ const order = { high: 0, medium: 1, low: 2 };
263
+ const confidenceDifference = order[left.safe.confidence] - order[right.safe.confidence];
264
+ return confidenceDifference || right.safe.mtimeMs - left.safe.mtimeMs;
265
+ }
266
+ function matchesAhpFilename(name) {
267
+ return FILENAME_RE_AHP_JSONL.test(name) || FILENAME_RE_AHP_NAMED_JSONL.test(name);
194
268
  }
195
269
 
196
270
  // ../host-node/src/find-latest-ahp-log.ts
197
- import { open as fsOpen, readdir as readdir2, stat as stat2 } from "fs/promises";
198
- import { join as join2 } from "path";
271
+ import { open as fsOpen } from "fs/promises";
199
272
 
200
273
  // ../parser/src/jsonl.ts
201
274
  var MAX_BUF_BYTES = 16 * 1024 * 1024;
@@ -550,55 +623,29 @@ function extractWireMeta(raw2) {
550
623
  // ../host-node/src/find-latest-ahp-log.ts
551
624
  var DEFAULT_TIME_BUDGET_MS2 = 1500;
552
625
  var DEFAULT_MAX_STATS2 = 5e3;
553
- var MAX_DEPTH_BELOW_ROOT = 5;
554
- var MAX_PROBE_CANDIDATES = 10;
626
+ var DEFAULT_MAX_IMMEDIATE_ENTRIES2 = 5e3;
627
+ var DEFAULT_TOP_LAUNCH_DIRS2 = 10;
628
+ var MAX_DEPTH_BELOW_LAUNCH2 = 4;
555
629
  var PROBE_READ_BYTES = 64 * 1024;
556
630
  async function findLatestAhpLog(opts = {}) {
557
631
  const roots = opts.rootsOverride ?? defaultRoots();
558
- const startedAt = Date.now();
559
- let stats = 0;
560
- const overBudget = () => stats >= DEFAULT_MAX_STATS2 || Date.now() - startedAt >= DEFAULT_TIME_BUDGET_MS2;
561
- const collected = [];
562
- for (const root of roots) {
563
- if (overBudget()) break;
564
- await walk(root.dir, MAX_DEPTH_BELOW_ROOT, collected, () => {
565
- stats++;
566
- return overBudget();
567
- });
568
- }
569
- const ranked = collected.filter((c) => c.sizeBytes > 0).sort((a, b) => b.mtimeMs - a.mtimeMs).slice(0, MAX_PROBE_CANDIDATES);
570
- for (const c of ranked) {
571
- if (await probeAhpShape(c.absPath)) return c.absPath;
632
+ const scan = await scanConfiguredRoots({
633
+ roots,
634
+ matchesFilename: matchesAhpFilename2,
635
+ timeBudgetMs: DEFAULT_TIME_BUDGET_MS2,
636
+ maxStats: DEFAULT_MAX_STATS2,
637
+ maxImmediateEntries: DEFAULT_MAX_IMMEDIATE_ENTRIES2,
638
+ topLaunchDirs: DEFAULT_TOP_LAUNCH_DIRS2,
639
+ maxDepthBelowLaunch: MAX_DEPTH_BELOW_LAUNCH2
640
+ });
641
+ const ranked = scan.roots.flatMap((root) => root.files).filter((candidate) => candidate.sizeBytes > 0).sort((left, right) => right.mtimeMs - left.mtimeMs);
642
+ for (const candidate of ranked) {
643
+ if (await probeAhpShape(candidate.absPath)) return candidate.absPath;
572
644
  }
573
645
  return null;
574
646
  }
575
- async function walk(absDir, depthLeft, sink, tickAndCheck) {
576
- if (depthLeft < 0) return;
577
- let names;
578
- try {
579
- names = await readdir2(absDir);
580
- } catch {
581
- return;
582
- }
583
- for (const name of names) {
584
- if (tickAndCheck()) return;
585
- const abs = join2(absDir, name);
586
- let st;
587
- try {
588
- st = await stat2(abs);
589
- } catch {
590
- continue;
591
- }
592
- if (st.isDirectory()) {
593
- await walk(abs, depthLeft - 1, sink, tickAndCheck);
594
- continue;
595
- }
596
- if (!st.isFile()) continue;
597
- if (!(FILENAME_RE_AHP_JSONL.test(name) || FILENAME_RE_AHP_NAMED_JSONL.test(name))) {
598
- continue;
599
- }
600
- sink.push({ absPath: abs, mtimeMs: st.mtimeMs, sizeBytes: st.size });
601
- }
647
+ function matchesAhpFilename2(name) {
648
+ return FILENAME_RE_AHP_JSONL.test(name) || FILENAME_RE_AHP_NAMED_JSONL.test(name);
602
649
  }
603
650
  async function probeAhpShape(absPath) {
604
651
  let fh;
@@ -637,7 +684,7 @@ async function probeAhpShape(absPath) {
637
684
 
638
685
  // ../host-node/src/host-adapter.ts
639
686
  import { accessSync, constants, statSync } from "fs";
640
- import { basename as basename4, resolve as pathResolve } from "path";
687
+ import { basename as basename5, resolve as pathResolve } from "path";
641
688
 
642
689
  // ../host-node/src/tail-reader.ts
643
690
  import { createReadStream } from "fs";
@@ -646,11 +693,11 @@ import { stat as fsStat } from "fs/promises";
646
693
  // ../../node_modules/.pnpm/chokidar@5.0.0/node_modules/chokidar/index.js
647
694
  import { EventEmitter } from "events";
648
695
  import { stat as statcb, Stats } from "fs";
649
- import { readdir as readdir4, stat as stat5 } from "fs/promises";
696
+ import { readdir as readdir2, stat as stat4 } from "fs/promises";
650
697
  import * as sp2 from "path";
651
698
 
652
699
  // ../../node_modules/.pnpm/readdirp@5.0.0/node_modules/readdirp/index.js
653
- import { lstat, readdir as readdir3, realpath, stat as stat3 } from "fs/promises";
700
+ import { lstat, readdir, realpath, stat as stat2 } from "fs/promises";
654
701
  import { join as pjoin, relative as prelative, resolve as presolve, sep as psep } from "path";
655
702
  import { Readable } from "stream";
656
703
  var EntryTypes = {
@@ -731,7 +778,7 @@ var ReaddirpStream = class extends Readable {
731
778
  const { root, type } = opts;
732
779
  this._fileFilter = normalizeFilter(opts.fileFilter);
733
780
  this._directoryFilter = normalizeFilter(opts.directoryFilter);
734
- const statMethod = opts.lstat ? lstat : stat3;
781
+ const statMethod = opts.lstat ? lstat : stat2;
735
782
  if (wantBigintFsStats) {
736
783
  this._stat = (path) => statMethod(path, { bigint: true });
737
784
  } else {
@@ -802,7 +849,7 @@ var ReaddirpStream = class extends Readable {
802
849
  async _exploreDir(path, depth) {
803
850
  let files;
804
851
  try {
805
- files = await readdir3(path, this._rdOptions);
852
+ files = await readdir(path, this._rdOptions);
806
853
  } catch (error) {
807
854
  this._onError(error);
808
855
  }
@@ -810,10 +857,10 @@ var ReaddirpStream = class extends Readable {
810
857
  }
811
858
  async _formatEntry(dirent, path) {
812
859
  let entry;
813
- const basename6 = this._isDirent ? dirent.name : dirent;
860
+ const basename7 = this._isDirent ? dirent.name : dirent;
814
861
  try {
815
- const fullPath = presolve(pjoin(path, basename6));
816
- entry = { path: prelative(this._root, fullPath), fullPath, basename: basename6 };
862
+ const fullPath = presolve(pjoin(path, basename7));
863
+ entry = { path: prelative(this._root, fullPath), fullPath, basename: basename7 };
817
864
  entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
818
865
  } catch (err) {
819
866
  this._onError(err);
@@ -884,7 +931,7 @@ function readdirp(root, options = {}) {
884
931
 
885
932
  // ../../node_modules/.pnpm/chokidar@5.0.0/node_modules/chokidar/handler.js
886
933
  import { watch as fs_watch, unwatchFile, watchFile } from "fs";
887
- import { realpath as fsrealpath, lstat as lstat2, open, stat as stat4 } from "fs/promises";
934
+ import { realpath as fsrealpath, lstat as lstat2, open, stat as stat3 } from "fs/promises";
888
935
  import { type as osType } from "os";
889
936
  import * as sp from "path";
890
937
  var STR_DATA = "data";
@@ -911,7 +958,7 @@ var EVENTS = {
911
958
  };
912
959
  var EV = EVENTS;
913
960
  var THROTTLE_MODE_WATCH = "watch";
914
- var statMethods = { lstat: lstat2, stat: stat4 };
961
+ var statMethods = { lstat: lstat2, stat: stat3 };
915
962
  var KEY_LISTENERS = "listeners";
916
963
  var KEY_ERR = "errHandlers";
917
964
  var KEY_RAW = "rawEmitters";
@@ -1354,9 +1401,9 @@ var NodeFsHandler = class {
1354
1401
  _watchWithNodeFs(path, listener) {
1355
1402
  const opts = this.fsw.options;
1356
1403
  const directory = sp.dirname(path);
1357
- const basename6 = sp.basename(path);
1404
+ const basename7 = sp.basename(path);
1358
1405
  const parent = this.fsw._getWatchedDir(directory);
1359
- parent.add(basename6);
1406
+ parent.add(basename7);
1360
1407
  const absolutePath = sp.resolve(path);
1361
1408
  const options = {
1362
1409
  persistent: opts.persistent
@@ -1366,7 +1413,7 @@ var NodeFsHandler = class {
1366
1413
  let closer;
1367
1414
  if (opts.usePolling) {
1368
1415
  const enableBin = opts.interval !== opts.binaryInterval;
1369
- options.interval = enableBin && isBinaryPath(basename6) ? opts.binaryInterval : opts.interval;
1416
+ options.interval = enableBin && isBinaryPath(basename7) ? opts.binaryInterval : opts.interval;
1370
1417
  closer = setFsWatchFileListener(path, absolutePath, options, {
1371
1418
  listener,
1372
1419
  rawEmitter: this.fsw._emitRaw
@@ -1388,18 +1435,18 @@ var NodeFsHandler = class {
1388
1435
  if (this.fsw.closed) {
1389
1436
  return;
1390
1437
  }
1391
- const dirname4 = sp.dirname(file);
1392
- const basename6 = sp.basename(file);
1393
- const parent = this.fsw._getWatchedDir(dirname4);
1438
+ const dirname6 = sp.dirname(file);
1439
+ const basename7 = sp.basename(file);
1440
+ const parent = this.fsw._getWatchedDir(dirname6);
1394
1441
  let prevStats = stats;
1395
- if (parent.has(basename6))
1442
+ if (parent.has(basename7))
1396
1443
  return;
1397
1444
  const listener = async (path, newStats) => {
1398
1445
  if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
1399
1446
  return;
1400
1447
  if (!newStats || newStats.mtimeMs === 0) {
1401
1448
  try {
1402
- const newStats2 = await stat4(file);
1449
+ const newStats2 = await stat3(file);
1403
1450
  if (this.fsw.closed)
1404
1451
  return;
1405
1452
  const at = newStats2.atimeMs;
@@ -1417,9 +1464,9 @@ var NodeFsHandler = class {
1417
1464
  prevStats = newStats2;
1418
1465
  }
1419
1466
  } catch (error) {
1420
- this.fsw._remove(dirname4, basename6);
1467
+ this.fsw._remove(dirname6, basename7);
1421
1468
  }
1422
- } else if (parent.has(basename6)) {
1469
+ } else if (parent.has(basename7)) {
1423
1470
  const at = newStats.atimeMs;
1424
1471
  const mt = newStats.mtimeMs;
1425
1472
  if (!at || at <= mt || mt !== prevStats.mtimeMs) {
@@ -1667,11 +1714,11 @@ function createPattern(matcher) {
1667
1714
  if (matcher.path === string)
1668
1715
  return true;
1669
1716
  if (matcher.recursive) {
1670
- const relative3 = sp2.relative(matcher.path, string);
1671
- if (!relative3) {
1717
+ const relative4 = sp2.relative(matcher.path, string);
1718
+ if (!relative4) {
1672
1719
  return false;
1673
1720
  }
1674
- return !relative3.startsWith("..") && !sp2.isAbsolute(relative3);
1721
+ return !relative4.startsWith("..") && !sp2.isAbsolute(relative4);
1675
1722
  }
1676
1723
  return false;
1677
1724
  };
@@ -1773,7 +1820,7 @@ var DirEntry = class {
1773
1820
  return;
1774
1821
  const dir = this.path;
1775
1822
  try {
1776
- await readdir4(dir);
1823
+ await readdir2(dir);
1777
1824
  } catch (err) {
1778
1825
  if (this._removeWatcher) {
1779
1826
  this._removeWatcher(sp2.dirname(dir), sp2.basename(dir));
@@ -2123,7 +2170,7 @@ var FSWatcher = class extends EventEmitter {
2123
2170
  const fullPath = opts.cwd ? sp2.join(opts.cwd, path) : path;
2124
2171
  let stats2;
2125
2172
  try {
2126
- stats2 = await stat5(fullPath);
2173
+ stats2 = await stat4(fullPath);
2127
2174
  } catch (err) {
2128
2175
  }
2129
2176
  if (!stats2 || this.closed)
@@ -2250,8 +2297,8 @@ var FSWatcher = class extends EventEmitter {
2250
2297
  }
2251
2298
  return this._userIgnored(path, stats);
2252
2299
  }
2253
- _isntIgnored(path, stat6) {
2254
- return !this._isIgnored(path, stat6);
2300
+ _isntIgnored(path, stat5) {
2301
+ return !this._isIgnored(path, stat5);
2255
2302
  }
2256
2303
  /**
2257
2304
  * Provides a set of common helpers and properties relating to symlink handling.
@@ -2549,21 +2596,21 @@ var NodeHostAdapter = class {
2549
2596
  }
2550
2597
  async openLog(path) {
2551
2598
  const resolved = pathResolve(process.cwd(), path);
2552
- let stat6;
2599
+ let stat5;
2553
2600
  try {
2554
- stat6 = statSync(resolved);
2601
+ stat5 = statSync(resolved);
2555
2602
  } catch {
2556
- throw new Error(`openLog: cannot stat '${basename4(resolved)}'`);
2603
+ throw new Error(`openLog: cannot stat '${basename5(resolved)}'`);
2557
2604
  }
2558
- if (!stat6.isFile()) {
2559
- throw new Error(`openLog: '${basename4(resolved)}' is not a regular file`);
2605
+ if (!stat5.isFile()) {
2606
+ throw new Error(`openLog: '${basename5(resolved)}' is not a regular file`);
2560
2607
  }
2561
2608
  try {
2562
2609
  accessSync(resolved, constants.R_OK);
2563
2610
  } catch {
2564
- throw new Error(`openLog: '${basename4(resolved)}' is not readable`);
2611
+ throw new Error(`openLog: '${basename5(resolved)}' is not readable`);
2565
2612
  }
2566
- return { id: resolved, path: resolved, size: stat6.size };
2613
+ return { id: resolved, path: resolved, size: stat5.size };
2567
2614
  }
2568
2615
  watchLog(handle, sinkOrChunk) {
2569
2616
  const node = handle;
@@ -2589,7 +2636,7 @@ var NodeHostAdapter = class {
2589
2636
 
2590
2637
  // ../server/src/app-state.ts
2591
2638
  import { Buffer as Buffer2 } from "buffer";
2592
- import { basename as basename5 } from "path";
2639
+ import { basename as basename6 } from "path";
2593
2640
 
2594
2641
  // ../core/src/correlator.ts
2595
2642
  var Correlator = class {
@@ -4828,7 +4875,7 @@ async function createAppState(opts) {
4828
4875
  const handlePath = handle.path ?? handle.id;
4829
4876
  const initialMtimeMs = opts.initialMtimeMs ?? Date.now();
4830
4877
  const meta = {
4831
- filename: basename5(handlePath),
4878
+ filename: basename6(handlePath),
4832
4879
  sizeBytes: handle.size ?? 0,
4833
4880
  startedAt: Date.now(),
4834
4881
  logKey: opts.logKey ?? computeLogKey(handlePath, initialMtimeMs)
@@ -8830,7 +8877,7 @@ function classifyDirection(raw2) {
8830
8877
 
8831
8878
  // src/index.ts
8832
8879
  var __filename2 = fileURLToPath(import.meta.url);
8833
- var __dirname2 = dirname3(__filename2);
8880
+ var __dirname2 = dirname5(__filename2);
8834
8881
  function loadVersion() {
8835
8882
  const candidates = [join7(__dirname2, "..", "package.json"), join7(__dirname2, "package.json")];
8836
8883
  for (const p of candidates) {
@@ -8902,9 +8949,9 @@ var program = new Command().name("ahp-inspector").version(VERSION).argument(
8902
8949
  let absPath;
8903
8950
  if (file) {
8904
8951
  absPath = resolvePath(file);
8905
- let stat6;
8952
+ let stat5;
8906
8953
  try {
8907
- stat6 = statSync3(absPath);
8954
+ stat5 = statSync3(absPath);
8908
8955
  } catch (err) {
8909
8956
  const e = err;
8910
8957
  if (e.code === "ENOENT") {
@@ -8914,7 +8961,7 @@ Usage: ahp-inspector [path-to-log.jsonl]`);
8914
8961
  fail(`Error: cannot read ${absPath}: ${e.message}
8915
8962
  Check file permissions.`);
8916
8963
  }
8917
- if (!stat6.isFile()) {
8964
+ if (!stat5.isFile()) {
8918
8965
  fail(`Error: log file not found: ${absPath}
8919
8966
  Usage: ahp-inspector [path-to-log.jsonl]`);
8920
8967
  }