ahp-inspector 1.1.1 → 1.2.0
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,7 +2,7 @@
|
|
|
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
|
|
5
|
+
import { dirname as dirname3, join as join7, resolve as resolvePath } from "path";
|
|
6
6
|
import { fileURLToPath } from "url";
|
|
7
7
|
|
|
8
8
|
// ../host-node/src/discovery.ts
|
|
@@ -19,10 +19,10 @@ var MAX_DEPTH_BELOW_LAUNCH = 3;
|
|
|
19
19
|
function defaultRoots() {
|
|
20
20
|
const home = homedir();
|
|
21
21
|
const platform = process.platform;
|
|
22
|
-
const
|
|
23
|
-
origin: "vscode-oss-dev",
|
|
24
|
-
dir: join(home, ".vscode-oss-agents-dev", "logs")
|
|
25
|
-
|
|
22
|
+
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") }
|
|
25
|
+
];
|
|
26
26
|
if (platform === "darwin") {
|
|
27
27
|
return [
|
|
28
28
|
{ origin: "vscode", dir: join(home, "Library", "Application Support", "Code", "logs") },
|
|
@@ -30,7 +30,7 @@ function defaultRoots() {
|
|
|
30
30
|
origin: "vscode-insiders",
|
|
31
31
|
dir: join(home, "Library", "Application Support", "Code - Insiders", "logs")
|
|
32
32
|
},
|
|
33
|
-
|
|
33
|
+
...ossDevRoots
|
|
34
34
|
];
|
|
35
35
|
}
|
|
36
36
|
if (platform === "win32") {
|
|
@@ -38,13 +38,13 @@ function defaultRoots() {
|
|
|
38
38
|
return [
|
|
39
39
|
{ origin: "vscode", dir: join(appData, "Code", "logs") },
|
|
40
40
|
{ origin: "vscode-insiders", dir: join(appData, "Code - Insiders", "logs") },
|
|
41
|
-
|
|
41
|
+
...ossDevRoots
|
|
42
42
|
];
|
|
43
43
|
}
|
|
44
44
|
return [
|
|
45
45
|
{ origin: "vscode", dir: join(home, ".config", "Code", "logs") },
|
|
46
46
|
{ origin: "vscode-insiders", dir: join(home, ".config", "Code - Insiders", "logs") },
|
|
47
|
-
|
|
47
|
+
...ossDevRoots
|
|
48
48
|
];
|
|
49
49
|
}
|
|
50
50
|
var FILENAME_RE_AHP_JSONL = /^(agenthost|agent-host|ahp).*\.jsonl$/i;
|
|
@@ -474,6 +474,20 @@ function normalize(raw2, meta) {
|
|
|
474
474
|
};
|
|
475
475
|
}
|
|
476
476
|
|
|
477
|
+
// ../parser/src/wire-meta.ts
|
|
478
|
+
function extractWireMeta(raw2) {
|
|
479
|
+
if (raw2 === null || typeof raw2 !== "object") return null;
|
|
480
|
+
const log = raw2._ahpLog;
|
|
481
|
+
if (log === null || typeof log !== "object") return null;
|
|
482
|
+
const tsField = log.ts;
|
|
483
|
+
if (typeof tsField !== "string" || tsField.length === 0) return null;
|
|
484
|
+
const parsedTs = Date.parse(tsField);
|
|
485
|
+
if (!Number.isFinite(parsedTs)) return null;
|
|
486
|
+
const dirField = log.dir;
|
|
487
|
+
const dir = dirField === "c2s" || dirField === "s2c" ? dirField : null;
|
|
488
|
+
return { ts: parsedTs, tsRaw: tsField, dir };
|
|
489
|
+
}
|
|
490
|
+
|
|
477
491
|
// ../host-node/src/find-latest-ahp-log.ts
|
|
478
492
|
var DEFAULT_TIME_BUDGET_MS2 = 1500;
|
|
479
493
|
var DEFAULT_MAX_STATS2 = 5e3;
|
|
@@ -4754,10 +4768,13 @@ async function createAppState(opts) {
|
|
|
4754
4768
|
}
|
|
4755
4769
|
for (const line of lines) {
|
|
4756
4770
|
const byteLength = Buffer2.byteLength(line, "utf8");
|
|
4757
|
-
const ts = Date.now();
|
|
4758
4771
|
const parsed = parseLine(line, byteOffset, byteLength);
|
|
4759
|
-
const
|
|
4760
|
-
const
|
|
4772
|
+
const wire = parsed.error ? null : extractWireMeta(parsed.raw);
|
|
4773
|
+
const ingestNow = Date.now();
|
|
4774
|
+
const ts = wire?.ts ?? ingestNow;
|
|
4775
|
+
const tsRaw = wire?.tsRaw ?? String(ingestNow);
|
|
4776
|
+
const dir = parsed.error ? "c2s" : wire?.dir ?? inferDir(parsed.raw);
|
|
4777
|
+
const m = { seq, ts, tsRaw, dir, byteOffset, byteLength };
|
|
4761
4778
|
const ev = parsed.error ? makeParseErrorEvent(m, parsed.error.reason, parsed.text) : normalize(parsed.raw, m);
|
|
4762
4779
|
store.append(ev);
|
|
4763
4780
|
seq += 1;
|
|
@@ -4866,6 +4883,30 @@ async function createAppState(opts) {
|
|
|
4866
4883
|
};
|
|
4867
4884
|
}
|
|
4868
4885
|
|
|
4886
|
+
// ../server/src/cors.ts
|
|
4887
|
+
var corsMiddleware = async (c, next) => {
|
|
4888
|
+
const origin = c.req.header("origin");
|
|
4889
|
+
if (c.req.method === "OPTIONS") {
|
|
4890
|
+
const reqHeaders = c.req.header("access-control-request-headers") ?? "*";
|
|
4891
|
+
const reqMethod = c.req.header("access-control-request-method") ?? "GET";
|
|
4892
|
+
return new Response(null, {
|
|
4893
|
+
status: 204,
|
|
4894
|
+
headers: {
|
|
4895
|
+
"access-control-allow-origin": origin ?? "*",
|
|
4896
|
+
"access-control-allow-methods": `${reqMethod}, GET, POST, OPTIONS`,
|
|
4897
|
+
"access-control-allow-headers": reqHeaders,
|
|
4898
|
+
"access-control-max-age": "600",
|
|
4899
|
+
vary: "Origin"
|
|
4900
|
+
}
|
|
4901
|
+
});
|
|
4902
|
+
}
|
|
4903
|
+
await next();
|
|
4904
|
+
if (origin) {
|
|
4905
|
+
c.res.headers.set("access-control-allow-origin", origin);
|
|
4906
|
+
c.res.headers.append("vary", "Origin");
|
|
4907
|
+
}
|
|
4908
|
+
};
|
|
4909
|
+
|
|
4869
4910
|
// ../server/src/csp.ts
|
|
4870
4911
|
var CSP_VALUE = "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; font-src 'self'; img-src 'self' data:; connect-src 'self'; object-src 'none'; base-uri 'none'; frame-ancestors 'none'";
|
|
4871
4912
|
var cspMiddleware = async (c, next) => {
|
|
@@ -8266,12 +8307,132 @@ function registerStaticUi(app, distDir) {
|
|
|
8266
8307
|
app.get("/", serveStatic({ path: `${distDir}/index.html` }));
|
|
8267
8308
|
}
|
|
8268
8309
|
|
|
8310
|
+
// ../server/src/upload-routes.ts
|
|
8311
|
+
import { mkdir, rm, writeFile } from "fs/promises";
|
|
8312
|
+
import { tmpdir } from "os";
|
|
8313
|
+
import { extname as extname2, join as join6, basename as pathBasename } from "path";
|
|
8314
|
+
var MAX_UPLOAD_BYTES = 100 * 1024 * 1024;
|
|
8315
|
+
var UPLOAD_DIR_PREFIX = "ahp-inspector-upload-";
|
|
8316
|
+
function sanitizeFilename(raw2) {
|
|
8317
|
+
let decoded;
|
|
8318
|
+
try {
|
|
8319
|
+
decoded = decodeURIComponent(raw2);
|
|
8320
|
+
} catch {
|
|
8321
|
+
return null;
|
|
8322
|
+
}
|
|
8323
|
+
const stripped = pathBasename(decoded);
|
|
8324
|
+
let base = "";
|
|
8325
|
+
for (let i = 0; i < stripped.length; i++) {
|
|
8326
|
+
const code = stripped.charCodeAt(i);
|
|
8327
|
+
if (code >= 32 && code !== 127) base += stripped[i];
|
|
8328
|
+
}
|
|
8329
|
+
if (base.length === 0 || base.length > 255) return null;
|
|
8330
|
+
if (extname2(base).toLowerCase() !== ".jsonl") return null;
|
|
8331
|
+
return base;
|
|
8332
|
+
}
|
|
8333
|
+
function createUploadStore() {
|
|
8334
|
+
const dirs = /* @__PURE__ */ new Map();
|
|
8335
|
+
async function write(filename, bytes) {
|
|
8336
|
+
const dir = join6(
|
|
8337
|
+
tmpdir(),
|
|
8338
|
+
`${UPLOAD_DIR_PREFIX}${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`
|
|
8339
|
+
);
|
|
8340
|
+
await mkdir(dir, { recursive: true });
|
|
8341
|
+
const filePath = join6(dir, filename);
|
|
8342
|
+
await writeFile(filePath, bytes);
|
|
8343
|
+
dirs.set(filePath, dir);
|
|
8344
|
+
return filePath;
|
|
8345
|
+
}
|
|
8346
|
+
async function removeDir(dir) {
|
|
8347
|
+
try {
|
|
8348
|
+
await rm(dir, { recursive: true, force: true });
|
|
8349
|
+
} catch {
|
|
8350
|
+
}
|
|
8351
|
+
}
|
|
8352
|
+
async function cleanupAllExcept(keepPath) {
|
|
8353
|
+
const tasks = [];
|
|
8354
|
+
for (const [path, dir] of dirs) {
|
|
8355
|
+
if (path === keepPath) continue;
|
|
8356
|
+
dirs.delete(path);
|
|
8357
|
+
tasks.push(removeDir(dir));
|
|
8358
|
+
}
|
|
8359
|
+
await Promise.all(tasks);
|
|
8360
|
+
}
|
|
8361
|
+
async function disposeAll() {
|
|
8362
|
+
await cleanupAllExcept(null);
|
|
8363
|
+
}
|
|
8364
|
+
return { write, cleanupAllExcept, disposeAll };
|
|
8365
|
+
}
|
|
8366
|
+
function registerUploadRoutes(app, sessions) {
|
|
8367
|
+
const store = createUploadStore();
|
|
8368
|
+
const unsubscribe = sessions.onChange((active) => {
|
|
8369
|
+
if (active === null) {
|
|
8370
|
+
void store.disposeAll();
|
|
8371
|
+
}
|
|
8372
|
+
});
|
|
8373
|
+
const exitCleanup = () => {
|
|
8374
|
+
void store.disposeAll();
|
|
8375
|
+
};
|
|
8376
|
+
process.once("exit", exitCleanup);
|
|
8377
|
+
app.post("/api/sessions/upload", async (c) => {
|
|
8378
|
+
const filenameHeader = c.req.header("x-filename");
|
|
8379
|
+
if (typeof filenameHeader !== "string" || filenameHeader.length === 0) {
|
|
8380
|
+
return c.json({ code: "bad-request", message: "missing X-Filename" }, 400);
|
|
8381
|
+
}
|
|
8382
|
+
const safeName = sanitizeFilename(filenameHeader);
|
|
8383
|
+
if (safeName === null) {
|
|
8384
|
+
return c.json({ code: "not-jsonl", message: "not-jsonl" }, 400);
|
|
8385
|
+
}
|
|
8386
|
+
const lengthHeader = c.req.header("content-length");
|
|
8387
|
+
const declaredLength = lengthHeader ? Number.parseInt(lengthHeader, 10) : Number.NaN;
|
|
8388
|
+
if (Number.isFinite(declaredLength) && declaredLength > MAX_UPLOAD_BYTES) {
|
|
8389
|
+
return c.json({ code: "too-large", message: "too-large" }, 413);
|
|
8390
|
+
}
|
|
8391
|
+
let buf;
|
|
8392
|
+
try {
|
|
8393
|
+
buf = await c.req.arrayBuffer();
|
|
8394
|
+
} catch {
|
|
8395
|
+
return c.json({ code: "bad-request", message: "could not read body" }, 400);
|
|
8396
|
+
}
|
|
8397
|
+
if (buf.byteLength === 0) {
|
|
8398
|
+
return c.json({ code: "bad-request", message: "empty body" }, 400);
|
|
8399
|
+
}
|
|
8400
|
+
if (buf.byteLength > MAX_UPLOAD_BYTES) {
|
|
8401
|
+
return c.json({ code: "too-large", message: "too-large" }, 413);
|
|
8402
|
+
}
|
|
8403
|
+
let tempPath;
|
|
8404
|
+
try {
|
|
8405
|
+
tempPath = await store.write(safeName, new Uint8Array(buf));
|
|
8406
|
+
} catch {
|
|
8407
|
+
return c.json({ code: "io-error", message: "io-error" }, 500);
|
|
8408
|
+
}
|
|
8409
|
+
try {
|
|
8410
|
+
const active = await sessions.open({ path: tempPath });
|
|
8411
|
+
void store.cleanupAllExcept(tempPath);
|
|
8412
|
+
return c.json({ active: { logKey: active.logKey, meta: active.appState.meta } });
|
|
8413
|
+
} catch (err) {
|
|
8414
|
+
void store.cleanupAllExcept(null);
|
|
8415
|
+
const e = err;
|
|
8416
|
+
const code = typeof e.code === "string" ? e.code : "not-found";
|
|
8417
|
+
return c.json({ code, message: code }, 400);
|
|
8418
|
+
}
|
|
8419
|
+
});
|
|
8420
|
+
return {
|
|
8421
|
+
async dispose() {
|
|
8422
|
+
unsubscribe();
|
|
8423
|
+
process.removeListener("exit", exitCleanup);
|
|
8424
|
+
await store.disposeAll();
|
|
8425
|
+
}
|
|
8426
|
+
};
|
|
8427
|
+
}
|
|
8428
|
+
|
|
8269
8429
|
// ../server/src/log-server.ts
|
|
8270
8430
|
var HOSTNAME = "127.0.0.1";
|
|
8271
8431
|
function startLogServer(opts) {
|
|
8272
8432
|
const { sessions } = opts;
|
|
8273
8433
|
const app = new Hono2();
|
|
8274
8434
|
app.use("*", hostGuardMiddleware);
|
|
8435
|
+
app.use("*", corsMiddleware);
|
|
8275
8436
|
app.use("*", cspMiddleware);
|
|
8276
8437
|
app.get("/health", (c) => c.json({ status: "ok", version: opts.version }));
|
|
8277
8438
|
registerLogRoutes(app, sessions);
|
|
@@ -8279,6 +8440,7 @@ function startLogServer(opts) {
|
|
|
8279
8440
|
registerSearchRoutes(app, sessions);
|
|
8280
8441
|
registerStateRoutes(app, sessions);
|
|
8281
8442
|
registerSessionRoutes(app, sessions);
|
|
8443
|
+
registerUploadRoutes(app, sessions);
|
|
8282
8444
|
if (opts.uiDistDir) registerStaticUi(app, opts.uiDistDir);
|
|
8283
8445
|
return new Promise((resolve3, reject) => {
|
|
8284
8446
|
const server = serve(
|
|
@@ -8422,7 +8584,7 @@ function classifyDirection(raw2) {
|
|
|
8422
8584
|
var __filename2 = fileURLToPath(import.meta.url);
|
|
8423
8585
|
var __dirname2 = dirname3(__filename2);
|
|
8424
8586
|
function loadVersion() {
|
|
8425
|
-
const candidates = [
|
|
8587
|
+
const candidates = [join7(__dirname2, "..", "package.json"), join7(__dirname2, "package.json")];
|
|
8426
8588
|
for (const p of candidates) {
|
|
8427
8589
|
try {
|
|
8428
8590
|
return JSON.parse(readFileSync(p, "utf8")).version ?? "0.0.0";
|
|
@@ -8450,7 +8612,7 @@ function locateUiDist() {
|
|
|
8450
8612
|
);
|
|
8451
8613
|
for (const c of candidates) {
|
|
8452
8614
|
try {
|
|
8453
|
-
if (existsSync2(
|
|
8615
|
+
if (existsSync2(join7(c, "index.html"))) return c;
|
|
8454
8616
|
} catch {
|
|
8455
8617
|
}
|
|
8456
8618
|
}
|