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
|
|
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:
|
|
24
|
-
{ origin: "vscode-oss-dev", dir:
|
|
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:
|
|
136
|
+
{ origin: "vscode", dir: join2(home, "Library", "Application Support", "Code", "logs") },
|
|
29
137
|
{
|
|
30
138
|
origin: "vscode-insiders",
|
|
31
|
-
dir:
|
|
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 ??
|
|
145
|
+
const appData = process.env.APPDATA ?? join2(home, "AppData", "Roaming");
|
|
38
146
|
return [
|
|
39
|
-
{ origin: "vscode", dir:
|
|
40
|
-
{ origin: "vscode-insiders", dir:
|
|
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:
|
|
46
|
-
{ origin: "vscode-insiders", dir:
|
|
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
|
|
74
|
-
if (
|
|
75
|
-
|
|
76
|
-
|
|
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
|
|
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
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
for (const
|
|
122
|
-
if (
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
return {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
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
|
|
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
|
|
554
|
-
var
|
|
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
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
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
|
-
|
|
576
|
-
|
|
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
|
|
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
|
|
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
|
|
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 :
|
|
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
|
|
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
|
|
860
|
+
const basename7 = this._isDirent ? dirent.name : dirent;
|
|
814
861
|
try {
|
|
815
|
-
const fullPath = presolve(pjoin(path,
|
|
816
|
-
entry = { path: prelative(this._root, fullPath), fullPath, basename:
|
|
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
|
|
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:
|
|
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
|
|
1404
|
+
const basename7 = sp.basename(path);
|
|
1358
1405
|
const parent = this.fsw._getWatchedDir(directory);
|
|
1359
|
-
parent.add(
|
|
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(
|
|
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
|
|
1392
|
-
const
|
|
1393
|
-
const parent = this.fsw._getWatchedDir(
|
|
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(
|
|
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
|
|
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(
|
|
1467
|
+
this.fsw._remove(dirname6, basename7);
|
|
1421
1468
|
}
|
|
1422
|
-
} else if (parent.has(
|
|
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
|
|
1671
|
-
if (!
|
|
1717
|
+
const relative4 = sp2.relative(matcher.path, string);
|
|
1718
|
+
if (!relative4) {
|
|
1672
1719
|
return false;
|
|
1673
1720
|
}
|
|
1674
|
-
return !
|
|
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
|
|
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
|
|
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,
|
|
2254
|
-
return !this._isIgnored(path,
|
|
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
|
|
2599
|
+
let stat5;
|
|
2553
2600
|
try {
|
|
2554
|
-
|
|
2601
|
+
stat5 = statSync(resolved);
|
|
2555
2602
|
} catch {
|
|
2556
|
-
throw new Error(`openLog: cannot stat '${
|
|
2603
|
+
throw new Error(`openLog: cannot stat '${basename5(resolved)}'`);
|
|
2557
2604
|
}
|
|
2558
|
-
if (!
|
|
2559
|
-
throw new Error(`openLog: '${
|
|
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: '${
|
|
2611
|
+
throw new Error(`openLog: '${basename5(resolved)}' is not readable`);
|
|
2565
2612
|
}
|
|
2566
|
-
return { id: resolved, path: resolved, 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
|
|
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:
|
|
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 =
|
|
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
|
|
8952
|
+
let stat5;
|
|
8906
8953
|
try {
|
|
8907
|
-
|
|
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 (!
|
|
8964
|
+
if (!stat5.isFile()) {
|
|
8918
8965
|
fail(`Error: log file not found: ${absPath}
|
|
8919
8966
|
Usage: ahp-inspector [path-to-log.jsonl]`);
|
|
8920
8967
|
}
|