agent-inspect 6.31.7 → 6.31.8

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.
Files changed (42) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +1 -1
  3. package/package.json +1 -1
  4. package/packages/cli/dist/{chunk-QV73NM25.mjs → chunk-6FE47XSF.mjs} +24 -11
  5. package/packages/cli/dist/chunk-6FE47XSF.mjs.map +1 -0
  6. package/packages/cli/dist/index.cjs +176 -42
  7. package/packages/cli/dist/index.cjs.map +1 -1
  8. package/packages/cli/dist/index.mjs +156 -36
  9. package/packages/cli/dist/index.mjs.map +1 -1
  10. package/packages/cli/dist/{src-KFOBXFPN.mjs → src-NXAYHG34.mjs} +3 -3
  11. package/packages/cli/dist/{src-KFOBXFPN.mjs.map → src-NXAYHG34.mjs.map} +1 -1
  12. package/packages/core/dist/advanced.cjs +22 -9
  13. package/packages/core/dist/advanced.cjs.map +1 -1
  14. package/packages/core/dist/advanced.mjs +5 -5
  15. package/packages/core/dist/checks.mjs +2 -2
  16. package/packages/core/dist/{chunk-LXYPM2ZO.mjs → chunk-2CCRUI42.mjs} +19 -318
  17. package/packages/core/dist/chunk-2CCRUI42.mjs.map +1 -0
  18. package/packages/core/dist/{chunk-QLYUWKK7.mjs → chunk-2IRRUNIN.mjs} +11 -5
  19. package/packages/core/dist/chunk-2IRRUNIN.mjs.map +1 -0
  20. package/packages/core/dist/{chunk-3RV3JILQ.mjs → chunk-IJJSPJXV.mjs} +20 -12
  21. package/packages/core/dist/chunk-IJJSPJXV.mjs.map +1 -0
  22. package/packages/core/dist/chunk-L5WLVBW4.mjs +355 -0
  23. package/packages/core/dist/chunk-L5WLVBW4.mjs.map +1 -0
  24. package/packages/core/dist/exporters.cjs +110 -18
  25. package/packages/core/dist/exporters.cjs.map +1 -1
  26. package/packages/core/dist/exporters.mjs +110 -18
  27. package/packages/core/dist/exporters.mjs.map +1 -1
  28. package/packages/core/dist/persisted.cjs +344 -9
  29. package/packages/core/dist/persisted.cjs.map +1 -1
  30. package/packages/core/dist/persisted.d.cts +8 -1
  31. package/packages/core/dist/persisted.d.ts +8 -1
  32. package/packages/core/dist/persisted.mjs +3 -2
  33. package/packages/core/dist/persisted.mjs.map +1 -1
  34. package/packages/core/dist/readers.cjs +377 -87
  35. package/packages/core/dist/readers.cjs.map +1 -1
  36. package/packages/core/dist/readers.mjs +3 -3
  37. package/packages/cli/dist/chunk-QV73NM25.mjs.map +0 -1
  38. package/packages/core/dist/chunk-3RV3JILQ.mjs.map +0 -1
  39. package/packages/core/dist/chunk-FWK3Q3OJ.mjs +0 -56
  40. package/packages/core/dist/chunk-FWK3Q3OJ.mjs.map +0 -1
  41. package/packages/core/dist/chunk-LXYPM2ZO.mjs.map +0 -1
  42. package/packages/core/dist/chunk-QLYUWKK7.mjs.map +0 -1
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { ATTRIBUTION_CONFIDENCES, createSafetyRawContentRule, createSafetyRedactionRule, createSafetySecretPatternRule, createSafetyOversizedAttributeRule, resolveTraceDir, parseDuration, buildSessionIndex, resolveBundleRunIds, getTraceFilePath, openTrace, sha256Hex, collectTraceSchemaVersions, aggregateBundleSafeStatus, bundleFailsOnSafety, bundleRunAssetRelativePath, buildPlaceholderArtifact, EVIDENCE_HTML_FILENAME, EVIDENCE_MANIFEST_FILENAME, buildBundleMetadata, buildBundleSummaryMarkdown, buildEvidenceHtmlShell, buildEvidenceProvenanceViewHtml, EVIDENCE_FORMAT_VERSION, inferEvidenceFileRole, buildEvidenceSafetyViewHtml, buildEvidenceDiffViewHtml, buildEvidenceCircuitViewHtml, buildEvidenceOutcomesViewHtml, buildEvidenceContractsViewHtml, buildEvidenceToolsLlmViewHtml, buildEvidenceCausalFailureViewHtml, buildEvidenceTimelineViewHtml, buildEvidenceTreeViewHtml, buildEvidenceManifest, serializeEvidenceManifest, buildZipArchive, assertBundlePathContained, enrichSessionRunRecord, normalizeBundleOutputPath, sanitizeBundleRunId, defaultBundleOutputPath, runTraceChecks, assertEvidenceRelativePath, TraceDirectory, loadTraceMetadataList, loadSessionRunRecords, TraceReadError, resolveRedactionProfile, applyProfileMetadataCaps, Redactor, flattenTree, escapeHtml, safeString, compactAttributes, stableJson, escapeMarkdown, DEFAULT_REDACT_KEYS, truncateStringForProfile, stringContainsHighConfidenceCredential, isCredentialSensitiveKey, extractMetadata, filterTraces, truncateName, buildRunSummary, formatDuration, formatTimestamp, renderErrorLine, isAgentInspectTrace, persistedInspectEventsToRunTrees, defineTraceContract, filterMetasBySessionScope, evaluateTraceContract, aggregateSessionCheckResults, createBaselineRegressionRule, summarizeSemanticParity, buildEvidenceCiPackage, verifyEvidenceDirectory, diffTraceEvents, renderRunDiff, buildRunTimeline, renderTimeline, buildTraceStats, renderTraceStats, parseDurationFilter, searchTraces, formatStepLabel, buildActivitySummary, renderActivitySummaryHuman, buildRunWhatSummary, renderRunWhat, buildLocalExplanation, resolveSuiteTemplate, defaultSuiteConfigTemplate, loadSuiteConfig, validateSuiteConfig, runSuite, renderSuiteReport, analyzeCohort, renderCohortReport, gateHasThresholds, runGate, renderGateReport, persistedInspectEventsToTraceEvents, renderStepLine, getIndent, TreeBuilder, validateEvent, traceEventToPersistedInspectEvent, isPersistedInspectEvent, createRunStatusRule, createStructureOrphanRule, createStructureCycleRule, createRunDurationRule, createMaxStepDurationRule, createRequireCompletedRule, createStallDetectionRule, createObservedOutcomeRule, createRunDepthRule, createToolUsageRule, createLlmUsageRule, createStructureRelationshipRule, createStructureParallelWidthRule, projectLogicalEvents, summarizeObservedOutcomes, extractOutcomesFromTraceEvents, renderObservedOutcomesMarkdown, renderObservedOutcomesHtml, DEFAULT_SUITE_ARTIFACTS_DIR, parseCohortMetricList, COHORT_METRIC_IDS, parseGateList, nanoid, isAttributionConfidence, zeroKinds, diffRuns, manualTraceEventsToComparableRun } from './chunk-QV73NM25.mjs';
2
+ import { ATTRIBUTION_CONFIDENCES, createSafetyRawContentRule, createSafetyRedactionRule, createSafetySecretPatternRule, createSafetyOversizedAttributeRule, resolveTraceDir, parseDuration, buildSessionIndex, resolveBundleRunIds, getTraceFilePath, openTrace, sha256Hex, collectTraceSchemaVersions, aggregateBundleSafeStatus, bundleFailsOnSafety, bundleRunAssetRelativePath, buildPlaceholderArtifact, EVIDENCE_HTML_FILENAME, EVIDENCE_MANIFEST_FILENAME, buildBundleMetadata, buildBundleSummaryMarkdown, buildEvidenceHtmlShell, buildEvidenceProvenanceViewHtml, EVIDENCE_FORMAT_VERSION, inferEvidenceFileRole, buildEvidenceSafetyViewHtml, buildEvidenceDiffViewHtml, buildEvidenceCircuitViewHtml, buildEvidenceOutcomesViewHtml, buildEvidenceContractsViewHtml, buildEvidenceToolsLlmViewHtml, buildEvidenceCausalFailureViewHtml, buildEvidenceTimelineViewHtml, buildEvidenceTreeViewHtml, buildEvidenceManifest, serializeEvidenceManifest, buildZipArchive, assertBundlePathContained, enrichSessionRunRecord, normalizeBundleOutputPath, sanitizeBundleRunId, defaultBundleOutputPath, runTraceChecks, assertEvidenceRelativePath, TraceDirectory, loadTraceMetadataList, loadSessionRunRecords, TraceReadError, resolveRedactionProfile, applyProfileMetadataCaps, Redactor, flattenTree, escapeHtml, safeString, compactAttributes, stableJson, escapeMarkdown, DEFAULT_REDACT_KEYS, truncateStringForProfile, stringContainsHighConfidenceCredential, isCredentialSensitiveKey, extractMetadata, filterTraces, truncateName, buildRunSummary, formatDuration, formatTimestamp, renderErrorLine, isAgentInspectTrace, persistedInspectEventsToRunTrees, defineTraceContract, filterMetasBySessionScope, evaluateTraceContract, aggregateSessionCheckResults, createBaselineRegressionRule, summarizeSemanticParity, buildEvidenceCiPackage, verifyEvidenceDirectory, diffTraceEvents, renderRunDiff, buildRunTimeline, renderTimeline, buildTraceStats, renderTraceStats, parseDurationFilter, searchTraces, formatStepLabel, buildActivitySummary, renderActivitySummaryHuman, buildRunWhatSummary, renderRunWhat, buildLocalExplanation, resolveSuiteTemplate, defaultSuiteConfigTemplate, loadSuiteConfig, validateSuiteConfig, runSuite, renderSuiteReport, analyzeCohort, renderCohortReport, gateHasThresholds, runGate, renderGateReport, persistedInspectEventsToTraceEvents, renderStepLine, getIndent, TreeBuilder, validateEvent, traceEventToPersistedInspectEvent, isPersistedInspectEvent, createRunStatusRule, createStructureOrphanRule, createStructureCycleRule, createRunDurationRule, createMaxStepDurationRule, createRequireCompletedRule, createStallDetectionRule, createObservedOutcomeRule, createRunDepthRule, createToolUsageRule, createLlmUsageRule, createStructureRelationshipRule, createStructureParallelWidthRule, projectLogicalEvents, summarizeObservedOutcomes, extractOutcomesFromTraceEvents, renderObservedOutcomesMarkdown, renderObservedOutcomesHtml, DEFAULT_SUITE_ARTIFACTS_DIR, parseCohortMetricList, COHORT_METRIC_IDS, parseGateList, nanoid, isAttributionConfidence, zeroKinds, diffRuns, manualTraceEventsToComparableRun } from './chunk-6FE47XSF.mjs';
3
3
  import { realpathSync, constants as constants$1, existsSync, readFileSync } from 'fs';
4
4
  import path19 from 'path';
5
5
  import { fileURLToPath, pathToFileURL } from 'url';
@@ -14,7 +14,7 @@ import { createServer } from 'http';
14
14
  import { createRequire } from 'module';
15
15
 
16
16
  // package.json
17
- var version = "6.31.7";
17
+ var version = "6.31.8";
18
18
 
19
19
  // packages/cli/src/trace-dir-scale.ts
20
20
  var TRACE_COUNT_WARN = 1e3;
@@ -2496,11 +2496,13 @@ function exportOpenInference(tree, options) {
2496
2496
  endNs = startNs + unixNano(ev.durationMs);
2497
2497
  }
2498
2498
  const { openInferenceKind } = mapInspectKindToOI(ev.kind, warnings);
2499
+ const meta = ev.attributes;
2500
+ const originalSource = typeof meta?.originalSourceType === "string" && meta.originalSourceType.trim() !== "" ? meta.originalSourceType.trim() : ev.source.type;
2499
2501
  const attrs = {
2500
2502
  "openinference.span.kind": openInferenceKind,
2501
2503
  "agent_inspect.kind": ev.kind,
2502
2504
  "agent_inspect.confidence": ev.confidence,
2503
- "agent_inspect.source.type": ev.source.type,
2505
+ "agent_inspect.source.type": originalSource,
2504
2506
  "agent_inspect.run_id": tree.runId,
2505
2507
  "agent_inspect.event_id": ev.eventId,
2506
2508
  "agent_inspect.status": ev.status ?? "unset"
@@ -2508,9 +2510,9 @@ function exportOpenInference(tree, options) {
2508
2510
  if (ev.durationMs !== void 0) {
2509
2511
  attrs["agent_inspect.duration_ms"] = ev.durationMs;
2510
2512
  }
2511
- const meta = ev.attributes;
2512
- if (meta?.model !== void 0 && typeof meta.model === "string") {
2513
- attrs["llm.model_name"] = meta.model;
2513
+ const requestModel = (typeof meta?.model === "string" && meta.model.trim() !== "" ? meta.model : void 0) ?? (typeof meta?.modelId === "string" && meta.modelId.trim() !== "" ? meta.modelId : void 0);
2514
+ if (requestModel !== void 0) {
2515
+ attrs["llm.model_name"] = requestModel;
2514
2516
  }
2515
2517
  const tokens = meta?.tokens;
2516
2518
  if (tokens && typeof tokens === "object" && tokens !== null) {
@@ -2520,8 +2522,9 @@ function exportOpenInference(tree, options) {
2520
2522
  if (typeof outp === "number") attrs["llm.token_count.completion"] = outp;
2521
2523
  }
2522
2524
  if (includeAttributes && meta && typeof meta === "object") {
2525
+ const skipKeys = /* @__PURE__ */ new Set(["tokens", "model", "modelId", "originalSourceType"]);
2523
2526
  for (const [k, v] of Object.entries(meta)) {
2524
- if (k === "tokens" || k === "model") continue;
2527
+ if (skipKeys.has(k)) continue;
2525
2528
  if (v !== void 0 && v !== null && typeof v !== "object") {
2526
2529
  attrs[`agent_inspect.preview.${k}`] = typeof v === "string" ? v.slice(0, maxLen) : v;
2527
2530
  }
@@ -2639,24 +2642,33 @@ function exportOtlpJson(tree, options) {
2639
2642
  const spanId = hexFrom2(`${tree.runId}:${ev.eventId}`, 8);
2640
2643
  const parentSpanId = ev.parentId ? hexFrom2(`${tree.runId}:${ev.parentId}`, 8) : void 0;
2641
2644
  const { startNs, endNs } = resolveSpanTimes(ev);
2645
+ const meta = ev.attributes;
2646
+ const originalSource = typeof meta?.originalSourceType === "string" && meta.originalSourceType.trim() !== "" ? meta.originalSourceType.trim() : ev.source.type;
2642
2647
  const attrs = [
2643
2648
  stringAttr("agent_inspect.kind", ev.kind),
2644
2649
  stringAttr("agent_inspect.confidence", ev.confidence),
2645
- stringAttr("agent_inspect.source.type", ev.source.type),
2650
+ stringAttr("agent_inspect.source.type", originalSource),
2646
2651
  stringAttr("agent_inspect.run_id", tree.runId),
2647
2652
  stringAttr("agent_inspect.event_id", ev.eventId),
2648
2653
  stringAttr("agent_inspect.status", ev.status ?? "unset")
2649
2654
  ];
2650
2655
  if (ev.durationMs !== void 0) {
2651
- attrs.push(intAttr("agent_inspect.duration_ms", ev.durationMs));
2656
+ attrs.push(numberAttr("agent_inspect.duration_ms", ev.durationMs));
2652
2657
  }
2653
2658
  const op = genAiOperationName(ev.kind);
2654
2659
  if (op !== void 0) {
2655
2660
  attrs.push(stringAttr("gen_ai.operation.name", op));
2656
2661
  }
2657
- const meta = ev.attributes;
2658
- if (meta?.model !== void 0 && typeof meta.model === "string") {
2659
- attrs.push(stringAttr("gen_ai.request.model", meta.model.slice(0, maxLen)));
2662
+ const requestModel = (typeof meta?.model === "string" && meta.model.trim() !== "" ? meta.model : void 0) ?? (typeof meta?.modelId === "string" && meta.modelId.trim() !== "" ? meta.modelId : void 0);
2663
+ if (requestModel !== void 0) {
2664
+ attrs.push(stringAttr("gen_ai.request.model", requestModel.slice(0, maxLen)));
2665
+ }
2666
+ const responseModel = typeof meta?.responseModelId === "string" && meta.responseModelId.trim() !== "" ? meta.responseModelId : typeof meta?.responseModel === "string" && meta.responseModel.trim() !== "" ? meta.responseModel : void 0;
2667
+ if (responseModel !== void 0) {
2668
+ attrs.push(stringAttr("gen_ai.response.model", responseModel.slice(0, maxLen)));
2669
+ }
2670
+ if (typeof meta?.provider === "string" && meta.provider.trim() !== "") {
2671
+ attrs.push(stringAttr("gen_ai.provider.name", meta.provider.slice(0, maxLen)));
2660
2672
  }
2661
2673
  const tokens = meta?.tokens;
2662
2674
  if (tokens && typeof tokens === "object" && tokens !== null) {
@@ -2666,8 +2678,17 @@ function exportOtlpJson(tree, options) {
2666
2678
  if (typeof outp === "number") attrs.push(intAttr("gen_ai.usage.output_tokens", outp));
2667
2679
  }
2668
2680
  if (includeAttributes && meta && typeof meta === "object") {
2681
+ const skipKeys = /* @__PURE__ */ new Set([
2682
+ "tokens",
2683
+ "model",
2684
+ "modelId",
2685
+ "responseModel",
2686
+ "responseModelId",
2687
+ "provider",
2688
+ "originalSourceType"
2689
+ ]);
2669
2690
  for (const [k, v] of Object.entries(meta)) {
2670
- if (k === "tokens" || k === "model") continue;
2691
+ if (skipKeys.has(k)) continue;
2671
2692
  if (typeof v === "string") {
2672
2693
  attrs.push(stringAttr(`agent_inspect.preview.${k}`, v.slice(0, maxLen)));
2673
2694
  } else if (typeof v === "number" && Number.isFinite(v)) {
@@ -2737,12 +2758,42 @@ function pushPath(errors, path30, message) {
2737
2758
  function isRecord5(value) {
2738
2759
  return value !== null && typeof value === "object" && !Array.isArray(value);
2739
2760
  }
2761
+ function isHexId(value, byteLen) {
2762
+ return typeof value === "string" && new RegExp(`^[0-9a-fA-F]{${byteLen * 2}}$`).test(value);
2763
+ }
2764
+ function validateAnyValue(errors, path30, value) {
2765
+ if (!isRecord5(value)) {
2766
+ pushPath(errors, path30, "must be an AnyValue object");
2767
+ return;
2768
+ }
2769
+ const variants = [
2770
+ "stringValue",
2771
+ "boolValue",
2772
+ "intValue",
2773
+ "doubleValue",
2774
+ "bytesValue",
2775
+ "arrayValue",
2776
+ "kvlistValue"
2777
+ ].filter((key) => value[key] !== void 0);
2778
+ if (variants.length !== 1) {
2779
+ pushPath(
2780
+ errors,
2781
+ path30,
2782
+ `AnyValue must set exactly one variant (found ${variants.length}: ${variants.join(",")})`
2783
+ );
2784
+ }
2785
+ if (value.intValue !== void 0) {
2786
+ if (typeof value.intValue !== "string" || !/^-?\d+$/.test(value.intValue)) {
2787
+ pushPath(errors, `${path30}.intValue`, "must be a decimal integer string");
2788
+ }
2789
+ }
2790
+ }
2740
2791
  function validateOtlpJson(content) {
2741
2792
  const errors = [];
2742
2793
  const warnings = [
2743
2794
  EXPERIMENTAL,
2744
2795
  "OTLP JSON mapping uses OTel GenAI-aligned attributes where applicable; collectors may require transformation.",
2745
- "protocol-valid \u2260 profile-complete \u2260 fixture-complete \u2014 nested path diagnostics report protocol shape only."
2796
+ "producer-profile checks IDs, timing, and AnyValue shape; historical string enums are reader-compat warnings only."
2746
2797
  ];
2747
2798
  let parsed;
2748
2799
  try {
@@ -2785,11 +2836,26 @@ function validateOtlpJson(content) {
2785
2836
  pushPath(errors, spanPath, "must be an object");
2786
2837
  return;
2787
2838
  }
2788
- if (typeof span.traceId !== "string" || span.traceId.length === 0) {
2789
- pushPath(errors, `${spanPath}.traceId`, "must be a non-empty string");
2839
+ if (!isHexId(span.traceId, 16)) {
2840
+ pushPath(
2841
+ errors,
2842
+ `${spanPath}.traceId`,
2843
+ "must be a 32-char hex trace id (16 bytes)"
2844
+ );
2790
2845
  }
2791
- if (typeof span.spanId !== "string" || span.spanId.length === 0) {
2792
- pushPath(errors, `${spanPath}.spanId`, "must be a non-empty string");
2846
+ if (!isHexId(span.spanId, 8)) {
2847
+ pushPath(
2848
+ errors,
2849
+ `${spanPath}.spanId`,
2850
+ "must be a 16-char hex span id (8 bytes)"
2851
+ );
2852
+ }
2853
+ if (span.parentSpanId !== void 0 && !isHexId(span.parentSpanId, 8)) {
2854
+ pushPath(
2855
+ errors,
2856
+ `${spanPath}.parentSpanId`,
2857
+ "must be a 16-char hex span id when present"
2858
+ );
2793
2859
  }
2794
2860
  if (typeof span.name !== "string") {
2795
2861
  pushPath(errors, `${spanPath}.name`, "must be a string");
@@ -2808,13 +2874,39 @@ function validateOtlpJson(content) {
2808
2874
  "must be a decimal-string 64-bit integer when present"
2809
2875
  );
2810
2876
  }
2877
+ if (typeof span.startTimeUnixNano === "string" && /^\d+$/.test(span.startTimeUnixNano) && typeof span.endTimeUnixNano === "string" && /^\d+$/.test(span.endTimeUnixNano)) {
2878
+ try {
2879
+ if (BigInt(span.endTimeUnixNano) < BigInt(span.startTimeUnixNano)) {
2880
+ pushPath(
2881
+ errors,
2882
+ `${spanPath}.endTimeUnixNano`,
2883
+ "must be >= startTimeUnixNano"
2884
+ );
2885
+ }
2886
+ } catch {
2887
+ pushPath(errors, `${spanPath}.endTimeUnixNano`, "out of integer range");
2888
+ }
2889
+ }
2890
+ if (Array.isArray(span.attributes)) {
2891
+ span.attributes.forEach((attr, ai) => {
2892
+ const attrPath = `${spanPath}.attributes[${ai}]`;
2893
+ if (!isRecord5(attr)) {
2894
+ pushPath(errors, attrPath, "must be an object");
2895
+ return;
2896
+ }
2897
+ if (typeof attr.key !== "string") {
2898
+ pushPath(errors, `${attrPath}.key`, "must be a string");
2899
+ }
2900
+ validateAnyValue(errors, `${attrPath}.value`, attr.value);
2901
+ });
2902
+ }
2811
2903
  if (typeof span.kind === "number") {
2812
2904
  if (!Number.isInteger(span.kind)) {
2813
2905
  pushPath(errors, `${spanPath}.kind`, "must be an integer SpanKind enum");
2814
2906
  }
2815
2907
  } else if (typeof span.kind === "string") {
2816
2908
  warnings.push(
2817
- `${spanPath}.kind: string SpanKind enum is legacy; prefer numeric (INTERNAL=1)`
2909
+ `${spanPath}.kind: string SpanKind is historical reader-compat only; producer wire format uses numeric enums`
2818
2910
  );
2819
2911
  } else if (span.kind !== void 0) {
2820
2912
  pushPath(
@@ -2845,7 +2937,7 @@ function validateOtlpJson(content) {
2845
2937
  );
2846
2938
  } else {
2847
2939
  warnings.push(
2848
- `${spanPath}.status.code: string StatusCode is legacy; prefer numeric 0/1/2`
2940
+ `${spanPath}.status.code: string StatusCode is historical reader-compat only; producer wire format uses numeric 0/1/2`
2849
2941
  );
2850
2942
  }
2851
2943
  } else {
@@ -3315,7 +3407,9 @@ Trace directory: ${traceDir}`);
3315
3407
  }
3316
3408
  let tree;
3317
3409
  try {
3318
- const trees = persistedInspectEventsToRunTrees(events);
3410
+ const trees = persistedInspectEventsToRunTrees(events, {
3411
+ coalesceLifecycle: true
3412
+ });
3319
3413
  tree = trees.find((candidate) => candidate.runId === id) ?? trees[0];
3320
3414
  if (tree === void 0) {
3321
3415
  throw new Error("No run tree could be built from persisted events");
@@ -3721,7 +3815,7 @@ async function newestTraceMtimeMs(traceDir) {
3721
3815
  }
3722
3816
  async function loadSessionRuns(traceDir) {
3723
3817
  try {
3724
- const mod = await import('./src-KFOBXFPN.mjs');
3818
+ const mod = await import('./src-NXAYHG34.mjs');
3725
3819
  const dbPath = mod.resolveIndexDbPath(traceDir);
3726
3820
  const status = mod.indexStatus(dbPath);
3727
3821
  if (!status.healthy) {
@@ -12552,13 +12646,15 @@ import { generateText, stepCountIs, tool } from "ai";
12552
12646
  import { MockLanguageModelV3 } from "ai/test";
12553
12647
  import { agentInspect } from "@agent-inspect/ai-sdk";
12554
12648
  import { z } from "zod";
12555
- import { readdirSync, readFileSync } from "node:fs";
12649
+ import { mkdirSync, readdirSync, readFileSync, rmSync } from "node:fs";
12556
12650
  import path from "node:path";
12651
+ import { randomUUID } from "node:crypto";
12557
12652
 
12558
- const TRACE_DIR = ".agent-inspect";
12653
+ const SESSION = randomUUID().slice(0, 8);
12654
+ const TRACE_DIR = path.join(".agent-inspect", \`demo-\${SESSION}\`);
12559
12655
  const ANSWER = "You have 2 orders";
12560
- const CORRECT_RUN = "ai-sdk-demo-correct";
12561
- const WRONG_RUN = "ai-sdk-demo-wrong";
12656
+ const CORRECT_RUN = \`ai-sdk-demo-correct-\${SESSION}\`;
12657
+ const WRONG_RUN = \`ai-sdk-demo-wrong-\${SESSION}\`;
12562
12658
 
12563
12659
  const usage = {
12564
12660
  inputTokens: { total: 4, noCache: 4, cacheRead: 0, cacheWrite: 0 },
@@ -12598,7 +12694,7 @@ async function runPath(runName, toolName) {
12598
12694
  type: "tool-call",
12599
12695
  toolCallId: \`call-\${toolName}\`,
12600
12696
  toolName,
12601
- input: { userId: "u1" },
12697
+ input: JSON.stringify({ userId: "u1" }),
12602
12698
  },
12603
12699
  ],
12604
12700
  finishReason: { unified: "tool-calls", raw: "tool-calls" },
@@ -12650,15 +12746,39 @@ function selectRunIdByName(runName) {
12650
12746
  return matches[0];
12651
12747
  }
12652
12748
 
12749
+ function assertToolExecuted(runId, requiredTool) {
12750
+ const text = readFileSync(path.join(TRACE_DIR, \`\${runId}.jsonl\`), "utf8");
12751
+ const toolHits = text
12752
+ .split("\\n")
12753
+ .filter(Boolean)
12754
+ .map((line) => JSON.parse(line))
12755
+ .filter(
12756
+ (ev) =>
12757
+ (ev.kind === "TOOL" || ev.attributes?.stepType === "tool") &&
12758
+ (ev.name === requiredTool || ev.attributes?.toolName === requiredTool),
12759
+ );
12760
+ if (toolHits.length === 0) {
12761
+ throw new Error(\`expected TOOL events for \${requiredTool} in \${runId}\`);
12762
+ }
12763
+ }
12764
+
12653
12765
  async function main() {
12654
- await runPath(CORRECT_RUN, "lookup_orders");
12655
- await runPath(WRONG_RUN, "delete_orders");
12656
- const correctId = selectRunIdByName(CORRECT_RUN);
12657
- const wrongId = selectRunIdByName(WRONG_RUN);
12658
- console.log("Trace written to .agent-inspect/");
12659
- console.log(\`Correct path runId: \${correctId}\`);
12660
- console.log(\`Wrong path runId: \${wrongId}\`);
12661
- console.log(\`Next: npx agent-inspect check \${correctId} --required-tool lookup_orders\`);
12766
+ mkdirSync(TRACE_DIR, { recursive: true });
12767
+ try {
12768
+ await runPath(CORRECT_RUN, "lookup_orders");
12769
+ await runPath(WRONG_RUN, "delete_orders");
12770
+ const correctId = selectRunIdByName(CORRECT_RUN);
12771
+ const wrongId = selectRunIdByName(WRONG_RUN);
12772
+ assertToolExecuted(correctId, "lookup_orders");
12773
+ assertToolExecuted(wrongId, "delete_orders");
12774
+ console.log(\`Trace written to \${TRACE_DIR}/\`);
12775
+ console.log(\`Correct path runId: \${correctId}\`);
12776
+ console.log(\`Wrong path runId: \${wrongId}\`);
12777
+ console.log(\`Next: npx agent-inspect check \${correctId} --dir \${TRACE_DIR} --required-tool lookup_orders\`);
12778
+ } catch (error) {
12779
+ rmSync(TRACE_DIR, { recursive: true, force: true });
12780
+ throw error;
12781
+ }
12662
12782
  }
12663
12783
 
12664
12784
  main().catch((error) => {
@@ -13651,7 +13771,7 @@ function isModuleNotFound4(e) {
13651
13771
  }
13652
13772
  async function loadIndexSqlite() {
13653
13773
  try {
13654
- return await import('./src-KFOBXFPN.mjs');
13774
+ return await import('./src-NXAYHG34.mjs');
13655
13775
  } catch (e) {
13656
13776
  if (isModuleNotFound4(e)) {
13657
13777
  console.error(