agent-inspect 6.31.6 → 6.31.7
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 +7 -0
- package/README.md +1 -1
- package/docs/AI-SDK-ADOPTION.md +62 -34
- package/package.json +1 -1
- package/packages/cli/dist/{chunk-YXDNWHNJ.mjs → chunk-QV73NM25.mjs} +97 -25
- package/packages/cli/dist/chunk-QV73NM25.mjs.map +1 -0
- package/packages/cli/dist/index.cjs +414 -81
- package/packages/cli/dist/index.cjs.map +1 -1
- package/packages/cli/dist/index.mjs +322 -62
- package/packages/cli/dist/index.mjs.map +1 -1
- package/packages/cli/dist/{src-H22KNWAZ.mjs → src-KFOBXFPN.mjs} +3 -3
- package/packages/cli/dist/{src-H22KNWAZ.mjs.map → src-KFOBXFPN.mjs.map} +1 -1
- package/packages/core/dist/advanced.cjs +94 -22
- package/packages/core/dist/advanced.cjs.map +1 -1
- package/packages/core/dist/advanced.mjs +4 -4
- package/packages/core/dist/{chunk-OSGNGRHF.mjs → chunk-3RV3JILQ.mjs} +34 -16
- package/packages/core/dist/chunk-3RV3JILQ.mjs.map +1 -0
- package/packages/core/dist/{chunk-EXGQLMVB.mjs → chunk-7YYS742B.mjs} +49 -12
- package/packages/core/dist/chunk-7YYS742B.mjs.map +1 -0
- package/packages/core/dist/{chunk-Q5SLKV2Y.mjs → chunk-QLYUWKK7.mjs} +19 -2
- package/packages/core/dist/chunk-QLYUWKK7.mjs.map +1 -0
- package/packages/core/dist/exporters.cjs +224 -47
- package/packages/core/dist/exporters.cjs.map +1 -1
- package/packages/core/dist/exporters.mjs +178 -38
- package/packages/core/dist/exporters.mjs.map +1 -1
- package/packages/core/dist/persisted.cjs +17 -0
- package/packages/core/dist/persisted.cjs.map +1 -1
- package/packages/core/dist/persisted.mjs +2 -2
- package/packages/core/dist/readers.cjs +48 -13
- package/packages/core/dist/readers.cjs.map +1 -1
- package/packages/core/dist/readers.mjs +2 -2
- package/packages/cli/dist/chunk-YXDNWHNJ.mjs.map +0 -1
- package/packages/core/dist/chunk-EXGQLMVB.mjs.map +0 -1
- package/packages/core/dist/chunk-OSGNGRHF.mjs.map +0 -1
- package/packages/core/dist/chunk-Q5SLKV2Y.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, 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,
|
|
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';
|
|
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.
|
|
17
|
+
var version = "6.31.7";
|
|
18
18
|
|
|
19
19
|
// packages/cli/src/trace-dir-scale.ts
|
|
20
20
|
var TRACE_COUNT_WARN = 1e3;
|
|
@@ -333,7 +333,7 @@ function mapReaderFormat(format) {
|
|
|
333
333
|
function isMissingFileError(error) {
|
|
334
334
|
return error !== null && typeof error === "object" && "code" in error && error.code === "ENOENT";
|
|
335
335
|
}
|
|
336
|
-
async function
|
|
336
|
+
async function readRunPersistedEvents(runId, traceDir) {
|
|
337
337
|
const filePath = getTraceFilePath(runId, traceDir);
|
|
338
338
|
try {
|
|
339
339
|
await access(filePath);
|
|
@@ -341,16 +341,24 @@ async function readRunTraceEvents(runId, traceDir) {
|
|
|
341
341
|
{ type: "file", path: filePath },
|
|
342
342
|
{ format: "agent-inspect-jsonl" }
|
|
343
343
|
);
|
|
344
|
-
const events = persistedInspectEventsToTraceEvents(result.events);
|
|
345
344
|
return {
|
|
346
|
-
events,
|
|
347
|
-
format: events.length > 0 ? mapReaderFormat(result.format) : "empty"
|
|
345
|
+
events: result.events,
|
|
346
|
+
format: result.events.length > 0 ? mapReaderFormat(result.format) : "empty"
|
|
348
347
|
};
|
|
349
348
|
} catch (error) {
|
|
350
349
|
if (isMissingFileError(error)) return void 0;
|
|
351
350
|
throw error;
|
|
352
351
|
}
|
|
353
352
|
}
|
|
353
|
+
async function readRunTraceEvents(runId, traceDir) {
|
|
354
|
+
const persisted = await readRunPersistedEvents(runId, traceDir);
|
|
355
|
+
if (persisted === void 0) return void 0;
|
|
356
|
+
const events = persistedInspectEventsToTraceEvents(persisted.events);
|
|
357
|
+
return {
|
|
358
|
+
events,
|
|
359
|
+
format: events.length > 0 ? persisted.format : "empty"
|
|
360
|
+
};
|
|
361
|
+
}
|
|
354
362
|
|
|
355
363
|
// packages/cli/src/view.ts
|
|
356
364
|
function isModuleNotFound(e) {
|
|
@@ -2556,6 +2564,10 @@ function exportOpenInference(tree, options) {
|
|
|
2556
2564
|
warnings
|
|
2557
2565
|
};
|
|
2558
2566
|
}
|
|
2567
|
+
var OTLP_STATUS_CODE_UNSET = 0;
|
|
2568
|
+
var OTLP_STATUS_CODE_OK = 1;
|
|
2569
|
+
var OTLP_STATUS_CODE_ERROR = 2;
|
|
2570
|
+
var OTLP_SPAN_KIND_INTERNAL = 1;
|
|
2559
2571
|
function hexFrom2(seed, byteLen) {
|
|
2560
2572
|
return crypto.createHash("sha256").update(seed, "utf8").digest("hex").slice(0, byteLen * 2);
|
|
2561
2573
|
}
|
|
@@ -2568,7 +2580,19 @@ function stringAttr(key, value) {
|
|
|
2568
2580
|
return { key, value: { stringValue: value } };
|
|
2569
2581
|
}
|
|
2570
2582
|
function intAttr(key, value) {
|
|
2571
|
-
return { key, value: { intValue: String(value) } };
|
|
2583
|
+
return { key, value: { intValue: String(Math.trunc(value)) } };
|
|
2584
|
+
}
|
|
2585
|
+
function doubleAttr(key, value) {
|
|
2586
|
+
return { key, value: { doubleValue: value } };
|
|
2587
|
+
}
|
|
2588
|
+
function boolAttr(key, value) {
|
|
2589
|
+
return { key, value: { boolValue: value } };
|
|
2590
|
+
}
|
|
2591
|
+
function numberAttr(key, value) {
|
|
2592
|
+
if (Number.isFinite(value) && !Number.isInteger(value)) {
|
|
2593
|
+
return doubleAttr(key, value);
|
|
2594
|
+
}
|
|
2595
|
+
return intAttr(key, value);
|
|
2572
2596
|
}
|
|
2573
2597
|
function genAiOperationName(kind) {
|
|
2574
2598
|
switch (kind) {
|
|
@@ -2582,10 +2606,27 @@ function genAiOperationName(kind) {
|
|
|
2582
2606
|
return void 0;
|
|
2583
2607
|
}
|
|
2584
2608
|
}
|
|
2609
|
+
function resolveSpanTimes(ev) {
|
|
2610
|
+
const startedAtMs = typeof ev.attributes?.startedAtMs === "number" && Number.isFinite(ev.attributes.startedAtMs) ? ev.attributes.startedAtMs : void 0;
|
|
2611
|
+
const endedAtMs = typeof ev.attributes?.endedAtMs === "number" && Number.isFinite(ev.attributes.endedAtMs) ? ev.attributes.endedAtMs : void 0;
|
|
2612
|
+
const startMs = startedAtMs ?? ev.timestamp;
|
|
2613
|
+
const startNs = String(unixNano2(startMs));
|
|
2614
|
+
if (endedAtMs !== void 0) {
|
|
2615
|
+
return { startNs, endNs: String(unixNano2(endedAtMs)) };
|
|
2616
|
+
}
|
|
2617
|
+
if (ev.durationMs !== void 0 && Number.isFinite(ev.durationMs)) {
|
|
2618
|
+
return {
|
|
2619
|
+
startNs,
|
|
2620
|
+
endNs: String(unixNano2(startMs) + unixNano2(ev.durationMs))
|
|
2621
|
+
};
|
|
2622
|
+
}
|
|
2623
|
+
return { startNs };
|
|
2624
|
+
}
|
|
2585
2625
|
function exportOtlpJson(tree, options) {
|
|
2586
2626
|
const warnings = [
|
|
2587
2627
|
"OTLP JSON export uses OTel GenAI-aligned attributes where applicable; experimental until verified against specific collectors.",
|
|
2588
|
-
"Not OTLP gRPC/protobuf \u2014 JSON mapping only. Generated locally; no network upload."
|
|
2628
|
+
"Not OTLP gRPC/protobuf \u2014 JSON mapping only. Generated locally; no network upload.",
|
|
2629
|
+
"Status and span kind use OTLP numeric enums (StatusCode 0/1/2, SpanKind INTERNAL=1)."
|
|
2589
2630
|
];
|
|
2590
2631
|
const traceId = hexFrom2(`trace:${tree.runId}`, 16);
|
|
2591
2632
|
const includeAttributes = options?.includeAttributes ?? false;
|
|
@@ -2597,11 +2638,7 @@ function exportOtlpJson(tree, options) {
|
|
|
2597
2638
|
const ev = n.event;
|
|
2598
2639
|
const spanId = hexFrom2(`${tree.runId}:${ev.eventId}`, 8);
|
|
2599
2640
|
const parentSpanId = ev.parentId ? hexFrom2(`${tree.runId}:${ev.parentId}`, 8) : void 0;
|
|
2600
|
-
const startNs =
|
|
2601
|
-
let endNs;
|
|
2602
|
-
if (ev.durationMs !== void 0 && Number.isFinite(ev.durationMs)) {
|
|
2603
|
-
endNs = String(unixNano2(ev.timestamp) + unixNano2(ev.durationMs));
|
|
2604
|
-
}
|
|
2641
|
+
const { startNs, endNs } = resolveSpanTimes(ev);
|
|
2605
2642
|
const attrs = [
|
|
2606
2643
|
stringAttr("agent_inspect.kind", ev.kind),
|
|
2607
2644
|
stringAttr("agent_inspect.confidence", ev.confidence),
|
|
@@ -2631,29 +2668,28 @@ function exportOtlpJson(tree, options) {
|
|
|
2631
2668
|
if (includeAttributes && meta && typeof meta === "object") {
|
|
2632
2669
|
for (const [k, v] of Object.entries(meta)) {
|
|
2633
2670
|
if (k === "tokens" || k === "model") continue;
|
|
2634
|
-
if (typeof v === "string"
|
|
2635
|
-
attrs.push(
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
);
|
|
2671
|
+
if (typeof v === "string") {
|
|
2672
|
+
attrs.push(stringAttr(`agent_inspect.preview.${k}`, v.slice(0, maxLen)));
|
|
2673
|
+
} else if (typeof v === "number" && Number.isFinite(v)) {
|
|
2674
|
+
attrs.push(numberAttr(`agent_inspect.preview.${k}`, v));
|
|
2675
|
+
} else if (typeof v === "boolean") {
|
|
2676
|
+
attrs.push(boolAttr(`agent_inspect.preview.${k}`, v));
|
|
2641
2677
|
}
|
|
2642
2678
|
}
|
|
2643
2679
|
}
|
|
2644
|
-
let statusCode =
|
|
2680
|
+
let statusCode = OTLP_STATUS_CODE_UNSET;
|
|
2645
2681
|
let statusMessage;
|
|
2646
2682
|
if (ev.status === "error") {
|
|
2647
|
-
statusCode =
|
|
2683
|
+
statusCode = OTLP_STATUS_CODE_ERROR;
|
|
2648
2684
|
statusMessage = meta && typeof meta.error === "object" && meta.error !== null ? String(meta.error.message ?? "error").slice(0, maxLen) : "error";
|
|
2649
2685
|
} else if (ev.status === "ok") {
|
|
2650
|
-
statusCode =
|
|
2686
|
+
statusCode = OTLP_STATUS_CODE_OK;
|
|
2651
2687
|
}
|
|
2652
2688
|
const spanJson = {
|
|
2653
2689
|
traceId,
|
|
2654
2690
|
spanId,
|
|
2655
2691
|
name: ev.name,
|
|
2656
|
-
kind:
|
|
2692
|
+
kind: OTLP_SPAN_KIND_INTERNAL,
|
|
2657
2693
|
startTimeUnixNano: startNs,
|
|
2658
2694
|
attributes: attrs,
|
|
2659
2695
|
status: {
|
|
@@ -2695,6 +2731,136 @@ function exportOtlpJson(tree, options) {
|
|
|
2695
2731
|
|
|
2696
2732
|
// packages/core/src/exporters/validation.ts
|
|
2697
2733
|
var EXPERIMENTAL = "Experimental compatibility export \u2014 verify against your target tooling before relying on it.";
|
|
2734
|
+
function pushPath(errors, path30, message) {
|
|
2735
|
+
errors.push(`${path30}: ${message}`);
|
|
2736
|
+
}
|
|
2737
|
+
function isRecord5(value) {
|
|
2738
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
2739
|
+
}
|
|
2740
|
+
function validateOtlpJson(content) {
|
|
2741
|
+
const errors = [];
|
|
2742
|
+
const warnings = [
|
|
2743
|
+
EXPERIMENTAL,
|
|
2744
|
+
"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."
|
|
2746
|
+
];
|
|
2747
|
+
let parsed;
|
|
2748
|
+
try {
|
|
2749
|
+
parsed = JSON.parse(content);
|
|
2750
|
+
} catch {
|
|
2751
|
+
pushPath(errors, "$", "OTLP JSON export is not valid JSON");
|
|
2752
|
+
return { ok: false, format: "otlp-json", errors, warnings };
|
|
2753
|
+
}
|
|
2754
|
+
if (!isRecord5(parsed)) {
|
|
2755
|
+
pushPath(errors, "$", "OTLP JSON export must be an object");
|
|
2756
|
+
return { ok: false, format: "otlp-json", errors, warnings };
|
|
2757
|
+
}
|
|
2758
|
+
if (!Array.isArray(parsed.resourceSpans)) {
|
|
2759
|
+
pushPath(errors, "$.resourceSpans", "must be an array");
|
|
2760
|
+
return { ok: false, format: "otlp-json", errors, warnings };
|
|
2761
|
+
}
|
|
2762
|
+
parsed.resourceSpans.forEach((resourceSpan, rsi) => {
|
|
2763
|
+
const rsPath = `$.resourceSpans[${rsi}]`;
|
|
2764
|
+
if (!isRecord5(resourceSpan)) {
|
|
2765
|
+
pushPath(errors, rsPath, "must be an object");
|
|
2766
|
+
return;
|
|
2767
|
+
}
|
|
2768
|
+
if (!Array.isArray(resourceSpan.scopeSpans)) {
|
|
2769
|
+
pushPath(errors, `${rsPath}.scopeSpans`, "must be an array");
|
|
2770
|
+
return;
|
|
2771
|
+
}
|
|
2772
|
+
resourceSpan.scopeSpans.forEach((scopeSpan, ssi) => {
|
|
2773
|
+
const ssPath = `${rsPath}.scopeSpans[${ssi}]`;
|
|
2774
|
+
if (!isRecord5(scopeSpan)) {
|
|
2775
|
+
pushPath(errors, ssPath, "must be an object");
|
|
2776
|
+
return;
|
|
2777
|
+
}
|
|
2778
|
+
if (!Array.isArray(scopeSpan.spans)) {
|
|
2779
|
+
pushPath(errors, `${ssPath}.spans`, "must be an array");
|
|
2780
|
+
return;
|
|
2781
|
+
}
|
|
2782
|
+
scopeSpan.spans.forEach((span, spi) => {
|
|
2783
|
+
const spanPath = `${ssPath}.spans[${spi}]`;
|
|
2784
|
+
if (!isRecord5(span)) {
|
|
2785
|
+
pushPath(errors, spanPath, "must be an object");
|
|
2786
|
+
return;
|
|
2787
|
+
}
|
|
2788
|
+
if (typeof span.traceId !== "string" || span.traceId.length === 0) {
|
|
2789
|
+
pushPath(errors, `${spanPath}.traceId`, "must be a non-empty string");
|
|
2790
|
+
}
|
|
2791
|
+
if (typeof span.spanId !== "string" || span.spanId.length === 0) {
|
|
2792
|
+
pushPath(errors, `${spanPath}.spanId`, "must be a non-empty string");
|
|
2793
|
+
}
|
|
2794
|
+
if (typeof span.name !== "string") {
|
|
2795
|
+
pushPath(errors, `${spanPath}.name`, "must be a string");
|
|
2796
|
+
}
|
|
2797
|
+
if (typeof span.startTimeUnixNano !== "string" || !/^\d+$/.test(span.startTimeUnixNano)) {
|
|
2798
|
+
pushPath(
|
|
2799
|
+
errors,
|
|
2800
|
+
`${spanPath}.startTimeUnixNano`,
|
|
2801
|
+
"must be a decimal-string 64-bit integer"
|
|
2802
|
+
);
|
|
2803
|
+
}
|
|
2804
|
+
if (span.endTimeUnixNano !== void 0 && (typeof span.endTimeUnixNano !== "string" || !/^\d+$/.test(span.endTimeUnixNano))) {
|
|
2805
|
+
pushPath(
|
|
2806
|
+
errors,
|
|
2807
|
+
`${spanPath}.endTimeUnixNano`,
|
|
2808
|
+
"must be a decimal-string 64-bit integer when present"
|
|
2809
|
+
);
|
|
2810
|
+
}
|
|
2811
|
+
if (typeof span.kind === "number") {
|
|
2812
|
+
if (!Number.isInteger(span.kind)) {
|
|
2813
|
+
pushPath(errors, `${spanPath}.kind`, "must be an integer SpanKind enum");
|
|
2814
|
+
}
|
|
2815
|
+
} else if (typeof span.kind === "string") {
|
|
2816
|
+
warnings.push(
|
|
2817
|
+
`${spanPath}.kind: string SpanKind enum is legacy; prefer numeric (INTERNAL=1)`
|
|
2818
|
+
);
|
|
2819
|
+
} else if (span.kind !== void 0) {
|
|
2820
|
+
pushPath(
|
|
2821
|
+
errors,
|
|
2822
|
+
`${spanPath}.kind`,
|
|
2823
|
+
"must be numeric SpanKind or historical string enum"
|
|
2824
|
+
);
|
|
2825
|
+
}
|
|
2826
|
+
if (!isRecord5(span.status)) {
|
|
2827
|
+
pushPath(errors, `${spanPath}.status`, "must be an object");
|
|
2828
|
+
} else {
|
|
2829
|
+
const code = span.status.code;
|
|
2830
|
+
if (typeof code === "number") {
|
|
2831
|
+
if (![0, 1, 2].includes(code)) {
|
|
2832
|
+
pushPath(
|
|
2833
|
+
errors,
|
|
2834
|
+
`${spanPath}.status.code`,
|
|
2835
|
+
"must be numeric StatusCode 0 (UNSET), 1 (OK), or 2 (ERROR)"
|
|
2836
|
+
);
|
|
2837
|
+
}
|
|
2838
|
+
} else if (typeof code === "string") {
|
|
2839
|
+
const upper = code.toUpperCase();
|
|
2840
|
+
if (upper !== "STATUS_CODE_UNSET" && upper !== "STATUS_CODE_OK" && upper !== "STATUS_CODE_ERROR" && upper !== "UNSET" && upper !== "OK" && upper !== "ERROR" && !/^[012]$/.test(code.trim())) {
|
|
2841
|
+
pushPath(
|
|
2842
|
+
errors,
|
|
2843
|
+
`${spanPath}.status.code`,
|
|
2844
|
+
"unrecognized StatusCode string"
|
|
2845
|
+
);
|
|
2846
|
+
} else {
|
|
2847
|
+
warnings.push(
|
|
2848
|
+
`${spanPath}.status.code: string StatusCode is legacy; prefer numeric 0/1/2`
|
|
2849
|
+
);
|
|
2850
|
+
}
|
|
2851
|
+
} else {
|
|
2852
|
+
pushPath(
|
|
2853
|
+
errors,
|
|
2854
|
+
`${spanPath}.status.code`,
|
|
2855
|
+
"must be numeric StatusCode 0/1/2 or historical string enum"
|
|
2856
|
+
);
|
|
2857
|
+
}
|
|
2858
|
+
}
|
|
2859
|
+
});
|
|
2860
|
+
});
|
|
2861
|
+
});
|
|
2862
|
+
return { ok: errors.length === 0, format: "otlp-json", errors, warnings };
|
|
2863
|
+
}
|
|
2698
2864
|
function validateExportContent(format, content) {
|
|
2699
2865
|
const errors = [];
|
|
2700
2866
|
const warnings = [EXPERIMENTAL];
|
|
@@ -2740,25 +2906,7 @@ function validateExportContent(format, content) {
|
|
|
2740
2906
|
return { ok: errors.length === 0, format, errors, warnings };
|
|
2741
2907
|
}
|
|
2742
2908
|
if (format === "otlp-json") {
|
|
2743
|
-
|
|
2744
|
-
try {
|
|
2745
|
-
parsed = JSON.parse(content);
|
|
2746
|
-
} catch {
|
|
2747
|
-
errors.push("OTLP JSON export is not valid JSON");
|
|
2748
|
-
return { ok: false, format, errors, warnings };
|
|
2749
|
-
}
|
|
2750
|
-
if (!parsed || typeof parsed !== "object") {
|
|
2751
|
-
errors.push("OTLP JSON export must be an object");
|
|
2752
|
-
return { ok: false, format, errors, warnings };
|
|
2753
|
-
}
|
|
2754
|
-
const o = parsed;
|
|
2755
|
-
if (!Array.isArray(o.resourceSpans)) {
|
|
2756
|
-
errors.push("OTLP JSON export must include resourceSpans array");
|
|
2757
|
-
}
|
|
2758
|
-
warnings.push(
|
|
2759
|
-
"OTLP JSON mapping uses OTel GenAI-aligned attributes where applicable; collectors may require transformation."
|
|
2760
|
-
);
|
|
2761
|
-
return { ok: errors.length === 0, format, errors, warnings };
|
|
2909
|
+
return validateOtlpJson(content);
|
|
2762
2910
|
}
|
|
2763
2911
|
errors.push(`Unsupported export format`);
|
|
2764
2912
|
return { ok: false, format, errors, warnings };
|
|
@@ -3151,7 +3299,7 @@ async function exportCommand(runId, options = {}) {
|
|
|
3151
3299
|
const traceDir = resolveTraceDir({ dir: options.dir });
|
|
3152
3300
|
let events;
|
|
3153
3301
|
try {
|
|
3154
|
-
const result2 = await
|
|
3302
|
+
const result2 = await readRunPersistedEvents(id, traceDir);
|
|
3155
3303
|
events = result2?.events ?? [];
|
|
3156
3304
|
} catch (e) {
|
|
3157
3305
|
const msg = e instanceof Error ? e.message : String(e);
|
|
@@ -3167,7 +3315,11 @@ Trace directory: ${traceDir}`);
|
|
|
3167
3315
|
}
|
|
3168
3316
|
let tree;
|
|
3169
3317
|
try {
|
|
3170
|
-
|
|
3318
|
+
const trees = persistedInspectEventsToRunTrees(events);
|
|
3319
|
+
tree = trees.find((candidate) => candidate.runId === id) ?? trees[0];
|
|
3320
|
+
if (tree === void 0) {
|
|
3321
|
+
throw new Error("No run tree could be built from persisted events");
|
|
3322
|
+
}
|
|
3171
3323
|
} catch (e) {
|
|
3172
3324
|
const msg = e instanceof Error ? e.message : String(e);
|
|
3173
3325
|
console.error(`[AgentInspect] export failed: ${msg}`);
|
|
@@ -3195,7 +3347,9 @@ Trace directory: ${traceDir}`);
|
|
|
3195
3347
|
await mkdir(path19.dirname(outPath), { recursive: true });
|
|
3196
3348
|
await writeFile(outPath, result.content, "utf-8");
|
|
3197
3349
|
const vlabel = validation !== void 0 ? validation.ok ? "ok" : "failed" : "skipped";
|
|
3198
|
-
console.
|
|
3350
|
+
console.error(
|
|
3351
|
+
`Wrote ${result.fileExtension} export to ${outPath} (validation: ${vlabel})`
|
|
3352
|
+
);
|
|
3199
3353
|
if (validation !== void 0 && !validation.ok) {
|
|
3200
3354
|
console.error("Validation errors:", validation.errors.join("; "));
|
|
3201
3355
|
}
|
|
@@ -3208,7 +3362,9 @@ Trace directory: ${traceDir}`);
|
|
|
3208
3362
|
warnings: [...result.warnings, ...validation?.warnings ?? []],
|
|
3209
3363
|
validation
|
|
3210
3364
|
};
|
|
3211
|
-
if (outPath
|
|
3365
|
+
if (outPath !== void 0) {
|
|
3366
|
+
payload.out = outPath;
|
|
3367
|
+
} else {
|
|
3212
3368
|
payload.content = result.content;
|
|
3213
3369
|
}
|
|
3214
3370
|
console.log(JSON.stringify(payload, null, 2));
|
|
@@ -3565,7 +3721,7 @@ async function newestTraceMtimeMs(traceDir) {
|
|
|
3565
3721
|
}
|
|
3566
3722
|
async function loadSessionRuns(traceDir) {
|
|
3567
3723
|
try {
|
|
3568
|
-
const mod = await import('./src-
|
|
3724
|
+
const mod = await import('./src-KFOBXFPN.mjs');
|
|
3569
3725
|
const dbPath = mod.resolveIndexDbPath(traceDir);
|
|
3570
3726
|
const status = mod.indexStatus(dbPath);
|
|
3571
3727
|
if (!status.healthy) {
|
|
@@ -4298,7 +4454,7 @@ var STRICT_PROFILE_EXTRA_KEYS = [
|
|
|
4298
4454
|
"retrieval",
|
|
4299
4455
|
"query"
|
|
4300
4456
|
];
|
|
4301
|
-
function
|
|
4457
|
+
function isRecord6(value) {
|
|
4302
4458
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4303
4459
|
}
|
|
4304
4460
|
function toKey(key) {
|
|
@@ -4727,7 +4883,7 @@ var Redactor2 = class {
|
|
|
4727
4883
|
});
|
|
4728
4884
|
return out;
|
|
4729
4885
|
}
|
|
4730
|
-
if (
|
|
4886
|
+
if (isRecord6(value)) {
|
|
4731
4887
|
if (state.seen.has(value)) return state.seen.get(value);
|
|
4732
4888
|
const out = {};
|
|
4733
4889
|
state.seen.set(value, out);
|
|
@@ -4762,7 +4918,7 @@ var REDACTION_POLICY_LIMITS = {
|
|
|
4762
4918
|
};
|
|
4763
4919
|
var ALLOWED_TOP_LEVEL = /* @__PURE__ */ new Set(["version", "extraKeys", "patterns"]);
|
|
4764
4920
|
var ALLOWED_PATTERN_FIELDS = /* @__PURE__ */ new Set(["id", "type", "value", "severity"]);
|
|
4765
|
-
function
|
|
4921
|
+
function isRecord7(value) {
|
|
4766
4922
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
4767
4923
|
}
|
|
4768
4924
|
function rejectRemotePolicyPath(policyPath) {
|
|
@@ -4802,7 +4958,7 @@ function rejectUnknownFields(record, allowed, label) {
|
|
|
4802
4958
|
}
|
|
4803
4959
|
function compilePatternDetector(input3, index) {
|
|
4804
4960
|
const label = `patterns[${index}]`;
|
|
4805
|
-
if (!
|
|
4961
|
+
if (!isRecord7(input3)) throw new Error(`${label} must be an object.`);
|
|
4806
4962
|
const typeEarly = input3.type;
|
|
4807
4963
|
if (typeEarly === "typed") {
|
|
4808
4964
|
throw new Error(
|
|
@@ -4857,7 +5013,7 @@ function compilePatternDetector(input3, index) {
|
|
|
4857
5013
|
};
|
|
4858
5014
|
}
|
|
4859
5015
|
function compileRedactionPolicy(raw, policyPath) {
|
|
4860
|
-
if (!
|
|
5016
|
+
if (!isRecord7(raw)) {
|
|
4861
5017
|
throw new Error(`Redaction policy must be a JSON object (${policyPath}).`);
|
|
4862
5018
|
}
|
|
4863
5019
|
rejectUnknownFields(raw, ALLOWED_TOP_LEVEL, "Redaction policy");
|
|
@@ -5879,7 +6035,7 @@ async function openCommand(input3, options = {}, stdin = process.stdin) {
|
|
|
5879
6035
|
}
|
|
5880
6036
|
}
|
|
5881
6037
|
}
|
|
5882
|
-
function
|
|
6038
|
+
function isRecord8(value) {
|
|
5883
6039
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5884
6040
|
}
|
|
5885
6041
|
function parseTarget(value) {
|
|
@@ -5888,7 +6044,7 @@ function parseTarget(value) {
|
|
|
5888
6044
|
throw new Error('Unsupported migration target. Use "--to 1.0".');
|
|
5889
6045
|
}
|
|
5890
6046
|
function formatOf(value) {
|
|
5891
|
-
if (!
|
|
6047
|
+
if (!isRecord8(value)) return "unknown";
|
|
5892
6048
|
if (value.schemaVersion === "0.1") return "0.1";
|
|
5893
6049
|
if (value.schemaVersion === "0.2") return "0.2";
|
|
5894
6050
|
if (value.schemaVersion === "1.0") return "1.0";
|
|
@@ -12389,16 +12545,120 @@ function demoTemplate(framework) {
|
|
|
12389
12545
|
switch (framework) {
|
|
12390
12546
|
case "ai-sdk":
|
|
12391
12547
|
return `/**
|
|
12392
|
-
* AI SDK starter \u2014
|
|
12393
|
-
* Install: npm install agent-inspect @agent-inspect/ai-sdk ai
|
|
12548
|
+
* AI SDK starter \u2014 keyless MockLanguageModelV3 + @agent-inspect/ai-sdk telemetry.
|
|
12549
|
+
* Install: npm install agent-inspect @agent-inspect/ai-sdk ai@6.0.210 zod
|
|
12394
12550
|
*/
|
|
12395
|
-
import {
|
|
12551
|
+
import { generateText, stepCountIs, tool } from "ai";
|
|
12552
|
+
import { MockLanguageModelV3 } from "ai/test";
|
|
12553
|
+
import { agentInspect } from "@agent-inspect/ai-sdk";
|
|
12554
|
+
import { z } from "zod";
|
|
12555
|
+
import { readdirSync, readFileSync } from "node:fs";
|
|
12556
|
+
import path from "node:path";
|
|
12557
|
+
|
|
12558
|
+
const TRACE_DIR = ".agent-inspect";
|
|
12559
|
+
const ANSWER = "You have 2 orders";
|
|
12560
|
+
const CORRECT_RUN = "ai-sdk-demo-correct";
|
|
12561
|
+
const WRONG_RUN = "ai-sdk-demo-wrong";
|
|
12562
|
+
|
|
12563
|
+
const usage = {
|
|
12564
|
+
inputTokens: { total: 4, noCache: 4, cacheRead: 0, cacheWrite: 0 },
|
|
12565
|
+
outputTokens: { total: 3, text: 3, reasoning: 0 },
|
|
12566
|
+
};
|
|
12567
|
+
|
|
12568
|
+
const lookupOrders = tool({
|
|
12569
|
+
description: "Look up orders for a user",
|
|
12570
|
+
inputSchema: z.object({ userId: z.string() }),
|
|
12571
|
+
execute: async () => ({ orders: 2 }),
|
|
12572
|
+
});
|
|
12573
|
+
|
|
12574
|
+
const deleteOrders = tool({
|
|
12575
|
+
description: "Delete orders for a user (wrong path)",
|
|
12576
|
+
inputSchema: z.object({ userId: z.string() }),
|
|
12577
|
+
execute: async () => ({ orders: 2 }),
|
|
12578
|
+
});
|
|
12579
|
+
|
|
12580
|
+
async function runPath(runName, toolName) {
|
|
12581
|
+
const integration = agentInspect({
|
|
12582
|
+
traceDir: TRACE_DIR,
|
|
12583
|
+
runName,
|
|
12584
|
+
capture: "metadata-only",
|
|
12585
|
+
});
|
|
12586
|
+
let step = 0;
|
|
12587
|
+
try {
|
|
12588
|
+
const result = await generateText({
|
|
12589
|
+
model: new MockLanguageModelV3({
|
|
12590
|
+
provider: "fixture-provider",
|
|
12591
|
+
modelId: "fixture-tools",
|
|
12592
|
+
doGenerate: async () => {
|
|
12593
|
+
step += 1;
|
|
12594
|
+
if (step === 1) {
|
|
12595
|
+
return {
|
|
12596
|
+
content: [
|
|
12597
|
+
{
|
|
12598
|
+
type: "tool-call",
|
|
12599
|
+
toolCallId: \`call-\${toolName}\`,
|
|
12600
|
+
toolName,
|
|
12601
|
+
input: { userId: "u1" },
|
|
12602
|
+
},
|
|
12603
|
+
],
|
|
12604
|
+
finishReason: { unified: "tool-calls", raw: "tool-calls" },
|
|
12605
|
+
usage,
|
|
12606
|
+
warnings: [],
|
|
12607
|
+
};
|
|
12608
|
+
}
|
|
12609
|
+
return {
|
|
12610
|
+
content: [{ type: "text", text: ANSWER }],
|
|
12611
|
+
finishReason: { unified: "stop", raw: "stop" },
|
|
12612
|
+
usage,
|
|
12613
|
+
warnings: [],
|
|
12614
|
+
};
|
|
12615
|
+
},
|
|
12616
|
+
}),
|
|
12617
|
+
tools: { lookup_orders: lookupOrders, delete_orders: deleteOrders },
|
|
12618
|
+
prompt: "How many orders do I have?",
|
|
12619
|
+
stopWhen: stepCountIs(5),
|
|
12620
|
+
experimental_telemetry: {
|
|
12621
|
+
isEnabled: true,
|
|
12622
|
+
recordInputs: false,
|
|
12623
|
+
recordOutputs: false,
|
|
12624
|
+
integrations: [integration],
|
|
12625
|
+
},
|
|
12626
|
+
});
|
|
12627
|
+
if (result.text !== ANSWER) {
|
|
12628
|
+
throw new Error(\`unexpected answer for \${runName}: \${result.text}\`);
|
|
12629
|
+
}
|
|
12630
|
+
} finally {
|
|
12631
|
+
await integration.flush();
|
|
12632
|
+
await integration.close();
|
|
12633
|
+
}
|
|
12634
|
+
}
|
|
12635
|
+
|
|
12636
|
+
function selectRunIdByName(runName) {
|
|
12637
|
+
const files = readdirSync(TRACE_DIR).filter((f) => f.endsWith(".jsonl"));
|
|
12638
|
+
const matches = [];
|
|
12639
|
+
for (const file of files) {
|
|
12640
|
+
const text = readFileSync(path.join(TRACE_DIR, file), "utf8");
|
|
12641
|
+
if (text.includes(\`"name":"\${runName}"\`) || text.includes(\`"name": "\${runName}"\`)) {
|
|
12642
|
+
matches.push(file.replace(/\\.jsonl$/, ""));
|
|
12643
|
+
}
|
|
12644
|
+
}
|
|
12645
|
+
if (matches.length !== 1) {
|
|
12646
|
+
throw new Error(
|
|
12647
|
+
\`expected exactly one run named \${runName}, found \${matches.length}\`,
|
|
12648
|
+
);
|
|
12649
|
+
}
|
|
12650
|
+
return matches[0];
|
|
12651
|
+
}
|
|
12396
12652
|
|
|
12397
12653
|
async function main() {
|
|
12398
|
-
await
|
|
12399
|
-
|
|
12400
|
-
|
|
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);
|
|
12401
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\`);
|
|
12402
12662
|
}
|
|
12403
12663
|
|
|
12404
12664
|
main().catch((error) => {
|
|
@@ -13391,7 +13651,7 @@ function isModuleNotFound4(e) {
|
|
|
13391
13651
|
}
|
|
13392
13652
|
async function loadIndexSqlite() {
|
|
13393
13653
|
try {
|
|
13394
|
-
return await import('./src-
|
|
13654
|
+
return await import('./src-KFOBXFPN.mjs');
|
|
13395
13655
|
} catch (e) {
|
|
13396
13656
|
if (isModuleNotFound4(e)) {
|
|
13397
13657
|
console.error(
|