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.
@@ -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 process2 = require('process');
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 process2__default = /*#__PURE__*/_interopDefault(process2);
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.0.0";
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 : process2__default.default.argv) {
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 } = process2__default.default;
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 (process2__default.default.platform === "win32") {
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 path16 = [];
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
- path16.push({
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 path16;
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: process2.stdin, output: process2.stdout });
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 (process2.stdin.isTTY !== true) {
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: process2.stdin, crlfDelay: Infinity });
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 path16 = buildPath(segments);
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: path16,
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: path16,
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: path16,
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: path16,
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: path16,
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: path16,
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: path16,
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(path16) {
8588
- if (path16 === void 0 || path16.path.length === 0) {
8588
+ function formatPath(path18) {
8589
+ if (path18 === void 0 || path18.path.length === 0) {
8589
8590
  return "(run)";
8590
8591
  }
8591
- return path16.path.map((s) => s.name).join(" > ");
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(path16, key) {
9470
+ function childPath(path18, key) {
9470
9471
  if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key)) {
9471
- return path16 ? `${path16}.${key}` : key;
9472
+ return path18 ? `${path18}.${key}` : key;
9472
9473
  }
9473
- return `${path16 || "$"}[${JSON.stringify(key)}]`;
9474
+ return `${path18 || "$"}[${JSON.stringify(key)}]`;
9474
9475
  }
9475
- function indexPath(path16, index) {
9476
- return `${path16 || "$"}[${index}]`;
9476
+ function indexPath(path18, index) {
9477
+ return `${path18 || "$"}[${index}]`;
9477
9478
  }
9478
- function makeFinding(path16, detector, action, matchKind, severity = "warning", preview) {
9479
- return preview === void 0 ? { path: path16, detector, action, severity, matchKind } : { path: path16, detector, action, severity, matchKind, preview };
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, path16, depth, state) {
9549
+ #redactValue(value, key, path18, depth, state) {
9549
9550
  if (depth > this.#maxDepth) {
9550
9551
  this.#recordFinding(
9551
9552
  state,
9552
- makeFinding(path16, "structure.maxDepth", "truncate", "value", "warning")
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(path16, `key.${rule.key}`, actionForRule(rule), "key", "warning")
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: path16, key, value });
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
- path16,
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(path16, index), depth + 1, state);
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(path16 === "$" ? "" : path16, entryKey),
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, path16) {
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
- ...path16 ? { path: path16 } : {}
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(path16) {
10549
- const parts = path16.split(".");
10550
- return parts[parts.length - 1] ?? path16;
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, path16, key, depth = 0) {
10565
- entries.push({ event, path: path16, key, value });
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, `${path16}.${index}`, String(index), depth + 1);
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
- `${path16}.${nestedKey}`,
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, path16) => {
10661
- lines.push(`${path16}:${node.event.kind}:${node.event.name}:${node.event.status ?? "unknown"}`);
10662
- node.children.forEach((child, index) => visit(child, `${path16}.${index}`));
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, path16) {
10712
+ function firstEvidenceForKind(context, kind, path18) {
10712
10713
  const event = context.events.find((candidate) => candidate.kind === kind);
10713
- return event ? [eventEvidence(event, path16)] : runEvidence(context.selectedRun);
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 path16 = [];
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 = path16.slice(existing);
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, path16.length);
10984
- path16.push(current);
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, path16, evidence) {
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: path16, preview: `expected ${field.type}, got ${actual}` });
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: path16, preview: "value not in enum" });
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: `${path16}.${key}`, preview: "missing required key" });
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 path16 = finding.evidence[0]?.path;
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}${path16 ? ` (${path16})` : ""}`);
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, path16) {
12804
- return [{ runId: run.runId, ...path16 !== void 0 ? { path: path16 } : {} }];
12804
+ function evidenceForRun(run, path18) {
12805
+ return [{ runId: run.runId, ...path18 !== void 0 ? { path: path18 } : {} }];
12805
12806
  }
12806
- function evidenceForEvent(event, path16) {
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
- ...path16 !== void 0 ? { path: path16 } : {}
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, path16) {
12973
+ function firstEvidence(fields, run, path18) {
12973
12974
  const first = fields[0];
12974
- return first === void 0 ? evidenceForRun(run, path16) : evidenceForEvent(first.node.event, first.path);
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 path16 = finding.evidence[0]?.path;
13352
- lines.push(`- ${finding.ruleId}: ${finding.message}${path16 ? ` (${path16})` : ""}`);
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 path16 = finding.evidence[0]?.path;
13546
- console.log(`- ${finding.ruleId}: ${finding.message}${path16 ? ` (${path16})` : ""}`);
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 path16 = finding.evidence[0]?.path;
13785
- console.log(`- ${finding.ruleId}: ${finding.message}${path16 ? ` (${path16})` : ""}`);
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 path16 = finding.evidence[0]?.path ?? "(run)";
13905
- lines.push(`- ${finding.ruleId}: ${finding.message} (${path16})`);
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() {