agent-inspect 3.2.0 → 3.4.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/CHANGELOG.md +12 -0
- package/README.md +1 -1
- package/docs/SCREENSHOTS.md +6 -1
- package/package.json +2 -2
- package/packages/cli/dist/index.cjs +435 -70
- package/packages/cli/dist/index.cjs.map +1 -1
- package/packages/cli/dist/index.mjs +436 -71
- package/packages/cli/dist/index.mjs.map +1 -1
- package/packages/core/dist/checks.cjs +105 -0
- package/packages/core/dist/checks.cjs.map +1 -1
- package/packages/core/dist/checks.d.cts +26 -1
- package/packages/core/dist/checks.d.ts +26 -1
- package/packages/core/dist/checks.mjs +103 -1
- package/packages/core/dist/checks.mjs.map +1 -1
|
@@ -25,7 +25,7 @@ var process3__default = /*#__PURE__*/_interopDefault(process3);
|
|
|
25
25
|
var tty__default = /*#__PURE__*/_interopDefault(tty);
|
|
26
26
|
|
|
27
27
|
// package.json
|
|
28
|
-
var version = "3.
|
|
28
|
+
var version = "3.4.0";
|
|
29
29
|
|
|
30
30
|
// packages/core/src/correlation-metadata.ts
|
|
31
31
|
var TRACE_CORRELATION_KEYS = [
|
|
@@ -3071,12 +3071,12 @@ function buildCriticalPath(runs, handoffs) {
|
|
|
3071
3071
|
handoffs.filter((edge) => edge.confidence === "explicit").map((edge) => edge.from)
|
|
3072
3072
|
);
|
|
3073
3073
|
const ordered = [...runs].sort(compareRuns);
|
|
3074
|
-
const
|
|
3074
|
+
const path19 = [];
|
|
3075
3075
|
const visited = /* @__PURE__ */ new Set();
|
|
3076
3076
|
const pushRun = (run, confidence, source) => {
|
|
3077
3077
|
if (visited.has(run.runId)) return;
|
|
3078
3078
|
visited.add(run.runId);
|
|
3079
|
-
|
|
3079
|
+
path19.push({
|
|
3080
3080
|
runId: run.runId,
|
|
3081
3081
|
name: run.name,
|
|
3082
3082
|
startedAt: run.startedAt,
|
|
@@ -3101,7 +3101,7 @@ function buildCriticalPath(runs, handoffs) {
|
|
|
3101
3101
|
const confidence = explicitTargets.has(run.runId) || explicitSources.has(run.runId) ? "explicit" : "correlated";
|
|
3102
3102
|
pushRun(run, confidence, confidence === "explicit" ? "manual" : "inferred");
|
|
3103
3103
|
}
|
|
3104
|
-
return
|
|
3104
|
+
return path19;
|
|
3105
3105
|
}
|
|
3106
3106
|
function metaRunIdMatches(run, token, runById) {
|
|
3107
3107
|
const meta = extractSessionWorkflowMetadata(run.metadata);
|
|
@@ -3214,6 +3214,62 @@ async function isAgentInspectTrace(filePath) {
|
|
|
3214
3214
|
}
|
|
3215
3215
|
}
|
|
3216
3216
|
|
|
3217
|
+
// packages/cli/src/trace-dir-scale.ts
|
|
3218
|
+
var TRACE_COUNT_WARN = 1e3;
|
|
3219
|
+
var TRACE_COUNT_SEVERE = 1e4;
|
|
3220
|
+
var LARGE_TRACE_FILE_BYTES = 50 * 1024 * 1024;
|
|
3221
|
+
function buildScaleWarnings(traceCount, largeFileCount) {
|
|
3222
|
+
const warnings = [];
|
|
3223
|
+
if (traceCount >= TRACE_COUNT_SEVERE) {
|
|
3224
|
+
warnings.push(
|
|
3225
|
+
`trace directory has ${traceCount} runs (>= ${TRACE_COUNT_SEVERE}); archive or split traces \u2014 see docs/SCALE-LIMITS.md`
|
|
3226
|
+
);
|
|
3227
|
+
} else if (traceCount >= TRACE_COUNT_WARN) {
|
|
3228
|
+
warnings.push(
|
|
3229
|
+
`trace directory has ${traceCount} runs (>= ${TRACE_COUNT_WARN}); list/search/stats may be slow \u2014 consider agent-inspect index build`
|
|
3230
|
+
);
|
|
3231
|
+
}
|
|
3232
|
+
if (largeFileCount > 0) {
|
|
3233
|
+
warnings.push(
|
|
3234
|
+
`${largeFileCount} trace file(s) exceed ${Math.round(LARGE_TRACE_FILE_BYTES / (1024 * 1024))}MB; open/check/report may be slow`
|
|
3235
|
+
);
|
|
3236
|
+
}
|
|
3237
|
+
return warnings;
|
|
3238
|
+
}
|
|
3239
|
+
async function assessTraceDirectoryScale(td, options = {}) {
|
|
3240
|
+
const files = await td.list();
|
|
3241
|
+
const sample = options.sampleLargeFiles ?? 25;
|
|
3242
|
+
let largeFileCount = 0;
|
|
3243
|
+
if (files.length > 0 && files.length <= sample * 4) {
|
|
3244
|
+
for (const file of files) {
|
|
3245
|
+
try {
|
|
3246
|
+
const stats = await td.getFileStats(file);
|
|
3247
|
+
if (stats.size >= LARGE_TRACE_FILE_BYTES) largeFileCount += 1;
|
|
3248
|
+
} catch {
|
|
3249
|
+
}
|
|
3250
|
+
}
|
|
3251
|
+
} else if (files.length > sample) {
|
|
3252
|
+
for (const file of files.slice(0, sample)) {
|
|
3253
|
+
try {
|
|
3254
|
+
const stats = await td.getFileStats(file);
|
|
3255
|
+
if (stats.size >= LARGE_TRACE_FILE_BYTES) largeFileCount += 1;
|
|
3256
|
+
} catch {
|
|
3257
|
+
}
|
|
3258
|
+
}
|
|
3259
|
+
if (largeFileCount > 0) {
|
|
3260
|
+
largeFileCount = Math.max(largeFileCount, 1);
|
|
3261
|
+
}
|
|
3262
|
+
}
|
|
3263
|
+
const warnings = buildScaleWarnings(files.length, largeFileCount);
|
|
3264
|
+
return { traceCount: files.length, largeFileCount, warnings };
|
|
3265
|
+
}
|
|
3266
|
+
function emitScaleWarnings(assessment, options = {}) {
|
|
3267
|
+
if (options.json || assessment.warnings.length === 0) return;
|
|
3268
|
+
for (const warning of assessment.warnings) {
|
|
3269
|
+
console.error(`[AgentInspect] warning: ${warning}`);
|
|
3270
|
+
}
|
|
3271
|
+
}
|
|
3272
|
+
|
|
3217
3273
|
// packages/cli/src/list.ts
|
|
3218
3274
|
function parseLimit(raw) {
|
|
3219
3275
|
const fallback = 20;
|
|
@@ -3248,6 +3304,8 @@ async function list(options = {}) {
|
|
|
3248
3304
|
parseDuration(options.since.trim());
|
|
3249
3305
|
}
|
|
3250
3306
|
const files = await td.list();
|
|
3307
|
+
const scale = await assessTraceDirectoryScale(td);
|
|
3308
|
+
emitScaleWarnings(scale, { json: options.json });
|
|
3251
3309
|
if (files.length === 0) {
|
|
3252
3310
|
if (options.json) {
|
|
3253
3311
|
console.log("[]");
|
|
@@ -8344,13 +8402,13 @@ function pairSteps(left, right) {
|
|
|
8344
8402
|
return pairs;
|
|
8345
8403
|
}
|
|
8346
8404
|
function compareLeafSteps(L, R, segments, opts, out) {
|
|
8347
|
-
const
|
|
8405
|
+
const path19 = buildPath(segments);
|
|
8348
8406
|
if (L.name !== R.name) {
|
|
8349
8407
|
out.push({
|
|
8350
8408
|
kind: "structure",
|
|
8351
8409
|
severity: "warning",
|
|
8352
8410
|
message: "Step name differs",
|
|
8353
|
-
path:
|
|
8411
|
+
path: path19,
|
|
8354
8412
|
left: L.name,
|
|
8355
8413
|
right: R.name
|
|
8356
8414
|
});
|
|
@@ -8360,7 +8418,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
|
|
|
8360
8418
|
kind: "step-type",
|
|
8361
8419
|
severity: "warning",
|
|
8362
8420
|
message: "Step type differs",
|
|
8363
|
-
path:
|
|
8421
|
+
path: path19,
|
|
8364
8422
|
left: L.type,
|
|
8365
8423
|
right: R.type
|
|
8366
8424
|
});
|
|
@@ -8370,7 +8428,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
|
|
|
8370
8428
|
kind: "step-status",
|
|
8371
8429
|
severity: "warning",
|
|
8372
8430
|
message: "Step status differs",
|
|
8373
|
-
path:
|
|
8431
|
+
path: path19,
|
|
8374
8432
|
left: L.status,
|
|
8375
8433
|
right: R.status
|
|
8376
8434
|
});
|
|
@@ -8382,7 +8440,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
|
|
|
8382
8440
|
kind: "error",
|
|
8383
8441
|
severity: "error",
|
|
8384
8442
|
message: "Step error message differs",
|
|
8385
|
-
path:
|
|
8443
|
+
path: path19,
|
|
8386
8444
|
left: le || void 0,
|
|
8387
8445
|
right: re || void 0
|
|
8388
8446
|
});
|
|
@@ -8400,20 +8458,20 @@ function compareLeafSteps(L, R, segments, opts, out) {
|
|
|
8400
8458
|
kind: "duration",
|
|
8401
8459
|
severity: "info",
|
|
8402
8460
|
message: "Step duration differs",
|
|
8403
|
-
path:
|
|
8461
|
+
path: path19,
|
|
8404
8462
|
left: ld,
|
|
8405
8463
|
right: rd
|
|
8406
8464
|
});
|
|
8407
8465
|
}
|
|
8408
8466
|
}
|
|
8409
8467
|
const lm = stableJson(L.metadata ?? {});
|
|
8410
|
-
const
|
|
8411
|
-
if (lm !==
|
|
8468
|
+
const rm2 = stableJson(R.metadata ?? {});
|
|
8469
|
+
if (lm !== rm2) {
|
|
8412
8470
|
out.push({
|
|
8413
8471
|
kind: "metadata",
|
|
8414
8472
|
severity: "info",
|
|
8415
8473
|
message: "Step metadata differs",
|
|
8416
|
-
path:
|
|
8474
|
+
path: path19,
|
|
8417
8475
|
left: L.metadata,
|
|
8418
8476
|
right: R.metadata
|
|
8419
8477
|
});
|
|
@@ -8425,7 +8483,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
|
|
|
8425
8483
|
kind: "output",
|
|
8426
8484
|
severity: "info",
|
|
8427
8485
|
message: "Output preview differs",
|
|
8428
|
-
path:
|
|
8486
|
+
path: path19,
|
|
8429
8487
|
left: L.outputPreview,
|
|
8430
8488
|
right: R.outputPreview
|
|
8431
8489
|
});
|
|
@@ -8585,11 +8643,11 @@ function diffRuns(left, right, options) {
|
|
|
8585
8643
|
}
|
|
8586
8644
|
|
|
8587
8645
|
// packages/core/src/diff/renderer.ts
|
|
8588
|
-
function formatPath(
|
|
8589
|
-
if (
|
|
8646
|
+
function formatPath(path19) {
|
|
8647
|
+
if (path19 === void 0 || path19.path.length === 0) {
|
|
8590
8648
|
return "(run)";
|
|
8591
8649
|
}
|
|
8592
|
-
return
|
|
8650
|
+
return path19.path.map((s) => s.name).join(" > ");
|
|
8593
8651
|
}
|
|
8594
8652
|
function formatValue(v, verbose) {
|
|
8595
8653
|
if (v === void 0) return "(undefined)";
|
|
@@ -8815,6 +8873,8 @@ async function statsCommand(options = {}) {
|
|
|
8815
8873
|
parseDuration(options.since.trim());
|
|
8816
8874
|
}
|
|
8817
8875
|
const files = await td.list();
|
|
8876
|
+
const scale = await assessTraceDirectoryScale(td);
|
|
8877
|
+
emitScaleWarnings(scale, { json: options.json });
|
|
8818
8878
|
if (files.length === 0) {
|
|
8819
8879
|
if (options.json) {
|
|
8820
8880
|
console.log(
|
|
@@ -8885,6 +8945,8 @@ async function searchCommand(options = {}) {
|
|
|
8885
8945
|
parseDurationFilter(options.duration);
|
|
8886
8946
|
}
|
|
8887
8947
|
const files = await td.list();
|
|
8948
|
+
const scale = await assessTraceDirectoryScale(td);
|
|
8949
|
+
emitScaleWarnings(scale, { json: options.json });
|
|
8888
8950
|
let metas = await loadTraceMetadataList(
|
|
8889
8951
|
traceDir,
|
|
8890
8952
|
files,
|
|
@@ -9467,17 +9529,17 @@ function applyRule(rule, value, replacement) {
|
|
|
9467
9529
|
}
|
|
9468
9530
|
return value;
|
|
9469
9531
|
}
|
|
9470
|
-
function childPath(
|
|
9532
|
+
function childPath(path19, key) {
|
|
9471
9533
|
if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key)) {
|
|
9472
|
-
return
|
|
9534
|
+
return path19 ? `${path19}.${key}` : key;
|
|
9473
9535
|
}
|
|
9474
|
-
return `${
|
|
9536
|
+
return `${path19 || "$"}[${JSON.stringify(key)}]`;
|
|
9475
9537
|
}
|
|
9476
|
-
function indexPath(
|
|
9477
|
-
return `${
|
|
9538
|
+
function indexPath(path19, index) {
|
|
9539
|
+
return `${path19 || "$"}[${index}]`;
|
|
9478
9540
|
}
|
|
9479
|
-
function makeFinding(
|
|
9480
|
-
return preview === void 0 ? { path:
|
|
9541
|
+
function makeFinding(path19, detector, action, matchKind, severity = "warning", preview) {
|
|
9542
|
+
return preview === void 0 ? { path: path19, detector, action, severity, matchKind } : { path: path19, detector, action, severity, matchKind, preview };
|
|
9481
9543
|
}
|
|
9482
9544
|
function createRedactionProfile(profile = "local") {
|
|
9483
9545
|
switch (profile) {
|
|
@@ -9546,11 +9608,11 @@ var Redactor2 = class {
|
|
|
9546
9608
|
#recordFinding(state, finding) {
|
|
9547
9609
|
if (this.#collectFindings) state.findings.push(finding);
|
|
9548
9610
|
}
|
|
9549
|
-
#redactValue(value, key,
|
|
9611
|
+
#redactValue(value, key, path19, depth, state) {
|
|
9550
9612
|
if (depth > this.#maxDepth) {
|
|
9551
9613
|
this.#recordFinding(
|
|
9552
9614
|
state,
|
|
9553
|
-
makeFinding(
|
|
9615
|
+
makeFinding(path19, "structure.maxDepth", "truncate", "value", "warning")
|
|
9554
9616
|
);
|
|
9555
9617
|
return "[Truncated]";
|
|
9556
9618
|
}
|
|
@@ -9559,19 +9621,19 @@ var Redactor2 = class {
|
|
|
9559
9621
|
if (rule) {
|
|
9560
9622
|
this.#recordFinding(
|
|
9561
9623
|
state,
|
|
9562
|
-
makeFinding(
|
|
9624
|
+
makeFinding(path19, `key.${rule.key}`, actionForRule(rule), "key", "warning")
|
|
9563
9625
|
);
|
|
9564
9626
|
return applyRule(rule, value, this.#replacement);
|
|
9565
9627
|
}
|
|
9566
9628
|
}
|
|
9567
9629
|
for (const detector of this.#detectors) {
|
|
9568
|
-
const detections = detector.detect({ path:
|
|
9630
|
+
const detections = detector.detect({ path: path19, key, value });
|
|
9569
9631
|
for (const detection of detections) {
|
|
9570
9632
|
const action = detection.action ?? "replace";
|
|
9571
9633
|
this.#recordFinding(
|
|
9572
9634
|
state,
|
|
9573
9635
|
makeFinding(
|
|
9574
|
-
|
|
9636
|
+
path19,
|
|
9575
9637
|
detector.id,
|
|
9576
9638
|
action,
|
|
9577
9639
|
detection.matchKind ?? detector.matchKind ?? "custom",
|
|
@@ -9589,7 +9651,7 @@ var Redactor2 = class {
|
|
|
9589
9651
|
const out = [];
|
|
9590
9652
|
state.seen.set(value, out);
|
|
9591
9653
|
value.forEach((item, index) => {
|
|
9592
|
-
out[index] = this.#redactValue(item, void 0, indexPath(
|
|
9654
|
+
out[index] = this.#redactValue(item, void 0, indexPath(path19, index), depth + 1, state);
|
|
9593
9655
|
});
|
|
9594
9656
|
return out;
|
|
9595
9657
|
}
|
|
@@ -9601,7 +9663,7 @@ var Redactor2 = class {
|
|
|
9601
9663
|
out[entryKey] = this.#redactValue(
|
|
9602
9664
|
entryValue,
|
|
9603
9665
|
entryKey,
|
|
9604
|
-
childPath(
|
|
9666
|
+
childPath(path19 === "$" ? "" : path19, entryKey),
|
|
9605
9667
|
depth + 1,
|
|
9606
9668
|
state
|
|
9607
9669
|
);
|
|
@@ -10473,7 +10535,7 @@ function stripPrefix(name, prefixes) {
|
|
|
10473
10535
|
}
|
|
10474
10536
|
return name;
|
|
10475
10537
|
}
|
|
10476
|
-
function eventEvidence(event,
|
|
10538
|
+
function eventEvidence(event, path19) {
|
|
10477
10539
|
return {
|
|
10478
10540
|
runId: event.runId,
|
|
10479
10541
|
eventId: event.eventId,
|
|
@@ -10483,7 +10545,7 @@ function eventEvidence(event, path18) {
|
|
|
10483
10545
|
kind: event.kind,
|
|
10484
10546
|
name: event.name,
|
|
10485
10547
|
status: event.status,
|
|
10486
|
-
...
|
|
10548
|
+
...path19 ? { path: path19 } : {}
|
|
10487
10549
|
};
|
|
10488
10550
|
}
|
|
10489
10551
|
function runEvidence(run) {
|
|
@@ -10546,9 +10608,9 @@ function eventEndMs(event) {
|
|
|
10546
10608
|
function normalizedKey(value) {
|
|
10547
10609
|
return value.toLowerCase().replace(/[^a-z0-9_]/g, "");
|
|
10548
10610
|
}
|
|
10549
|
-
function lastPathSegment(
|
|
10550
|
-
const parts =
|
|
10551
|
-
return parts[parts.length - 1] ??
|
|
10611
|
+
function lastPathSegment(path19) {
|
|
10612
|
+
const parts = path19.split(".");
|
|
10613
|
+
return parts[parts.length - 1] ?? path19;
|
|
10552
10614
|
}
|
|
10553
10615
|
function valueType(value) {
|
|
10554
10616
|
if (Array.isArray(value)) return "array";
|
|
@@ -10562,12 +10624,12 @@ function serializedByteLength(value) {
|
|
|
10562
10624
|
return void 0;
|
|
10563
10625
|
}
|
|
10564
10626
|
}
|
|
10565
|
-
function pushValueEntries(entries, event, value,
|
|
10566
|
-
entries.push({ event, path:
|
|
10627
|
+
function pushValueEntries(entries, event, value, path19, key, depth = 0) {
|
|
10628
|
+
entries.push({ event, path: path19, key, value });
|
|
10567
10629
|
if (depth >= 8) return;
|
|
10568
10630
|
if (Array.isArray(value)) {
|
|
10569
10631
|
for (const [index, item] of value.entries()) {
|
|
10570
|
-
pushValueEntries(entries, event, item, `${
|
|
10632
|
+
pushValueEntries(entries, event, item, `${path19}.${index}`, String(index), depth + 1);
|
|
10571
10633
|
}
|
|
10572
10634
|
return;
|
|
10573
10635
|
}
|
|
@@ -10577,7 +10639,7 @@ function pushValueEntries(entries, event, value, path18, key, depth = 0) {
|
|
|
10577
10639
|
entries,
|
|
10578
10640
|
event,
|
|
10579
10641
|
value[nestedKey],
|
|
10580
|
-
`${
|
|
10642
|
+
`${path19}.${nestedKey}`,
|
|
10581
10643
|
nestedKey,
|
|
10582
10644
|
depth + 1
|
|
10583
10645
|
);
|
|
@@ -10658,9 +10720,9 @@ function eventDurationMs(event) {
|
|
|
10658
10720
|
}
|
|
10659
10721
|
function treeShape(nodes) {
|
|
10660
10722
|
const lines = [];
|
|
10661
|
-
const visit = (node,
|
|
10662
|
-
lines.push(`${
|
|
10663
|
-
node.children.forEach((child, index) => visit(child, `${
|
|
10723
|
+
const visit = (node, path19) => {
|
|
10724
|
+
lines.push(`${path19}:${node.event.kind}:${node.event.name}:${node.event.status ?? "unknown"}`);
|
|
10725
|
+
node.children.forEach((child, index) => visit(child, `${path19}.${index}`));
|
|
10664
10726
|
};
|
|
10665
10727
|
nodes.forEach((node, index) => visit(node, String(index)));
|
|
10666
10728
|
return lines;
|
|
@@ -10709,9 +10771,9 @@ function retrievalShape(context) {
|
|
|
10709
10771
|
function guardrailShape(context) {
|
|
10710
10772
|
return guardrailEvents(context).map((event) => signalName(event, ["guardrailName", "guardrail", "guardrailId"], ["guardrail:"])).sort((a, b) => a.localeCompare(b));
|
|
10711
10773
|
}
|
|
10712
|
-
function firstEvidenceForKind(context, kind,
|
|
10774
|
+
function firstEvidenceForKind(context, kind, path19) {
|
|
10713
10775
|
const event = context.events.find((candidate) => candidate.kind === kind);
|
|
10714
|
-
return event ? [eventEvidence(event,
|
|
10776
|
+
return event ? [eventEvidence(event, path19)] : runEvidence(context.selectedRun);
|
|
10715
10777
|
}
|
|
10716
10778
|
function baselineDiffFinding(message, evidence, expected, actual) {
|
|
10717
10779
|
return failFinding("baseline.regression", message, evidence, expected, actual);
|
|
@@ -10775,6 +10837,108 @@ function createRunDurationRule(options) {
|
|
|
10775
10837
|
}
|
|
10776
10838
|
};
|
|
10777
10839
|
}
|
|
10840
|
+
function createMaxStepDurationRule(options) {
|
|
10841
|
+
return {
|
|
10842
|
+
id: "run.maxStepDuration",
|
|
10843
|
+
category: "run",
|
|
10844
|
+
defaultSeverity: "error",
|
|
10845
|
+
evaluate(context) {
|
|
10846
|
+
const over = context.events.filter((event) => {
|
|
10847
|
+
const duration = eventDurationMs(event);
|
|
10848
|
+
return duration !== void 0 && duration > options.maxDurationMs;
|
|
10849
|
+
});
|
|
10850
|
+
if (over.length === 0) return [];
|
|
10851
|
+
return [
|
|
10852
|
+
failFinding(
|
|
10853
|
+
"run.maxStepDuration",
|
|
10854
|
+
`${over.length} step(s) exceeded max duration ${options.maxDurationMs}ms.`,
|
|
10855
|
+
over.map((event) => eventEvidence(event, "durationMs")),
|
|
10856
|
+
{ maxDurationMs: options.maxDurationMs },
|
|
10857
|
+
over.map((event) => ({
|
|
10858
|
+
eventId: event.eventId,
|
|
10859
|
+
name: event.name,
|
|
10860
|
+
durationMs: eventDurationMs(event)
|
|
10861
|
+
}))
|
|
10862
|
+
)
|
|
10863
|
+
];
|
|
10864
|
+
}
|
|
10865
|
+
};
|
|
10866
|
+
}
|
|
10867
|
+
function createStallDetectionRule(options = {}) {
|
|
10868
|
+
const requireEndedAt = options.requireEndedAt === true;
|
|
10869
|
+
return {
|
|
10870
|
+
id: "run.stall",
|
|
10871
|
+
category: "run",
|
|
10872
|
+
defaultSeverity: "warning",
|
|
10873
|
+
evaluate(context) {
|
|
10874
|
+
const findings = [];
|
|
10875
|
+
const running = context.events.filter((event) => event.status === "running");
|
|
10876
|
+
if (running.length > 0) {
|
|
10877
|
+
findings.push(
|
|
10878
|
+
failFinding(
|
|
10879
|
+
"run.stall",
|
|
10880
|
+
`Found ${running.length} event(s) still running (possible stall).`,
|
|
10881
|
+
running.map((event) => eventEvidence(event, "status")),
|
|
10882
|
+
"no running events",
|
|
10883
|
+
running.length
|
|
10884
|
+
)
|
|
10885
|
+
);
|
|
10886
|
+
}
|
|
10887
|
+
if (requireEndedAt) {
|
|
10888
|
+
const incomplete = context.events.filter(
|
|
10889
|
+
(event) => event.startedAt !== void 0 && event.endedAt === void 0 && event.status !== "running"
|
|
10890
|
+
);
|
|
10891
|
+
if (incomplete.length > 0) {
|
|
10892
|
+
findings.push(
|
|
10893
|
+
failFinding(
|
|
10894
|
+
"run.stall",
|
|
10895
|
+
`Found ${incomplete.length} started event(s) without endedAt.`,
|
|
10896
|
+
incomplete.map((event) => eventEvidence(event, "endedAt")),
|
|
10897
|
+
"endedAt for started events",
|
|
10898
|
+
incomplete.length
|
|
10899
|
+
)
|
|
10900
|
+
);
|
|
10901
|
+
}
|
|
10902
|
+
}
|
|
10903
|
+
return findings;
|
|
10904
|
+
}
|
|
10905
|
+
};
|
|
10906
|
+
}
|
|
10907
|
+
function createRequireCompletedRule() {
|
|
10908
|
+
return {
|
|
10909
|
+
id: "run.requireCompleted",
|
|
10910
|
+
category: "run",
|
|
10911
|
+
defaultSeverity: "error",
|
|
10912
|
+
evaluate(context) {
|
|
10913
|
+
const findings = [];
|
|
10914
|
+
const runStatus = context.selectedRun?.status;
|
|
10915
|
+
if (runStatus === "running") {
|
|
10916
|
+
findings.push(
|
|
10917
|
+
failFinding(
|
|
10918
|
+
"run.requireCompleted",
|
|
10919
|
+
"Run is still running.",
|
|
10920
|
+
runEvidence(context.selectedRun),
|
|
10921
|
+
"completed run",
|
|
10922
|
+
runStatus
|
|
10923
|
+
)
|
|
10924
|
+
);
|
|
10925
|
+
}
|
|
10926
|
+
const running = context.events.filter((event) => event.status === "running");
|
|
10927
|
+
if (running.length > 0) {
|
|
10928
|
+
findings.push(
|
|
10929
|
+
failFinding(
|
|
10930
|
+
"run.requireCompleted",
|
|
10931
|
+
`Run has ${running.length} incomplete running event(s).`,
|
|
10932
|
+
running.map((event) => eventEvidence(event, "status")),
|
|
10933
|
+
"no running events",
|
|
10934
|
+
running.length
|
|
10935
|
+
)
|
|
10936
|
+
);
|
|
10937
|
+
}
|
|
10938
|
+
return findings;
|
|
10939
|
+
}
|
|
10940
|
+
};
|
|
10941
|
+
}
|
|
10778
10942
|
function createRunDepthRule(options) {
|
|
10779
10943
|
return {
|
|
10780
10944
|
id: "run.depth",
|
|
@@ -10959,13 +11123,13 @@ function createStructureCycleRule() {
|
|
|
10959
11123
|
const seenCycles = /* @__PURE__ */ new Set();
|
|
10960
11124
|
const findings = [];
|
|
10961
11125
|
for (const event of [...context.events].sort((a, b) => a.eventId.localeCompare(b.eventId))) {
|
|
10962
|
-
const
|
|
11126
|
+
const path19 = [];
|
|
10963
11127
|
const seenAt = /* @__PURE__ */ new Map();
|
|
10964
11128
|
let current = event;
|
|
10965
11129
|
while (current) {
|
|
10966
11130
|
const existing = seenAt.get(current.eventId);
|
|
10967
11131
|
if (existing !== void 0) {
|
|
10968
|
-
const cycle =
|
|
11132
|
+
const cycle = path19.slice(existing);
|
|
10969
11133
|
const key = cycle.map((item) => item.eventId).sort().join("\0");
|
|
10970
11134
|
if (!seenCycles.has(key)) {
|
|
10971
11135
|
seenCycles.add(key);
|
|
@@ -10981,8 +11145,8 @@ function createStructureCycleRule() {
|
|
|
10981
11145
|
}
|
|
10982
11146
|
break;
|
|
10983
11147
|
}
|
|
10984
|
-
seenAt.set(current.eventId,
|
|
10985
|
-
|
|
11148
|
+
seenAt.set(current.eventId, path19.length);
|
|
11149
|
+
path19.push(current);
|
|
10986
11150
|
current = current.parentId ? byId.get(current.parentId) : void 0;
|
|
10987
11151
|
}
|
|
10988
11152
|
}
|
|
@@ -11779,23 +11943,23 @@ function evaluatePromptInjection(text, options = {}) {
|
|
|
11779
11943
|
}
|
|
11780
11944
|
return fail(ruleId, `Matched ${evidence.length} injection pattern(s).`, evidence, "warning");
|
|
11781
11945
|
}
|
|
11782
|
-
function validateSchemaField(value, field,
|
|
11946
|
+
function validateSchemaField(value, field, path19, evidence) {
|
|
11783
11947
|
const ruleId = "guardrail.structured-output";
|
|
11784
11948
|
if (field.type) {
|
|
11785
11949
|
const actual = value === null ? "null" : Array.isArray(value) ? "array" : typeof value;
|
|
11786
11950
|
if (actual !== field.type) {
|
|
11787
|
-
evidence.push({ ruleId, path:
|
|
11951
|
+
evidence.push({ ruleId, path: path19, preview: `expected ${field.type}, got ${actual}` });
|
|
11788
11952
|
return;
|
|
11789
11953
|
}
|
|
11790
11954
|
}
|
|
11791
11955
|
if (field.enum && !field.enum.some((item) => Object.is(item, value))) {
|
|
11792
|
-
evidence.push({ ruleId, path:
|
|
11956
|
+
evidence.push({ ruleId, path: path19, preview: "value not in enum" });
|
|
11793
11957
|
}
|
|
11794
11958
|
if (field.type === "object" && field.required && value && typeof value === "object" && !Array.isArray(value)) {
|
|
11795
11959
|
const record = value;
|
|
11796
11960
|
for (const key of field.required) {
|
|
11797
11961
|
if (!(key in record)) {
|
|
11798
|
-
evidence.push({ ruleId, path: `${
|
|
11962
|
+
evidence.push({ ruleId, path: `${path19}.${key}`, preview: "missing required key" });
|
|
11799
11963
|
}
|
|
11800
11964
|
}
|
|
11801
11965
|
}
|
|
@@ -12156,6 +12320,17 @@ function buildRules(config, options) {
|
|
|
12156
12320
|
const safety = checks2.safety ?? {};
|
|
12157
12321
|
const maxDurationMs = parseNumber(options.maxDurationMs, "--max-duration-ms") ?? run.maxDurationMs;
|
|
12158
12322
|
const maxTotalTokens = parseNumber(options.maxTotalTokens, "--max-total-tokens") ?? llm.maxTotalTokens;
|
|
12323
|
+
let maxStepDurationMs;
|
|
12324
|
+
if (options.maxStepDuration !== void 0) {
|
|
12325
|
+
try {
|
|
12326
|
+
maxStepDurationMs = parseDuration(options.maxStepDuration.trim());
|
|
12327
|
+
} catch (error) {
|
|
12328
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
12329
|
+
diagnostics.push(
|
|
12330
|
+
diagnostic2("AI_CHECK_INVALID_ARGUMENTS", `--max-step-duration: ${message}`)
|
|
12331
|
+
);
|
|
12332
|
+
}
|
|
12333
|
+
}
|
|
12159
12334
|
const rules = [
|
|
12160
12335
|
createRunStatusRule(run),
|
|
12161
12336
|
createStructureOrphanRule(),
|
|
@@ -12166,6 +12341,15 @@ function buildRules(config, options) {
|
|
|
12166
12341
|
if (maxDurationMs !== void 0) {
|
|
12167
12342
|
rules.push(createRunDurationRule({ maxDurationMs }));
|
|
12168
12343
|
}
|
|
12344
|
+
if (maxStepDurationMs !== void 0) {
|
|
12345
|
+
rules.push(createMaxStepDurationRule({ maxDurationMs: maxStepDurationMs }));
|
|
12346
|
+
}
|
|
12347
|
+
if (options.requireCompleted) {
|
|
12348
|
+
rules.push(createRequireCompletedRule());
|
|
12349
|
+
}
|
|
12350
|
+
if (options.detectStalls) {
|
|
12351
|
+
rules.push(createStallDetectionRule({ requireEndedAt: true }));
|
|
12352
|
+
}
|
|
12169
12353
|
if (run.maxDepth !== void 0) {
|
|
12170
12354
|
rules.push(createRunDepthRule({ maxDepth: run.maxDepth }));
|
|
12171
12355
|
}
|
|
@@ -12260,10 +12444,10 @@ function printHuman(result) {
|
|
|
12260
12444
|
console.log(`- ${diagnostic4.code}: ${diagnostic4.message}`);
|
|
12261
12445
|
}
|
|
12262
12446
|
for (const finding of result.findings) {
|
|
12263
|
-
const
|
|
12447
|
+
const path19 = finding.evidence[0]?.path;
|
|
12264
12448
|
const run = finding.evidence[0]?.runId;
|
|
12265
12449
|
const runPrefix = run ? `[${run}] ` : "";
|
|
12266
|
-
console.log(`- ${runPrefix}${finding.ruleId}: ${finding.message}${
|
|
12450
|
+
console.log(`- ${runPrefix}${finding.ruleId}: ${finding.message}${path19 ? ` (${path19})` : ""}`);
|
|
12267
12451
|
}
|
|
12268
12452
|
}
|
|
12269
12453
|
function readErrorResult(error) {
|
|
@@ -12801,10 +12985,10 @@ async function evalRun(input3, options = {}) {
|
|
|
12801
12985
|
diagnostics: []
|
|
12802
12986
|
};
|
|
12803
12987
|
}
|
|
12804
|
-
function evidenceForRun(run,
|
|
12805
|
-
return [{ runId: run.runId, ...
|
|
12988
|
+
function evidenceForRun(run, path19) {
|
|
12989
|
+
return [{ runId: run.runId, ...path19 !== void 0 ? { path: path19 } : {} }];
|
|
12806
12990
|
}
|
|
12807
|
-
function evidenceForEvent(event,
|
|
12991
|
+
function evidenceForEvent(event, path19) {
|
|
12808
12992
|
return [
|
|
12809
12993
|
{
|
|
12810
12994
|
runId: event.runId,
|
|
@@ -12812,7 +12996,7 @@ function evidenceForEvent(event, path18) {
|
|
|
12812
12996
|
...event.parentId !== void 0 ? { parentId: event.parentId } : {},
|
|
12813
12997
|
kind: event.kind,
|
|
12814
12998
|
name: event.name,
|
|
12815
|
-
...
|
|
12999
|
+
...path19 !== void 0 ? { path: path19 } : {}
|
|
12816
13000
|
}
|
|
12817
13001
|
];
|
|
12818
13002
|
}
|
|
@@ -12970,9 +13154,9 @@ function collectTextFields(nodes, keys, preferredKinds = []) {
|
|
|
12970
13154
|
function tokenize(text) {
|
|
12971
13155
|
return [...text.toLowerCase().matchAll(/[a-z0-9][a-z0-9'-]{2,}/g)].map((match) => match[0].replace(/^['-]+|['-]+$/g, "")).filter((token) => token.length > 2 && !STOP_WORDS.has(token));
|
|
12972
13156
|
}
|
|
12973
|
-
function firstEvidence(fields, run,
|
|
13157
|
+
function firstEvidence(fields, run, path19) {
|
|
12974
13158
|
const first = fields[0];
|
|
12975
|
-
return first === void 0 ? evidenceForRun(run,
|
|
13159
|
+
return first === void 0 ? evidenceForRun(run, path19) : evidenceForEvent(first.node.event, first.path);
|
|
12976
13160
|
}
|
|
12977
13161
|
function collectSourceIds(nodes, keys) {
|
|
12978
13162
|
const wanted = keySet(keys);
|
|
@@ -13349,8 +13533,8 @@ function renderEvalMarkdown(result) {
|
|
|
13349
13533
|
if (result.findings.length > 0) {
|
|
13350
13534
|
lines.push("", "## Findings");
|
|
13351
13535
|
for (const finding of result.findings) {
|
|
13352
|
-
const
|
|
13353
|
-
lines.push(`- ${finding.ruleId}: ${finding.message}${
|
|
13536
|
+
const path19 = finding.evidence[0]?.path;
|
|
13537
|
+
lines.push(`- ${finding.ruleId}: ${finding.message}${path19 ? ` (${path19})` : ""}`);
|
|
13354
13538
|
}
|
|
13355
13539
|
}
|
|
13356
13540
|
return `${lines.join("\n")}
|
|
@@ -13543,8 +13727,8 @@ function printHuman2(result) {
|
|
|
13543
13727
|
console.log(`- ${diagnostic4.code}: ${diagnostic4.message}`);
|
|
13544
13728
|
}
|
|
13545
13729
|
for (const finding of result.findings) {
|
|
13546
|
-
const
|
|
13547
|
-
console.log(`- ${finding.ruleId}: ${finding.message}${
|
|
13730
|
+
const path19 = finding.evidence[0]?.path;
|
|
13731
|
+
console.log(`- ${finding.ruleId}: ${finding.message}${path19 ? ` (${path19})` : ""}`);
|
|
13548
13732
|
}
|
|
13549
13733
|
}
|
|
13550
13734
|
function readErrorResult2(error) {
|
|
@@ -13782,8 +13966,8 @@ function printHuman3(result) {
|
|
|
13782
13966
|
console.log(`- ${diagnostic4.code}: ${diagnostic4.message}`);
|
|
13783
13967
|
}
|
|
13784
13968
|
for (const finding of result.findings) {
|
|
13785
|
-
const
|
|
13786
|
-
console.log(`- ${finding.ruleId}: ${finding.message}${
|
|
13969
|
+
const path19 = finding.evidence[0]?.path;
|
|
13970
|
+
console.log(`- ${finding.ruleId}: ${finding.message}${path19 ? ` (${path19})` : ""}`);
|
|
13787
13971
|
}
|
|
13788
13972
|
console.log(`Note: ${result.note}`);
|
|
13789
13973
|
}
|
|
@@ -13902,8 +14086,8 @@ function renderCheckSection(result) {
|
|
|
13902
14086
|
`Diagnostics: ${result.diagnostics.length}`
|
|
13903
14087
|
];
|
|
13904
14088
|
for (const finding of result.findings.slice(0, 10)) {
|
|
13905
|
-
const
|
|
13906
|
-
lines.push(`- ${finding.ruleId}: ${finding.message} (${
|
|
14089
|
+
const path19 = finding.evidence[0]?.path ?? "(run)";
|
|
14090
|
+
lines.push(`- ${finding.ruleId}: ${finding.message} (${path19})`);
|
|
13907
14091
|
}
|
|
13908
14092
|
for (const diagnostic4 of result.diagnostics.slice(0, 10)) {
|
|
13909
14093
|
lines.push(`- ${diagnostic4.code}: ${diagnostic4.message}`);
|
|
@@ -14905,6 +15089,174 @@ Summary: ${failed} failed, ${warned} warnings`);
|
|
|
14905
15089
|
if (failed > 0) process3__default.default.exitCode = 1;
|
|
14906
15090
|
}
|
|
14907
15091
|
|
|
15092
|
+
// packages/adapter-sdk/src/indexer.ts
|
|
15093
|
+
function defineIndexer(indexer) {
|
|
15094
|
+
if (!indexer.id.trim()) throw new Error("indexer id is required");
|
|
15095
|
+
return indexer;
|
|
15096
|
+
}
|
|
15097
|
+
async function indexIsStale(snapshot, traceDir) {
|
|
15098
|
+
const builtMs = Date.parse(snapshot.builtAt);
|
|
15099
|
+
if (Number.isNaN(builtMs)) return true;
|
|
15100
|
+
const td = new TraceDirectory({ dir: traceDir });
|
|
15101
|
+
const files = await td.list();
|
|
15102
|
+
for (const file of files) {
|
|
15103
|
+
const stats = await td.getFileStats(file);
|
|
15104
|
+
if (stats.mtimeMs > builtMs) return true;
|
|
15105
|
+
}
|
|
15106
|
+
return false;
|
|
15107
|
+
}
|
|
15108
|
+
function createTraceDirectoryIndexer() {
|
|
15109
|
+
return defineIndexer({
|
|
15110
|
+
id: "trace-directory-metadata",
|
|
15111
|
+
async rebuild(traceDir, options = {}) {
|
|
15112
|
+
const warnings = [];
|
|
15113
|
+
const td = new TraceDirectory({ dir: traceDir });
|
|
15114
|
+
const files = await td.list();
|
|
15115
|
+
const maxEntries = options.maxEntries ?? 1e4;
|
|
15116
|
+
if (files.length > maxEntries) {
|
|
15117
|
+
warnings.push(
|
|
15118
|
+
`indexer.truncated: trace directory has ${files.length} files; indexing first ${maxEntries}`
|
|
15119
|
+
);
|
|
15120
|
+
}
|
|
15121
|
+
const slice = files.slice(0, maxEntries);
|
|
15122
|
+
const metas = await loadTraceMetadataList(
|
|
15123
|
+
traceDir,
|
|
15124
|
+
slice,
|
|
15125
|
+
(fileName) => td.getPath(fileName)
|
|
15126
|
+
);
|
|
15127
|
+
const entries = metas.map((meta) => ({
|
|
15128
|
+
runId: meta.runId,
|
|
15129
|
+
path: meta.filePath,
|
|
15130
|
+
name: meta.name,
|
|
15131
|
+
startedAt: meta.startedAt,
|
|
15132
|
+
status: meta.status
|
|
15133
|
+
})).sort((a, b) => a.runId.localeCompare(b.runId));
|
|
15134
|
+
if (entries.length < slice.length) {
|
|
15135
|
+
warnings.push(
|
|
15136
|
+
`indexer.partial: indexed ${entries.length} of ${slice.length} trace files`
|
|
15137
|
+
);
|
|
15138
|
+
}
|
|
15139
|
+
return {
|
|
15140
|
+
traceDir,
|
|
15141
|
+
builtAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
15142
|
+
entries,
|
|
15143
|
+
warnings
|
|
15144
|
+
};
|
|
15145
|
+
}
|
|
15146
|
+
});
|
|
15147
|
+
}
|
|
15148
|
+
|
|
15149
|
+
// packages/cli/src/index-cmd.ts
|
|
15150
|
+
var INDEX_FILENAME = ".agent-inspect-index.json";
|
|
15151
|
+
function traceIndexPath(traceDir) {
|
|
15152
|
+
return path14__default.default.join(traceDir, INDEX_FILENAME);
|
|
15153
|
+
}
|
|
15154
|
+
function parseMaxEntries(raw) {
|
|
15155
|
+
if (raw === void 0 || raw.trim() === "") return void 0;
|
|
15156
|
+
const parsed = Number.parseInt(raw, 10);
|
|
15157
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
15158
|
+
throw new Error("--max-entries must be a positive integer.");
|
|
15159
|
+
}
|
|
15160
|
+
return parsed;
|
|
15161
|
+
}
|
|
15162
|
+
async function readSnapshot(indexPath2) {
|
|
15163
|
+
try {
|
|
15164
|
+
const raw = await promises.readFile(indexPath2, "utf8");
|
|
15165
|
+
return JSON.parse(raw);
|
|
15166
|
+
} catch {
|
|
15167
|
+
return void 0;
|
|
15168
|
+
}
|
|
15169
|
+
}
|
|
15170
|
+
async function indexBuildCommand(options = {}) {
|
|
15171
|
+
try {
|
|
15172
|
+
const traceDir = resolveTraceDir({ dir: options.dir });
|
|
15173
|
+
await promises.mkdir(traceDir, { recursive: true });
|
|
15174
|
+
const indexer = createTraceDirectoryIndexer();
|
|
15175
|
+
const snapshot = await indexer.rebuild(traceDir, {
|
|
15176
|
+
maxEntries: parseMaxEntries(options.maxEntries)
|
|
15177
|
+
});
|
|
15178
|
+
const indexPath2 = traceIndexPath(traceDir);
|
|
15179
|
+
await promises.writeFile(indexPath2, `${JSON.stringify(snapshot, null, 2)}
|
|
15180
|
+
`, "utf8");
|
|
15181
|
+
if (options.json) {
|
|
15182
|
+
console.log(JSON.stringify({ ok: true, indexPath: indexPath2, ...snapshot }, null, 2));
|
|
15183
|
+
return;
|
|
15184
|
+
}
|
|
15185
|
+
console.log(`Built trace index: ${indexPath2}`);
|
|
15186
|
+
console.log(`Entries: ${snapshot.entries.length}`);
|
|
15187
|
+
if (snapshot.warnings.length > 0) {
|
|
15188
|
+
for (const warning of snapshot.warnings) {
|
|
15189
|
+
console.log(`warning: ${warning}`);
|
|
15190
|
+
}
|
|
15191
|
+
}
|
|
15192
|
+
} catch (e) {
|
|
15193
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
15194
|
+
console.error(`[AgentInspect] index build failed: ${msg}`);
|
|
15195
|
+
process.exitCode = 1;
|
|
15196
|
+
}
|
|
15197
|
+
}
|
|
15198
|
+
async function indexStatusCommand(options = {}) {
|
|
15199
|
+
try {
|
|
15200
|
+
const traceDir = resolveTraceDir({ dir: options.dir });
|
|
15201
|
+
const indexPath2 = traceIndexPath(traceDir);
|
|
15202
|
+
const snapshot = await readSnapshot(indexPath2);
|
|
15203
|
+
if (!snapshot) {
|
|
15204
|
+
const payload2 = { ok: true, exists: false, indexPath: indexPath2, traceDir, stale: true };
|
|
15205
|
+
if (options.json) {
|
|
15206
|
+
console.log(JSON.stringify(payload2, null, 2));
|
|
15207
|
+
} else {
|
|
15208
|
+
console.log(`No index at ${indexPath2}`);
|
|
15209
|
+
console.log("Run: agent-inspect index build");
|
|
15210
|
+
}
|
|
15211
|
+
return;
|
|
15212
|
+
}
|
|
15213
|
+
const stale = await indexIsStale(snapshot, traceDir);
|
|
15214
|
+
const payload = {
|
|
15215
|
+
ok: true,
|
|
15216
|
+
exists: true,
|
|
15217
|
+
indexPath: indexPath2,
|
|
15218
|
+
traceDir,
|
|
15219
|
+
stale,
|
|
15220
|
+
builtAt: snapshot.builtAt,
|
|
15221
|
+
entries: snapshot.entries.length,
|
|
15222
|
+
warnings: snapshot.warnings
|
|
15223
|
+
};
|
|
15224
|
+
if (options.json) {
|
|
15225
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
15226
|
+
return;
|
|
15227
|
+
}
|
|
15228
|
+
console.log(`Index: ${indexPath2}`);
|
|
15229
|
+
console.log(`Built: ${snapshot.builtAt}`);
|
|
15230
|
+
console.log(`Entries: ${snapshot.entries.length}`);
|
|
15231
|
+
console.log(`Stale: ${stale ? "yes" : "no"}`);
|
|
15232
|
+
if (snapshot.warnings.length > 0) {
|
|
15233
|
+
for (const warning of snapshot.warnings) {
|
|
15234
|
+
console.log(`warning: ${warning}`);
|
|
15235
|
+
}
|
|
15236
|
+
}
|
|
15237
|
+
} catch (e) {
|
|
15238
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
15239
|
+
console.error(`[AgentInspect] index status failed: ${msg}`);
|
|
15240
|
+
process.exitCode = 1;
|
|
15241
|
+
}
|
|
15242
|
+
}
|
|
15243
|
+
async function indexCleanCommand(options = {}) {
|
|
15244
|
+
try {
|
|
15245
|
+
const traceDir = resolveTraceDir({ dir: options.dir });
|
|
15246
|
+
const indexPath2 = traceIndexPath(traceDir);
|
|
15247
|
+
await promises.rm(indexPath2, { force: true });
|
|
15248
|
+
if (options.json) {
|
|
15249
|
+
console.log(JSON.stringify({ ok: true, removed: indexPath2 }, null, 2));
|
|
15250
|
+
return;
|
|
15251
|
+
}
|
|
15252
|
+
console.log(`Removed index: ${indexPath2}`);
|
|
15253
|
+
} catch (e) {
|
|
15254
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
15255
|
+
console.error(`[AgentInspect] index clean failed: ${msg}`);
|
|
15256
|
+
process.exitCode = 1;
|
|
15257
|
+
}
|
|
15258
|
+
}
|
|
15259
|
+
|
|
14908
15260
|
// packages/cli/src/index.ts
|
|
14909
15261
|
function runCommand(action) {
|
|
14910
15262
|
void action().catch((error) => {
|
|
@@ -15029,7 +15381,10 @@ function createCliProgram() {
|
|
|
15029
15381
|
]).option("--allowed-model <model>", "allow an LLM model (repeatable)", (value, previous = []) => [
|
|
15030
15382
|
...previous,
|
|
15031
15383
|
value
|
|
15032
|
-
]).option("--max-total-tokens <number>", "add llm.usage with a max total-token budget").option(
|
|
15384
|
+
]).option("--max-total-tokens <number>", "add llm.usage with a max total-token budget").option(
|
|
15385
|
+
"--max-step-duration <duration>",
|
|
15386
|
+
"add run.maxStepDuration (e.g. 30s, 5m)"
|
|
15387
|
+
).option("--require-completed", "add run.requireCompleted").option("--detect-stalls", "add run.stall for running or incomplete events").option("--session <id>", "check all runs in a workflow session (requires --dir)").option("--group <id>", "check all runs sharing a groupId (requires --dir)").option(
|
|
15033
15388
|
"--correlate-group",
|
|
15034
15389
|
"when using --session, also match synthetic group: session keys"
|
|
15035
15390
|
).option(
|
|
@@ -15223,6 +15578,16 @@ function createCliProgram() {
|
|
|
15223
15578
|
).action((opts) => {
|
|
15224
15579
|
runCommand(() => doctorCommand(opts));
|
|
15225
15580
|
});
|
|
15581
|
+
const indexCmd = program.command("index").description("Optional local trace directory index (rebuildable metadata cache)");
|
|
15582
|
+
indexCmd.command("build").description("Build or refresh .agent-inspect-index.json").option("--dir <path>", "trace directory").option("--json", "print JSON result").option("--max-entries <n>", "cap indexed entries (default 10000)").action((opts) => {
|
|
15583
|
+
runCommand(() => indexBuildCommand(opts));
|
|
15584
|
+
});
|
|
15585
|
+
indexCmd.command("status").description("Show index freshness and entry count").option("--dir <path>", "trace directory").option("--json", "print JSON result").action((opts) => {
|
|
15586
|
+
runCommand(() => indexStatusCommand(opts));
|
|
15587
|
+
});
|
|
15588
|
+
indexCmd.command("clean").description("Remove the local index file").option("--dir <path>", "trace directory").option("--json", "print JSON result").action((opts) => {
|
|
15589
|
+
runCommand(() => indexCleanCommand(opts));
|
|
15590
|
+
});
|
|
15226
15591
|
return program;
|
|
15227
15592
|
}
|
|
15228
15593
|
function isPrimaryModule() {
|