agent-inspect 3.0.0 → 3.1.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 +16 -0
- package/README.md +11 -1
- package/docs/CLI.md +2 -0
- package/docs/GETTING-STARTED.md +19 -0
- package/package.json +1 -1
- package/packages/cli/dist/index.cjs +537 -75
- package/packages/cli/dist/index.cjs.map +1 -1
- package/packages/cli/dist/index.mjs +534 -72
- package/packages/cli/dist/index.mjs.map +1 -1
|
@@ -9,10 +9,11 @@ var async_hooks = require('async_hooks');
|
|
|
9
9
|
var crypto = require('crypto');
|
|
10
10
|
var promises = require('fs/promises');
|
|
11
11
|
var os = require('os');
|
|
12
|
-
var
|
|
12
|
+
var process3 = require('process');
|
|
13
13
|
var tty = require('tty');
|
|
14
14
|
var readline = require('readline');
|
|
15
15
|
var http = require('http');
|
|
16
|
+
var module$1 = require('module');
|
|
16
17
|
|
|
17
18
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
18
19
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
@@ -20,11 +21,11 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
|
20
21
|
var path14__default = /*#__PURE__*/_interopDefault(path14);
|
|
21
22
|
var crypto__default = /*#__PURE__*/_interopDefault(crypto);
|
|
22
23
|
var os__default = /*#__PURE__*/_interopDefault(os);
|
|
23
|
-
var
|
|
24
|
+
var process3__default = /*#__PURE__*/_interopDefault(process3);
|
|
24
25
|
var tty__default = /*#__PURE__*/_interopDefault(tty);
|
|
25
26
|
|
|
26
27
|
// package.json
|
|
27
|
-
var version = "3.
|
|
28
|
+
var version = "3.1.0";
|
|
28
29
|
|
|
29
30
|
// packages/core/src/correlation-metadata.ts
|
|
30
31
|
var TRACE_CORRELATION_KEYS = [
|
|
@@ -1188,13 +1189,13 @@ function assembleStyles() {
|
|
|
1188
1189
|
}
|
|
1189
1190
|
var ansiStyles = assembleStyles();
|
|
1190
1191
|
var ansi_styles_default = ansiStyles;
|
|
1191
|
-
function hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args :
|
|
1192
|
+
function hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args : process3__default.default.argv) {
|
|
1192
1193
|
const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
|
|
1193
1194
|
const position = argv.indexOf(prefix + flag);
|
|
1194
1195
|
const terminatorPosition = argv.indexOf("--");
|
|
1195
1196
|
return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
|
|
1196
1197
|
}
|
|
1197
|
-
var { env } =
|
|
1198
|
+
var { env } = process3__default.default;
|
|
1198
1199
|
var flagForceColor;
|
|
1199
1200
|
if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) {
|
|
1200
1201
|
flagForceColor = 0;
|
|
@@ -1250,7 +1251,7 @@ function _supportsColor(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
|
|
|
1250
1251
|
if (env.TERM === "dumb") {
|
|
1251
1252
|
return min;
|
|
1252
1253
|
}
|
|
1253
|
-
if (
|
|
1254
|
+
if (process3__default.default.platform === "win32") {
|
|
1254
1255
|
const osRelease = os__default.default.release().split(".");
|
|
1255
1256
|
if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
|
|
1256
1257
|
return Number(osRelease[2]) >= 14931 ? 3 : 2;
|
|
@@ -3070,12 +3071,12 @@ function buildCriticalPath(runs, handoffs) {
|
|
|
3070
3071
|
handoffs.filter((edge) => edge.confidence === "explicit").map((edge) => edge.from)
|
|
3071
3072
|
);
|
|
3072
3073
|
const ordered = [...runs].sort(compareRuns);
|
|
3073
|
-
const
|
|
3074
|
+
const path18 = [];
|
|
3074
3075
|
const visited = /* @__PURE__ */ new Set();
|
|
3075
3076
|
const pushRun = (run, confidence, source) => {
|
|
3076
3077
|
if (visited.has(run.runId)) return;
|
|
3077
3078
|
visited.add(run.runId);
|
|
3078
|
-
|
|
3079
|
+
path18.push({
|
|
3079
3080
|
runId: run.runId,
|
|
3080
3081
|
name: run.name,
|
|
3081
3082
|
startedAt: run.startedAt,
|
|
@@ -3100,7 +3101,7 @@ function buildCriticalPath(runs, handoffs) {
|
|
|
3100
3101
|
const confidence = explicitTargets.has(run.runId) || explicitSources.has(run.runId) ? "explicit" : "correlated";
|
|
3101
3102
|
pushRun(run, confidence, confidence === "explicit" ? "manual" : "inferred");
|
|
3102
3103
|
}
|
|
3103
|
-
return
|
|
3104
|
+
return path18;
|
|
3104
3105
|
}
|
|
3105
3106
|
function metaRunIdMatches(run, token, runById) {
|
|
3106
3107
|
const meta = extractSessionWorkflowMetadata(run.metadata);
|
|
@@ -3326,7 +3327,7 @@ function stableSortNewestFirst(a, b) {
|
|
|
3326
3327
|
}
|
|
3327
3328
|
async function confirmDeletion(count) {
|
|
3328
3329
|
const { createInterface: createInterface2 } = await import('readline/promises');
|
|
3329
|
-
const rl = createInterface2({ input:
|
|
3330
|
+
const rl = createInterface2({ input: process3.stdin, output: process3.stdout });
|
|
3330
3331
|
try {
|
|
3331
3332
|
const answer = await rl.question(
|
|
3332
3333
|
`Delete ${count} AgentInspect trace file(s)? Type "yes" to continue: `
|
|
@@ -3419,7 +3420,7 @@ async function clean(options = {}) {
|
|
|
3419
3420
|
return;
|
|
3420
3421
|
}
|
|
3421
3422
|
if (options.yes !== true) {
|
|
3422
|
-
if (
|
|
3423
|
+
if (process3.stdin.isTTY !== true) {
|
|
3423
3424
|
console.error(
|
|
3424
3425
|
"Refusing to delete without --yes in a non-interactive terminal."
|
|
3425
3426
|
);
|
|
@@ -6674,7 +6675,7 @@ function sleep(ms) {
|
|
|
6674
6675
|
}
|
|
6675
6676
|
async function* readStdinLines() {
|
|
6676
6677
|
const { createInterface: createInterface2 } = await import('readline');
|
|
6677
|
-
const rl = createInterface2({ input:
|
|
6678
|
+
const rl = createInterface2({ input: process3.stdin, crlfDelay: Infinity });
|
|
6678
6679
|
try {
|
|
6679
6680
|
for await (const line of rl) {
|
|
6680
6681
|
yield line;
|
|
@@ -8343,13 +8344,13 @@ function pairSteps(left, right) {
|
|
|
8343
8344
|
return pairs;
|
|
8344
8345
|
}
|
|
8345
8346
|
function compareLeafSteps(L, R, segments, opts, out) {
|
|
8346
|
-
const
|
|
8347
|
+
const path18 = buildPath(segments);
|
|
8347
8348
|
if (L.name !== R.name) {
|
|
8348
8349
|
out.push({
|
|
8349
8350
|
kind: "structure",
|
|
8350
8351
|
severity: "warning",
|
|
8351
8352
|
message: "Step name differs",
|
|
8352
|
-
path:
|
|
8353
|
+
path: path18,
|
|
8353
8354
|
left: L.name,
|
|
8354
8355
|
right: R.name
|
|
8355
8356
|
});
|
|
@@ -8359,7 +8360,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
|
|
|
8359
8360
|
kind: "step-type",
|
|
8360
8361
|
severity: "warning",
|
|
8361
8362
|
message: "Step type differs",
|
|
8362
|
-
path:
|
|
8363
|
+
path: path18,
|
|
8363
8364
|
left: L.type,
|
|
8364
8365
|
right: R.type
|
|
8365
8366
|
});
|
|
@@ -8369,7 +8370,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
|
|
|
8369
8370
|
kind: "step-status",
|
|
8370
8371
|
severity: "warning",
|
|
8371
8372
|
message: "Step status differs",
|
|
8372
|
-
path:
|
|
8373
|
+
path: path18,
|
|
8373
8374
|
left: L.status,
|
|
8374
8375
|
right: R.status
|
|
8375
8376
|
});
|
|
@@ -8381,7 +8382,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
|
|
|
8381
8382
|
kind: "error",
|
|
8382
8383
|
severity: "error",
|
|
8383
8384
|
message: "Step error message differs",
|
|
8384
|
-
path:
|
|
8385
|
+
path: path18,
|
|
8385
8386
|
left: le || void 0,
|
|
8386
8387
|
right: re || void 0
|
|
8387
8388
|
});
|
|
@@ -8399,7 +8400,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
|
|
|
8399
8400
|
kind: "duration",
|
|
8400
8401
|
severity: "info",
|
|
8401
8402
|
message: "Step duration differs",
|
|
8402
|
-
path:
|
|
8403
|
+
path: path18,
|
|
8403
8404
|
left: ld,
|
|
8404
8405
|
right: rd
|
|
8405
8406
|
});
|
|
@@ -8412,7 +8413,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
|
|
|
8412
8413
|
kind: "metadata",
|
|
8413
8414
|
severity: "info",
|
|
8414
8415
|
message: "Step metadata differs",
|
|
8415
|
-
path:
|
|
8416
|
+
path: path18,
|
|
8416
8417
|
left: L.metadata,
|
|
8417
8418
|
right: R.metadata
|
|
8418
8419
|
});
|
|
@@ -8424,7 +8425,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
|
|
|
8424
8425
|
kind: "output",
|
|
8425
8426
|
severity: "info",
|
|
8426
8427
|
message: "Output preview differs",
|
|
8427
|
-
path:
|
|
8428
|
+
path: path18,
|
|
8428
8429
|
left: L.outputPreview,
|
|
8429
8430
|
right: R.outputPreview
|
|
8430
8431
|
});
|
|
@@ -8584,11 +8585,11 @@ function diffRuns(left, right, options) {
|
|
|
8584
8585
|
}
|
|
8585
8586
|
|
|
8586
8587
|
// packages/core/src/diff/renderer.ts
|
|
8587
|
-
function formatPath(
|
|
8588
|
-
if (
|
|
8588
|
+
function formatPath(path18) {
|
|
8589
|
+
if (path18 === void 0 || path18.path.length === 0) {
|
|
8589
8590
|
return "(run)";
|
|
8590
8591
|
}
|
|
8591
|
-
return
|
|
8592
|
+
return path18.path.map((s) => s.name).join(" > ");
|
|
8592
8593
|
}
|
|
8593
8594
|
function formatValue(v, verbose) {
|
|
8594
8595
|
if (v === void 0) return "(undefined)";
|
|
@@ -9466,17 +9467,17 @@ function applyRule(rule, value, replacement) {
|
|
|
9466
9467
|
}
|
|
9467
9468
|
return value;
|
|
9468
9469
|
}
|
|
9469
|
-
function childPath(
|
|
9470
|
+
function childPath(path18, key) {
|
|
9470
9471
|
if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key)) {
|
|
9471
|
-
return
|
|
9472
|
+
return path18 ? `${path18}.${key}` : key;
|
|
9472
9473
|
}
|
|
9473
|
-
return `${
|
|
9474
|
+
return `${path18 || "$"}[${JSON.stringify(key)}]`;
|
|
9474
9475
|
}
|
|
9475
|
-
function indexPath(
|
|
9476
|
-
return `${
|
|
9476
|
+
function indexPath(path18, index) {
|
|
9477
|
+
return `${path18 || "$"}[${index}]`;
|
|
9477
9478
|
}
|
|
9478
|
-
function makeFinding(
|
|
9479
|
-
return preview === void 0 ? { path:
|
|
9479
|
+
function makeFinding(path18, detector, action, matchKind, severity = "warning", preview) {
|
|
9480
|
+
return preview === void 0 ? { path: path18, detector, action, severity, matchKind } : { path: path18, detector, action, severity, matchKind, preview };
|
|
9480
9481
|
}
|
|
9481
9482
|
function createRedactionProfile(profile = "local") {
|
|
9482
9483
|
switch (profile) {
|
|
@@ -9545,11 +9546,11 @@ var Redactor2 = class {
|
|
|
9545
9546
|
#recordFinding(state, finding) {
|
|
9546
9547
|
if (this.#collectFindings) state.findings.push(finding);
|
|
9547
9548
|
}
|
|
9548
|
-
#redactValue(value, key,
|
|
9549
|
+
#redactValue(value, key, path18, depth, state) {
|
|
9549
9550
|
if (depth > this.#maxDepth) {
|
|
9550
9551
|
this.#recordFinding(
|
|
9551
9552
|
state,
|
|
9552
|
-
makeFinding(
|
|
9553
|
+
makeFinding(path18, "structure.maxDepth", "truncate", "value", "warning")
|
|
9553
9554
|
);
|
|
9554
9555
|
return "[Truncated]";
|
|
9555
9556
|
}
|
|
@@ -9558,19 +9559,19 @@ var Redactor2 = class {
|
|
|
9558
9559
|
if (rule) {
|
|
9559
9560
|
this.#recordFinding(
|
|
9560
9561
|
state,
|
|
9561
|
-
makeFinding(
|
|
9562
|
+
makeFinding(path18, `key.${rule.key}`, actionForRule(rule), "key", "warning")
|
|
9562
9563
|
);
|
|
9563
9564
|
return applyRule(rule, value, this.#replacement);
|
|
9564
9565
|
}
|
|
9565
9566
|
}
|
|
9566
9567
|
for (const detector of this.#detectors) {
|
|
9567
|
-
const detections = detector.detect({ path:
|
|
9568
|
+
const detections = detector.detect({ path: path18, key, value });
|
|
9568
9569
|
for (const detection of detections) {
|
|
9569
9570
|
const action = detection.action ?? "replace";
|
|
9570
9571
|
this.#recordFinding(
|
|
9571
9572
|
state,
|
|
9572
9573
|
makeFinding(
|
|
9573
|
-
|
|
9574
|
+
path18,
|
|
9574
9575
|
detector.id,
|
|
9575
9576
|
action,
|
|
9576
9577
|
detection.matchKind ?? detector.matchKind ?? "custom",
|
|
@@ -9588,7 +9589,7 @@ var Redactor2 = class {
|
|
|
9588
9589
|
const out = [];
|
|
9589
9590
|
state.seen.set(value, out);
|
|
9590
9591
|
value.forEach((item, index) => {
|
|
9591
|
-
out[index] = this.#redactValue(item, void 0, indexPath(
|
|
9592
|
+
out[index] = this.#redactValue(item, void 0, indexPath(path18, index), depth + 1, state);
|
|
9592
9593
|
});
|
|
9593
9594
|
return out;
|
|
9594
9595
|
}
|
|
@@ -9600,7 +9601,7 @@ var Redactor2 = class {
|
|
|
9600
9601
|
out[entryKey] = this.#redactValue(
|
|
9601
9602
|
entryValue,
|
|
9602
9603
|
entryKey,
|
|
9603
|
-
childPath(
|
|
9604
|
+
childPath(path18 === "$" ? "" : path18, entryKey),
|
|
9604
9605
|
depth + 1,
|
|
9605
9606
|
state
|
|
9606
9607
|
);
|
|
@@ -10472,7 +10473,7 @@ function stripPrefix(name, prefixes) {
|
|
|
10472
10473
|
}
|
|
10473
10474
|
return name;
|
|
10474
10475
|
}
|
|
10475
|
-
function eventEvidence(event,
|
|
10476
|
+
function eventEvidence(event, path18) {
|
|
10476
10477
|
return {
|
|
10477
10478
|
runId: event.runId,
|
|
10478
10479
|
eventId: event.eventId,
|
|
@@ -10482,7 +10483,7 @@ function eventEvidence(event, path16) {
|
|
|
10482
10483
|
kind: event.kind,
|
|
10483
10484
|
name: event.name,
|
|
10484
10485
|
status: event.status,
|
|
10485
|
-
...
|
|
10486
|
+
...path18 ? { path: path18 } : {}
|
|
10486
10487
|
};
|
|
10487
10488
|
}
|
|
10488
10489
|
function runEvidence(run) {
|
|
@@ -10545,9 +10546,9 @@ function eventEndMs(event) {
|
|
|
10545
10546
|
function normalizedKey(value) {
|
|
10546
10547
|
return value.toLowerCase().replace(/[^a-z0-9_]/g, "");
|
|
10547
10548
|
}
|
|
10548
|
-
function lastPathSegment(
|
|
10549
|
-
const parts =
|
|
10550
|
-
return parts[parts.length - 1] ??
|
|
10549
|
+
function lastPathSegment(path18) {
|
|
10550
|
+
const parts = path18.split(".");
|
|
10551
|
+
return parts[parts.length - 1] ?? path18;
|
|
10551
10552
|
}
|
|
10552
10553
|
function valueType(value) {
|
|
10553
10554
|
if (Array.isArray(value)) return "array";
|
|
@@ -10561,12 +10562,12 @@ function serializedByteLength(value) {
|
|
|
10561
10562
|
return void 0;
|
|
10562
10563
|
}
|
|
10563
10564
|
}
|
|
10564
|
-
function pushValueEntries(entries, event, value,
|
|
10565
|
-
entries.push({ event, path:
|
|
10565
|
+
function pushValueEntries(entries, event, value, path18, key, depth = 0) {
|
|
10566
|
+
entries.push({ event, path: path18, key, value });
|
|
10566
10567
|
if (depth >= 8) return;
|
|
10567
10568
|
if (Array.isArray(value)) {
|
|
10568
10569
|
for (const [index, item] of value.entries()) {
|
|
10569
|
-
pushValueEntries(entries, event, item, `${
|
|
10570
|
+
pushValueEntries(entries, event, item, `${path18}.${index}`, String(index), depth + 1);
|
|
10570
10571
|
}
|
|
10571
10572
|
return;
|
|
10572
10573
|
}
|
|
@@ -10576,7 +10577,7 @@ function pushValueEntries(entries, event, value, path16, key, depth = 0) {
|
|
|
10576
10577
|
entries,
|
|
10577
10578
|
event,
|
|
10578
10579
|
value[nestedKey],
|
|
10579
|
-
`${
|
|
10580
|
+
`${path18}.${nestedKey}`,
|
|
10580
10581
|
nestedKey,
|
|
10581
10582
|
depth + 1
|
|
10582
10583
|
);
|
|
@@ -10657,9 +10658,9 @@ function eventDurationMs(event) {
|
|
|
10657
10658
|
}
|
|
10658
10659
|
function treeShape(nodes) {
|
|
10659
10660
|
const lines = [];
|
|
10660
|
-
const visit = (node,
|
|
10661
|
-
lines.push(`${
|
|
10662
|
-
node.children.forEach((child, index) => visit(child, `${
|
|
10661
|
+
const visit = (node, path18) => {
|
|
10662
|
+
lines.push(`${path18}:${node.event.kind}:${node.event.name}:${node.event.status ?? "unknown"}`);
|
|
10663
|
+
node.children.forEach((child, index) => visit(child, `${path18}.${index}`));
|
|
10663
10664
|
};
|
|
10664
10665
|
nodes.forEach((node, index) => visit(node, String(index)));
|
|
10665
10666
|
return lines;
|
|
@@ -10708,9 +10709,9 @@ function retrievalShape(context) {
|
|
|
10708
10709
|
function guardrailShape(context) {
|
|
10709
10710
|
return guardrailEvents(context).map((event) => signalName(event, ["guardrailName", "guardrail", "guardrailId"], ["guardrail:"])).sort((a, b) => a.localeCompare(b));
|
|
10710
10711
|
}
|
|
10711
|
-
function firstEvidenceForKind(context, kind,
|
|
10712
|
+
function firstEvidenceForKind(context, kind, path18) {
|
|
10712
10713
|
const event = context.events.find((candidate) => candidate.kind === kind);
|
|
10713
|
-
return event ? [eventEvidence(event,
|
|
10714
|
+
return event ? [eventEvidence(event, path18)] : runEvidence(context.selectedRun);
|
|
10714
10715
|
}
|
|
10715
10716
|
function baselineDiffFinding(message, evidence, expected, actual) {
|
|
10716
10717
|
return failFinding("baseline.regression", message, evidence, expected, actual);
|
|
@@ -10958,13 +10959,13 @@ function createStructureCycleRule() {
|
|
|
10958
10959
|
const seenCycles = /* @__PURE__ */ new Set();
|
|
10959
10960
|
const findings = [];
|
|
10960
10961
|
for (const event of [...context.events].sort((a, b) => a.eventId.localeCompare(b.eventId))) {
|
|
10961
|
-
const
|
|
10962
|
+
const path18 = [];
|
|
10962
10963
|
const seenAt = /* @__PURE__ */ new Map();
|
|
10963
10964
|
let current = event;
|
|
10964
10965
|
while (current) {
|
|
10965
10966
|
const existing = seenAt.get(current.eventId);
|
|
10966
10967
|
if (existing !== void 0) {
|
|
10967
|
-
const cycle =
|
|
10968
|
+
const cycle = path18.slice(existing);
|
|
10968
10969
|
const key = cycle.map((item) => item.eventId).sort().join("\0");
|
|
10969
10970
|
if (!seenCycles.has(key)) {
|
|
10970
10971
|
seenCycles.add(key);
|
|
@@ -10980,8 +10981,8 @@ function createStructureCycleRule() {
|
|
|
10980
10981
|
}
|
|
10981
10982
|
break;
|
|
10982
10983
|
}
|
|
10983
|
-
seenAt.set(current.eventId,
|
|
10984
|
-
|
|
10984
|
+
seenAt.set(current.eventId, path18.length);
|
|
10985
|
+
path18.push(current);
|
|
10985
10986
|
current = current.parentId ? byId.get(current.parentId) : void 0;
|
|
10986
10987
|
}
|
|
10987
10988
|
}
|
|
@@ -11778,23 +11779,23 @@ function evaluatePromptInjection(text, options = {}) {
|
|
|
11778
11779
|
}
|
|
11779
11780
|
return fail(ruleId, `Matched ${evidence.length} injection pattern(s).`, evidence, "warning");
|
|
11780
11781
|
}
|
|
11781
|
-
function validateSchemaField(value, field,
|
|
11782
|
+
function validateSchemaField(value, field, path18, evidence) {
|
|
11782
11783
|
const ruleId = "guardrail.structured-output";
|
|
11783
11784
|
if (field.type) {
|
|
11784
11785
|
const actual = value === null ? "null" : Array.isArray(value) ? "array" : typeof value;
|
|
11785
11786
|
if (actual !== field.type) {
|
|
11786
|
-
evidence.push({ ruleId, path:
|
|
11787
|
+
evidence.push({ ruleId, path: path18, preview: `expected ${field.type}, got ${actual}` });
|
|
11787
11788
|
return;
|
|
11788
11789
|
}
|
|
11789
11790
|
}
|
|
11790
11791
|
if (field.enum && !field.enum.some((item) => Object.is(item, value))) {
|
|
11791
|
-
evidence.push({ ruleId, path:
|
|
11792
|
+
evidence.push({ ruleId, path: path18, preview: "value not in enum" });
|
|
11792
11793
|
}
|
|
11793
11794
|
if (field.type === "object" && field.required && value && typeof value === "object" && !Array.isArray(value)) {
|
|
11794
11795
|
const record = value;
|
|
11795
11796
|
for (const key of field.required) {
|
|
11796
11797
|
if (!(key in record)) {
|
|
11797
|
-
evidence.push({ ruleId, path: `${
|
|
11798
|
+
evidence.push({ ruleId, path: `${path18}.${key}`, preview: "missing required key" });
|
|
11798
11799
|
}
|
|
11799
11800
|
}
|
|
11800
11801
|
}
|
|
@@ -12259,10 +12260,10 @@ function printHuman(result) {
|
|
|
12259
12260
|
console.log(`- ${diagnostic4.code}: ${diagnostic4.message}`);
|
|
12260
12261
|
}
|
|
12261
12262
|
for (const finding of result.findings) {
|
|
12262
|
-
const
|
|
12263
|
+
const path18 = finding.evidence[0]?.path;
|
|
12263
12264
|
const run = finding.evidence[0]?.runId;
|
|
12264
12265
|
const runPrefix = run ? `[${run}] ` : "";
|
|
12265
|
-
console.log(`- ${runPrefix}${finding.ruleId}: ${finding.message}${
|
|
12266
|
+
console.log(`- ${runPrefix}${finding.ruleId}: ${finding.message}${path18 ? ` (${path18})` : ""}`);
|
|
12266
12267
|
}
|
|
12267
12268
|
}
|
|
12268
12269
|
function readErrorResult(error) {
|
|
@@ -12800,10 +12801,10 @@ async function evalRun(input3, options = {}) {
|
|
|
12800
12801
|
diagnostics: []
|
|
12801
12802
|
};
|
|
12802
12803
|
}
|
|
12803
|
-
function evidenceForRun(run,
|
|
12804
|
-
return [{ runId: run.runId, ...
|
|
12804
|
+
function evidenceForRun(run, path18) {
|
|
12805
|
+
return [{ runId: run.runId, ...path18 !== void 0 ? { path: path18 } : {} }];
|
|
12805
12806
|
}
|
|
12806
|
-
function evidenceForEvent(event,
|
|
12807
|
+
function evidenceForEvent(event, path18) {
|
|
12807
12808
|
return [
|
|
12808
12809
|
{
|
|
12809
12810
|
runId: event.runId,
|
|
@@ -12811,7 +12812,7 @@ function evidenceForEvent(event, path16) {
|
|
|
12811
12812
|
...event.parentId !== void 0 ? { parentId: event.parentId } : {},
|
|
12812
12813
|
kind: event.kind,
|
|
12813
12814
|
name: event.name,
|
|
12814
|
-
...
|
|
12815
|
+
...path18 !== void 0 ? { path: path18 } : {}
|
|
12815
12816
|
}
|
|
12816
12817
|
];
|
|
12817
12818
|
}
|
|
@@ -12969,9 +12970,9 @@ function collectTextFields(nodes, keys, preferredKinds = []) {
|
|
|
12969
12970
|
function tokenize(text) {
|
|
12970
12971
|
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));
|
|
12971
12972
|
}
|
|
12972
|
-
function firstEvidence(fields, run,
|
|
12973
|
+
function firstEvidence(fields, run, path18) {
|
|
12973
12974
|
const first = fields[0];
|
|
12974
|
-
return first === void 0 ? evidenceForRun(run,
|
|
12975
|
+
return first === void 0 ? evidenceForRun(run, path18) : evidenceForEvent(first.node.event, first.path);
|
|
12975
12976
|
}
|
|
12976
12977
|
function collectSourceIds(nodes, keys) {
|
|
12977
12978
|
const wanted = keySet(keys);
|
|
@@ -13348,8 +13349,8 @@ function renderEvalMarkdown(result) {
|
|
|
13348
13349
|
if (result.findings.length > 0) {
|
|
13349
13350
|
lines.push("", "## Findings");
|
|
13350
13351
|
for (const finding of result.findings) {
|
|
13351
|
-
const
|
|
13352
|
-
lines.push(`- ${finding.ruleId}: ${finding.message}${
|
|
13352
|
+
const path18 = finding.evidence[0]?.path;
|
|
13353
|
+
lines.push(`- ${finding.ruleId}: ${finding.message}${path18 ? ` (${path18})` : ""}`);
|
|
13353
13354
|
}
|
|
13354
13355
|
}
|
|
13355
13356
|
return `${lines.join("\n")}
|
|
@@ -13542,8 +13543,8 @@ function printHuman2(result) {
|
|
|
13542
13543
|
console.log(`- ${diagnostic4.code}: ${diagnostic4.message}`);
|
|
13543
13544
|
}
|
|
13544
13545
|
for (const finding of result.findings) {
|
|
13545
|
-
const
|
|
13546
|
-
console.log(`- ${finding.ruleId}: ${finding.message}${
|
|
13546
|
+
const path18 = finding.evidence[0]?.path;
|
|
13547
|
+
console.log(`- ${finding.ruleId}: ${finding.message}${path18 ? ` (${path18})` : ""}`);
|
|
13547
13548
|
}
|
|
13548
13549
|
}
|
|
13549
13550
|
function readErrorResult2(error) {
|
|
@@ -13781,8 +13782,8 @@ function printHuman3(result) {
|
|
|
13781
13782
|
console.log(`- ${diagnostic4.code}: ${diagnostic4.message}`);
|
|
13782
13783
|
}
|
|
13783
13784
|
for (const finding of result.findings) {
|
|
13784
|
-
const
|
|
13785
|
-
console.log(`- ${finding.ruleId}: ${finding.message}${
|
|
13785
|
+
const path18 = finding.evidence[0]?.path;
|
|
13786
|
+
console.log(`- ${finding.ruleId}: ${finding.message}${path18 ? ` (${path18})` : ""}`);
|
|
13786
13787
|
}
|
|
13787
13788
|
console.log(`Note: ${result.note}`);
|
|
13788
13789
|
}
|
|
@@ -13901,8 +13902,8 @@ function renderCheckSection(result) {
|
|
|
13901
13902
|
`Diagnostics: ${result.diagnostics.length}`
|
|
13902
13903
|
];
|
|
13903
13904
|
for (const finding of result.findings.slice(0, 10)) {
|
|
13904
|
-
const
|
|
13905
|
-
lines.push(`- ${finding.ruleId}: ${finding.message} (${
|
|
13905
|
+
const path18 = finding.evidence[0]?.path ?? "(run)";
|
|
13906
|
+
lines.push(`- ${finding.ruleId}: ${finding.message} (${path18})`);
|
|
13906
13907
|
}
|
|
13907
13908
|
for (const diagnostic4 of result.diagnostics.slice(0, 10)) {
|
|
13908
13909
|
lines.push(`- ${diagnostic4.code}: ${diagnostic4.message}`);
|
|
@@ -14462,6 +14463,447 @@ ${markdown}`, "utf-8");
|
|
|
14462
14463
|
console.log(markdown.trimEnd());
|
|
14463
14464
|
}
|
|
14464
14465
|
}
|
|
14466
|
+
var CONFIG_FILE = "agent-inspect.config.ts";
|
|
14467
|
+
var TRACE_DIR = ".agent-inspect";
|
|
14468
|
+
var GITKEEP = ".agent-inspect/.gitkeep";
|
|
14469
|
+
function normalizeFramework(value) {
|
|
14470
|
+
const raw = (value ?? "custom").trim();
|
|
14471
|
+
if (raw === "ai-sdk" || raw === "openai-agents" || raw === "langchain" || raw === "custom") {
|
|
14472
|
+
return raw;
|
|
14473
|
+
}
|
|
14474
|
+
throw new Error(
|
|
14475
|
+
"Unsupported --framework value. Use ai-sdk, openai-agents, langchain, or custom."
|
|
14476
|
+
);
|
|
14477
|
+
}
|
|
14478
|
+
function configTemplate(framework) {
|
|
14479
|
+
const base = `/**
|
|
14480
|
+
* AgentInspect local config (metadata-only capture by default).
|
|
14481
|
+
* See https://github.com/rajudandigam/agent-inspect/blob/main/docs/SAFE-TRACE-SHARING.md
|
|
14482
|
+
*/
|
|
14483
|
+
export const agentInspectConfig = {
|
|
14484
|
+
traceDir: ".agent-inspect",
|
|
14485
|
+
enabled: process.env.AGENT_INSPECT !== "0",
|
|
14486
|
+
redactionProfile: "local" as const,
|
|
14487
|
+
};
|
|
14488
|
+
`;
|
|
14489
|
+
if (framework === "custom") return base;
|
|
14490
|
+
return `${base}
|
|
14491
|
+
export const framework = "${framework}" as const;
|
|
14492
|
+
`;
|
|
14493
|
+
}
|
|
14494
|
+
function demoTemplate(framework) {
|
|
14495
|
+
switch (framework) {
|
|
14496
|
+
case "ai-sdk":
|
|
14497
|
+
return `/**
|
|
14498
|
+
* AI SDK starter \u2014 metadata-only telemetry (no real model calls in this demo).
|
|
14499
|
+
* Install: npm install agent-inspect @agent-inspect/ai-sdk ai
|
|
14500
|
+
*/
|
|
14501
|
+
import { inspectRun, step } from "agent-inspect";
|
|
14502
|
+
|
|
14503
|
+
async function main() {
|
|
14504
|
+
await inspectRun("ai-sdk-demo", async () => {
|
|
14505
|
+
await step.tool("mock-generate", async () => ({ text: "ok" }));
|
|
14506
|
+
}, { traceDir: ".agent-inspect", silent: true });
|
|
14507
|
+
console.log("Trace written to .agent-inspect/");
|
|
14508
|
+
}
|
|
14509
|
+
|
|
14510
|
+
main().catch((error) => {
|
|
14511
|
+
console.error(error);
|
|
14512
|
+
process.exitCode = 1;
|
|
14513
|
+
});
|
|
14514
|
+
`;
|
|
14515
|
+
case "openai-agents":
|
|
14516
|
+
return `/**
|
|
14517
|
+
* OpenAI Agents starter \u2014 use @agent-inspect/openai-agents for local-only processors.
|
|
14518
|
+
* This demo uses manual steps (no API keys).
|
|
14519
|
+
*/
|
|
14520
|
+
import { inspectRun, step } from "agent-inspect";
|
|
14521
|
+
|
|
14522
|
+
async function main() {
|
|
14523
|
+
await inspectRun("openai-agents-demo", async () => {
|
|
14524
|
+
await step.tool("mock-agent-run", async () => "ok");
|
|
14525
|
+
}, { traceDir: ".agent-inspect", silent: true });
|
|
14526
|
+
console.log("Trace written to .agent-inspect/");
|
|
14527
|
+
}
|
|
14528
|
+
|
|
14529
|
+
main().catch((error) => {
|
|
14530
|
+
console.error(error);
|
|
14531
|
+
process.exitCode = 1;
|
|
14532
|
+
});
|
|
14533
|
+
`;
|
|
14534
|
+
case "langchain":
|
|
14535
|
+
return `/**
|
|
14536
|
+
* LangChain starter \u2014 wire @agent-inspect/langchain callbacks in your app.
|
|
14537
|
+
* This demo uses manual steps (no API keys).
|
|
14538
|
+
*/
|
|
14539
|
+
import { inspectRun, step } from "agent-inspect";
|
|
14540
|
+
|
|
14541
|
+
async function main() {
|
|
14542
|
+
await inspectRun("langchain-demo", async () => {
|
|
14543
|
+
await step.tool("mock-chain", async () => "ok");
|
|
14544
|
+
}, { traceDir: ".agent-inspect", silent: true });
|
|
14545
|
+
console.log("Trace written to .agent-inspect/");
|
|
14546
|
+
}
|
|
14547
|
+
|
|
14548
|
+
main().catch((error) => {
|
|
14549
|
+
console.error(error);
|
|
14550
|
+
process.exitCode = 1;
|
|
14551
|
+
});
|
|
14552
|
+
`;
|
|
14553
|
+
default:
|
|
14554
|
+
return `import { observe } from "agent-inspect";
|
|
14555
|
+
|
|
14556
|
+
class DemoAgent {
|
|
14557
|
+
async run(input: { question: string }) {
|
|
14558
|
+
return { answer: \`Echo: \${input.question}\` };
|
|
14559
|
+
}
|
|
14560
|
+
}
|
|
14561
|
+
|
|
14562
|
+
const agent = observe(new DemoAgent(), {
|
|
14563
|
+
traceDir: ".agent-inspect",
|
|
14564
|
+
silent: true,
|
|
14565
|
+
});
|
|
14566
|
+
|
|
14567
|
+
await agent.run({ question: "hello" });
|
|
14568
|
+
console.log("Trace written to .agent-inspect/");
|
|
14569
|
+
`;
|
|
14570
|
+
}
|
|
14571
|
+
}
|
|
14572
|
+
function githubWorkflowTemplate() {
|
|
14573
|
+
return `name: AgentInspect artifacts
|
|
14574
|
+
|
|
14575
|
+
on:
|
|
14576
|
+
workflow_dispatch:
|
|
14577
|
+
push:
|
|
14578
|
+
branches: [main]
|
|
14579
|
+
|
|
14580
|
+
jobs:
|
|
14581
|
+
trace-artifacts:
|
|
14582
|
+
runs-on: ubuntu-latest
|
|
14583
|
+
steps:
|
|
14584
|
+
- uses: actions/checkout@v4
|
|
14585
|
+
- uses: actions/setup-node@v4
|
|
14586
|
+
with:
|
|
14587
|
+
node-version: "22"
|
|
14588
|
+
- run: npm ci
|
|
14589
|
+
- run: npm test
|
|
14590
|
+
- name: Upload AgentInspect traces
|
|
14591
|
+
if: always()
|
|
14592
|
+
uses: actions/upload-artifact@v4
|
|
14593
|
+
with:
|
|
14594
|
+
name: agent-inspect-traces
|
|
14595
|
+
path: .agent-inspect/**/*.jsonl
|
|
14596
|
+
if-no-files-found: ignore
|
|
14597
|
+
`;
|
|
14598
|
+
}
|
|
14599
|
+
async function planInit(options = {}) {
|
|
14600
|
+
const framework = normalizeFramework(options.framework);
|
|
14601
|
+
const cwd = path14__default.default.resolve(options.cwd ?? process.cwd());
|
|
14602
|
+
const demoPath = framework === "custom" ? path14__default.default.join("examples", "agent-inspect-demo.mjs") : path14__default.default.join("examples", `agent-inspect-${framework}-demo.mjs`);
|
|
14603
|
+
const candidates = [
|
|
14604
|
+
{ rel: CONFIG_FILE, content: configTemplate(framework) },
|
|
14605
|
+
{ rel: GITKEEP, content: "" },
|
|
14606
|
+
{ rel: demoPath, content: demoTemplate(framework) }
|
|
14607
|
+
];
|
|
14608
|
+
if (options.ci === "github") {
|
|
14609
|
+
candidates.push({
|
|
14610
|
+
rel: ".github/workflows/agent-inspect-artifacts.yml",
|
|
14611
|
+
content: githubWorkflowTemplate()
|
|
14612
|
+
});
|
|
14613
|
+
}
|
|
14614
|
+
const files = [];
|
|
14615
|
+
for (const candidate of candidates) {
|
|
14616
|
+
const abs = path14__default.default.join(cwd, candidate.rel);
|
|
14617
|
+
try {
|
|
14618
|
+
await promises.access(abs);
|
|
14619
|
+
files.push({
|
|
14620
|
+
path: candidate.rel,
|
|
14621
|
+
action: "skip",
|
|
14622
|
+
reason: "file already exists"
|
|
14623
|
+
});
|
|
14624
|
+
} catch (error) {
|
|
14625
|
+
if (error.code !== "ENOENT") throw error;
|
|
14626
|
+
files.push({ path: candidate.rel, action: "create" });
|
|
14627
|
+
}
|
|
14628
|
+
}
|
|
14629
|
+
return { framework, ...options.ci ? { ci: options.ci } : {}, files };
|
|
14630
|
+
}
|
|
14631
|
+
async function writePlannedFiles(plan, cwd, options) {
|
|
14632
|
+
const written = [];
|
|
14633
|
+
for (const entry of plan.files) {
|
|
14634
|
+
if (entry.action === "skip") {
|
|
14635
|
+
continue;
|
|
14636
|
+
}
|
|
14637
|
+
const abs = path14__default.default.join(cwd, entry.path);
|
|
14638
|
+
if (options.dryRun) {
|
|
14639
|
+
written.push(entry.path);
|
|
14640
|
+
continue;
|
|
14641
|
+
}
|
|
14642
|
+
await promises.mkdir(path14__default.default.dirname(abs), { recursive: true });
|
|
14643
|
+
const content = entry.path === CONFIG_FILE ? configTemplate(plan.framework) : entry.path === GITKEEP ? "" : entry.path.endsWith(".yml") ? githubWorkflowTemplate() : demoTemplate(plan.framework);
|
|
14644
|
+
await promises.writeFile(abs, content, "utf-8");
|
|
14645
|
+
written.push(entry.path);
|
|
14646
|
+
}
|
|
14647
|
+
return written;
|
|
14648
|
+
}
|
|
14649
|
+
async function initCommand(options = {}) {
|
|
14650
|
+
const cwd = path14__default.default.resolve(options.cwd ?? process.cwd());
|
|
14651
|
+
try {
|
|
14652
|
+
const plan = await planInit({ ...options, cwd });
|
|
14653
|
+
const toWrite = plan.files.filter((file) => file.action === "create").map((f) => f.path);
|
|
14654
|
+
const skipped = plan.files.filter((file) => file.action === "skip");
|
|
14655
|
+
if (options.json) {
|
|
14656
|
+
const payload = {
|
|
14657
|
+
ok: true,
|
|
14658
|
+
version,
|
|
14659
|
+
framework: plan.framework,
|
|
14660
|
+
ci: plan.ci ?? null,
|
|
14661
|
+
dryRun: options.dryRun === true,
|
|
14662
|
+
planned: plan.files,
|
|
14663
|
+
wouldWrite: options.dryRun ? toWrite : void 0
|
|
14664
|
+
};
|
|
14665
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
14666
|
+
if (options.dryRun) return;
|
|
14667
|
+
}
|
|
14668
|
+
const written = await writePlannedFiles(plan, cwd, options);
|
|
14669
|
+
if (!options.json) {
|
|
14670
|
+
console.log("AgentInspect init");
|
|
14671
|
+
console.log(`Framework: ${plan.framework}`);
|
|
14672
|
+
console.log(`Trace directory: ${TRACE_DIR}/`);
|
|
14673
|
+
if (options.dryRun) {
|
|
14674
|
+
console.log("Dry run \u2014 would create:");
|
|
14675
|
+
for (const file of toWrite) console.log(`- ${file}`);
|
|
14676
|
+
for (const file of skipped) {
|
|
14677
|
+
console.log(`- ${file.path} (skip: ${file.reason ?? "exists"})`);
|
|
14678
|
+
}
|
|
14679
|
+
return;
|
|
14680
|
+
}
|
|
14681
|
+
console.log("Created:");
|
|
14682
|
+
for (const file of written) console.log(`- ${file}`);
|
|
14683
|
+
for (const file of skipped) {
|
|
14684
|
+
console.log(`- ${file.path} (skipped: ${file.reason ?? "exists"})`);
|
|
14685
|
+
}
|
|
14686
|
+
console.log("\nNext: run your demo, then `npx agent-inspect list --dir .agent-inspect`");
|
|
14687
|
+
console.log("No dependencies were installed. Add packages manually when ready.");
|
|
14688
|
+
}
|
|
14689
|
+
} catch (error) {
|
|
14690
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
14691
|
+
if (options.json) {
|
|
14692
|
+
console.log(JSON.stringify({ ok: false, error: msg }, null, 2));
|
|
14693
|
+
} else {
|
|
14694
|
+
console.error(`[AgentInspect] init failed: ${msg}`);
|
|
14695
|
+
}
|
|
14696
|
+
process.exitCode = 1;
|
|
14697
|
+
}
|
|
14698
|
+
}
|
|
14699
|
+
var OPTIONAL_PACKAGES = {
|
|
14700
|
+
custom: [],
|
|
14701
|
+
"ai-sdk": ["@agent-inspect/ai-sdk"],
|
|
14702
|
+
"openai-agents": ["@agent-inspect/openai-agents"],
|
|
14703
|
+
langchain: ["@agent-inspect/langchain"]
|
|
14704
|
+
};
|
|
14705
|
+
function nodeVersionCheck() {
|
|
14706
|
+
const major = Number(process3__default.default.versions.node.split(".")[0]);
|
|
14707
|
+
if (Number.isNaN(major) || major < 20) {
|
|
14708
|
+
return {
|
|
14709
|
+
id: "node-version",
|
|
14710
|
+
status: "fail",
|
|
14711
|
+
message: `Node ${process3__default.default.versions.node} is below the supported minimum (20).`,
|
|
14712
|
+
remediation: "Upgrade to Node 20 LTS or newer.",
|
|
14713
|
+
evidence: process3__default.default.versions.node
|
|
14714
|
+
};
|
|
14715
|
+
}
|
|
14716
|
+
return {
|
|
14717
|
+
id: "node-version",
|
|
14718
|
+
status: "pass",
|
|
14719
|
+
message: `Node ${process3__default.default.versions.node} meets the minimum (>=20).`,
|
|
14720
|
+
evidence: process3__default.default.versions.node
|
|
14721
|
+
};
|
|
14722
|
+
}
|
|
14723
|
+
function envCheck(name, optional = true) {
|
|
14724
|
+
const value = process3__default.default.env[name];
|
|
14725
|
+
if (value === void 0 || value.trim() === "") {
|
|
14726
|
+
return {
|
|
14727
|
+
id: `env-${name.toLowerCase()}`,
|
|
14728
|
+
status: optional ? "skipped" : "warn",
|
|
14729
|
+
message: `${name} is not set.`,
|
|
14730
|
+
remediation: optional ? void 0 : `Set ${name}=1 to enable tracing.`
|
|
14731
|
+
};
|
|
14732
|
+
}
|
|
14733
|
+
return {
|
|
14734
|
+
id: `env-${name.toLowerCase()}`,
|
|
14735
|
+
status: "pass",
|
|
14736
|
+
message: `${name} is set.`,
|
|
14737
|
+
evidence: value
|
|
14738
|
+
};
|
|
14739
|
+
}
|
|
14740
|
+
async function traceDirWritable(traceDir) {
|
|
14741
|
+
const resolved = path14__default.default.resolve(traceDir);
|
|
14742
|
+
try {
|
|
14743
|
+
await promises.mkdir(resolved, { recursive: true });
|
|
14744
|
+
await promises.access(resolved, promises.constants.W_OK);
|
|
14745
|
+
return {
|
|
14746
|
+
id: "trace-dir-writable",
|
|
14747
|
+
status: "pass",
|
|
14748
|
+
message: `Trace directory is writable: ${resolved}`,
|
|
14749
|
+
evidence: resolved
|
|
14750
|
+
};
|
|
14751
|
+
} catch (error) {
|
|
14752
|
+
return {
|
|
14753
|
+
id: "trace-dir-writable",
|
|
14754
|
+
status: "fail",
|
|
14755
|
+
message: `Trace directory is not writable: ${resolved}`,
|
|
14756
|
+
remediation: "Create the directory or set AGENT_INSPECT_TRACE_DIR to a writable path.",
|
|
14757
|
+
evidence: error instanceof Error ? error.message : String(error)
|
|
14758
|
+
};
|
|
14759
|
+
}
|
|
14760
|
+
}
|
|
14761
|
+
function resolvePackage(cwd, name) {
|
|
14762
|
+
const require2 = module$1.createRequire(path14__default.default.join(cwd, "package.json"));
|
|
14763
|
+
try {
|
|
14764
|
+
const pkgPath = require2.resolve(`${name}/package.json`);
|
|
14765
|
+
const pkg = require2(pkgPath);
|
|
14766
|
+
return { ok: true, version: pkg.version };
|
|
14767
|
+
} catch {
|
|
14768
|
+
return { ok: false };
|
|
14769
|
+
}
|
|
14770
|
+
}
|
|
14771
|
+
function importSmoke(cwd) {
|
|
14772
|
+
const results = [];
|
|
14773
|
+
const require2 = module$1.createRequire(path14__default.default.join(cwd, "package.json"));
|
|
14774
|
+
try {
|
|
14775
|
+
require2.resolve("agent-inspect");
|
|
14776
|
+
results.push({
|
|
14777
|
+
id: "import-agent-inspect",
|
|
14778
|
+
status: "pass",
|
|
14779
|
+
message: "agent-inspect resolves from the current project."
|
|
14780
|
+
});
|
|
14781
|
+
} catch {
|
|
14782
|
+
results.push({
|
|
14783
|
+
id: "import-agent-inspect",
|
|
14784
|
+
status: "warn",
|
|
14785
|
+
message: "agent-inspect is not installed in the current project.",
|
|
14786
|
+
remediation: "Run npm install agent-inspect (or pnpm add agent-inspect)."
|
|
14787
|
+
});
|
|
14788
|
+
}
|
|
14789
|
+
try {
|
|
14790
|
+
require2.resolve("agent-inspect/package.json");
|
|
14791
|
+
results.push({
|
|
14792
|
+
id: "import-agent-inspect-cjs",
|
|
14793
|
+
status: "pass",
|
|
14794
|
+
message: "CJS resolution for agent-inspect succeeded."
|
|
14795
|
+
});
|
|
14796
|
+
} catch {
|
|
14797
|
+
results.push({
|
|
14798
|
+
id: "import-agent-inspect-cjs",
|
|
14799
|
+
status: "skipped",
|
|
14800
|
+
message: "CJS resolution check skipped (package not installed locally)."
|
|
14801
|
+
});
|
|
14802
|
+
}
|
|
14803
|
+
return results;
|
|
14804
|
+
}
|
|
14805
|
+
function optionalPackageChecks(cwd, framework) {
|
|
14806
|
+
const packages = framework !== void 0 ? OPTIONAL_PACKAGES[framework] : [
|
|
14807
|
+
"@agent-inspect/ai-sdk",
|
|
14808
|
+
"@agent-inspect/openai-agents",
|
|
14809
|
+
"@agent-inspect/langchain",
|
|
14810
|
+
"@agent-inspect/redact",
|
|
14811
|
+
"@agent-inspect/eval"
|
|
14812
|
+
];
|
|
14813
|
+
return packages.map((name) => {
|
|
14814
|
+
const resolved = resolvePackage(cwd, name);
|
|
14815
|
+
if (!resolved.ok) {
|
|
14816
|
+
return {
|
|
14817
|
+
id: `optional-package-${name}`,
|
|
14818
|
+
status: framework !== void 0 ? "warn" : "skipped",
|
|
14819
|
+
message: `${name} is not installed.`,
|
|
14820
|
+
remediation: framework !== void 0 ? `npm install ${name}` : void 0
|
|
14821
|
+
};
|
|
14822
|
+
}
|
|
14823
|
+
return {
|
|
14824
|
+
id: `optional-package-${name}`,
|
|
14825
|
+
status: "pass",
|
|
14826
|
+
message: `${name} is available.`,
|
|
14827
|
+
evidence: resolved.version
|
|
14828
|
+
};
|
|
14829
|
+
});
|
|
14830
|
+
}
|
|
14831
|
+
function versionMismatchCheck(cwd) {
|
|
14832
|
+
const root = resolvePackage(cwd, "agent-inspect");
|
|
14833
|
+
if (!root.ok || root.version === void 0) {
|
|
14834
|
+
return {
|
|
14835
|
+
id: "version-alignment",
|
|
14836
|
+
status: "skipped",
|
|
14837
|
+
message: "Skipped version alignment \u2014 agent-inspect not installed locally."
|
|
14838
|
+
};
|
|
14839
|
+
}
|
|
14840
|
+
if (root.version !== version) {
|
|
14841
|
+
return {
|
|
14842
|
+
id: "version-alignment",
|
|
14843
|
+
status: "warn",
|
|
14844
|
+
message: `CLI version ${version} differs from local agent-inspect@${root.version}.`,
|
|
14845
|
+
remediation: "Align versions with npm install agent-inspect@latest",
|
|
14846
|
+
evidence: `cli=${version};local=${root.version}`
|
|
14847
|
+
};
|
|
14848
|
+
}
|
|
14849
|
+
return {
|
|
14850
|
+
id: "version-alignment",
|
|
14851
|
+
status: "pass",
|
|
14852
|
+
message: `CLI and local agent-inspect are aligned at ${version}.`
|
|
14853
|
+
};
|
|
14854
|
+
}
|
|
14855
|
+
async function runDoctorChecks(options = {}) {
|
|
14856
|
+
const cwd = path14__default.default.resolve(options.cwd ?? process3__default.default.cwd());
|
|
14857
|
+
const traceDir = options.traceDir?.trim() || process3__default.default.env.AGENT_INSPECT_TRACE_DIR?.trim() || ".agent-inspect";
|
|
14858
|
+
const checks2 = [
|
|
14859
|
+
nodeVersionCheck(),
|
|
14860
|
+
{
|
|
14861
|
+
id: "cli-version",
|
|
14862
|
+
status: "pass",
|
|
14863
|
+
message: `agent-inspect CLI ${version}`,
|
|
14864
|
+
evidence: version
|
|
14865
|
+
},
|
|
14866
|
+
await traceDirWritable(traceDir),
|
|
14867
|
+
envCheck("AGENT_INSPECT"),
|
|
14868
|
+
envCheck("AGENT_INSPECT_TRACE_DIR"),
|
|
14869
|
+
versionMismatchCheck(cwd)
|
|
14870
|
+
];
|
|
14871
|
+
if (options.checkImports !== false) {
|
|
14872
|
+
checks2.push(...importSmoke(cwd));
|
|
14873
|
+
}
|
|
14874
|
+
checks2.push(...optionalPackageChecks(cwd, options.framework));
|
|
14875
|
+
return checks2.sort((a, b) => a.id.localeCompare(b.id));
|
|
14876
|
+
}
|
|
14877
|
+
async function doctorCommand(options = {}) {
|
|
14878
|
+
const checks2 = await runDoctorChecks(options);
|
|
14879
|
+
const failed = checks2.filter((check) => check.status === "fail").length;
|
|
14880
|
+
const warned = checks2.filter((check) => check.status === "warn").length;
|
|
14881
|
+
if (options.json) {
|
|
14882
|
+
console.log(
|
|
14883
|
+
JSON.stringify(
|
|
14884
|
+
{
|
|
14885
|
+
ok: failed === 0,
|
|
14886
|
+
version,
|
|
14887
|
+
summary: { pass: checks2.filter((c) => c.status === "pass").length, warn: warned, fail: failed },
|
|
14888
|
+
checks: checks2
|
|
14889
|
+
},
|
|
14890
|
+
null,
|
|
14891
|
+
2
|
|
14892
|
+
)
|
|
14893
|
+
);
|
|
14894
|
+
if (failed > 0) process3__default.default.exitCode = 1;
|
|
14895
|
+
return;
|
|
14896
|
+
}
|
|
14897
|
+
console.log("AgentInspect doctor");
|
|
14898
|
+
for (const check of checks2) {
|
|
14899
|
+
const tag = check.status.toUpperCase();
|
|
14900
|
+
console.log(`[${tag}] ${check.id}: ${check.message}`);
|
|
14901
|
+
if (check.remediation) console.log(` \u2192 ${check.remediation}`);
|
|
14902
|
+
}
|
|
14903
|
+
console.log(`
|
|
14904
|
+
Summary: ${failed} failed, ${warned} warnings`);
|
|
14905
|
+
if (failed > 0) process3__default.default.exitCode = 1;
|
|
14906
|
+
}
|
|
14465
14907
|
|
|
14466
14908
|
// packages/cli/src/index.ts
|
|
14467
14909
|
function runCommand(action) {
|
|
@@ -14761,6 +15203,26 @@ function createCliProgram() {
|
|
|
14761
15203
|
).action((target, opts) => {
|
|
14762
15204
|
runCommand(() => explainCommand(target, opts));
|
|
14763
15205
|
});
|
|
15206
|
+
program.command("init").description("Initialize a minimal local AgentInspect setup (no dependency install)").addOption(
|
|
15207
|
+
new commander.Option("--framework <framework>", "starter framework path").choices([
|
|
15208
|
+
"ai-sdk",
|
|
15209
|
+
"openai-agents",
|
|
15210
|
+
"langchain",
|
|
15211
|
+
"custom"
|
|
15212
|
+
])
|
|
15213
|
+
).addOption(new commander.Option("--ci <provider>", "optional CI snippet").choices(["github"])).option("--dry-run", "print planned files without writing").option("--yes", "non-interactive; skip existing files").option("--json", "print deterministic JSON plan/result").action((opts) => {
|
|
15214
|
+
runCommand(() => initCommand(opts));
|
|
15215
|
+
});
|
|
15216
|
+
program.command("doctor").description("Diagnose local AgentInspect setup (no network, no installs)").option("--json", "print deterministic JSON results").option("--trace-dir <path>", "trace directory to validate (default .agent-inspect)").option("--check-imports", "check local package resolution", true).option("--no-check-imports", "skip import resolution checks").addOption(
|
|
15217
|
+
new commander.Option("--framework <framework>", "check optional adapter packages").choices([
|
|
15218
|
+
"ai-sdk",
|
|
15219
|
+
"openai-agents",
|
|
15220
|
+
"langchain",
|
|
15221
|
+
"custom"
|
|
15222
|
+
])
|
|
15223
|
+
).action((opts) => {
|
|
15224
|
+
runCommand(() => doctorCommand(opts));
|
|
15225
|
+
});
|
|
14764
15226
|
return program;
|
|
14765
15227
|
}
|
|
14766
15228
|
function isPrimaryModule() {
|