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
|
@@ -2690,16 +2690,51 @@ function buildRunTimeline(events, options = {}) {
|
|
|
2690
2690
|
const computeDepth = (stepId) => {
|
|
2691
2691
|
const cached2 = depthCache.get(stepId);
|
|
2692
2692
|
if (cached2 !== void 0) return cached2;
|
|
2693
|
-
const
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2693
|
+
const ancestry = [];
|
|
2694
|
+
const ancestryIndexes = /* @__PURE__ */ new Map();
|
|
2695
|
+
let currentStepId = stepId;
|
|
2696
|
+
let resolvedDepth;
|
|
2697
|
+
while (resolvedDepth === void 0) {
|
|
2698
|
+
const cachedDepth = depthCache.get(currentStepId);
|
|
2699
|
+
if (cachedDepth !== void 0) {
|
|
2700
|
+
resolvedDepth = cachedDepth;
|
|
2701
|
+
continue;
|
|
2702
|
+
}
|
|
2703
|
+
const cycleStart = ancestryIndexes.get(currentStepId);
|
|
2704
|
+
if (cycleStart !== void 0) {
|
|
2705
|
+
const cycleStepIds = ancestry.splice(cycleStart);
|
|
2706
|
+
for (const cycleStepId of cycleStepIds) {
|
|
2707
|
+
depthCache.set(cycleStepId, ROOT_TIMELINE_DEPTH);
|
|
2708
|
+
}
|
|
2709
|
+
resolvedDepth = ROOT_TIMELINE_DEPTH;
|
|
2710
|
+
continue;
|
|
2711
|
+
}
|
|
2712
|
+
const currentStep = steps.get(currentStepId);
|
|
2713
|
+
if (!currentStep) {
|
|
2714
|
+
resolvedDepth = ROOT_TIMELINE_DEPTH;
|
|
2715
|
+
continue;
|
|
2716
|
+
}
|
|
2717
|
+
ancestryIndexes.set(currentStepId, ancestry.length);
|
|
2718
|
+
ancestry.push(currentStepId);
|
|
2719
|
+
const parentId = currentStep.parentId;
|
|
2720
|
+
if (typeof parentId !== "string" || parentId.trim() === "" || !steps.has(parentId)) {
|
|
2721
|
+
ancestry.pop();
|
|
2722
|
+
depthCache.set(currentStepId, ROOT_TIMELINE_DEPTH);
|
|
2723
|
+
resolvedDepth = ROOT_TIMELINE_DEPTH;
|
|
2724
|
+
continue;
|
|
2725
|
+
}
|
|
2726
|
+
currentStepId = parentId;
|
|
2699
2727
|
}
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2728
|
+
ancestry.reverse();
|
|
2729
|
+
for (const ancestorStepId of ancestry) {
|
|
2730
|
+
resolvedDepth = Math.min(MAX_TIMELINE_DEPTH, resolvedDepth + 1);
|
|
2731
|
+
depthCache.set(ancestorStepId, resolvedDepth);
|
|
2732
|
+
}
|
|
2733
|
+
const resolvedStepDepth = depthCache.get(stepId);
|
|
2734
|
+
if (resolvedStepDepth === void 0) {
|
|
2735
|
+
throw new Error(`Failed to resolve timeline depth for step "${stepId}"`);
|
|
2736
|
+
}
|
|
2737
|
+
return resolvedStepDepth;
|
|
2703
2738
|
};
|
|
2704
2739
|
const entries = [];
|
|
2705
2740
|
for (const [stepId, s] of steps.entries()) {
|
|
@@ -2787,10 +2822,13 @@ function renderTimeline(timeline, options = {}) {
|
|
|
2787
2822
|
}
|
|
2788
2823
|
return lines.join("\n");
|
|
2789
2824
|
}
|
|
2825
|
+
var ROOT_TIMELINE_DEPTH, MAX_TIMELINE_DEPTH;
|
|
2790
2826
|
var init_timeline = __esm({
|
|
2791
2827
|
"packages/core/src/timeline.ts"() {
|
|
2792
2828
|
init_stats();
|
|
2793
2829
|
init_utils();
|
|
2830
|
+
ROOT_TIMELINE_DEPTH = 0;
|
|
2831
|
+
MAX_TIMELINE_DEPTH = 1e3;
|
|
2794
2832
|
}
|
|
2795
2833
|
});
|
|
2796
2834
|
|
|
@@ -12540,6 +12578,23 @@ function persistedInspectEventToInspectEvent(event) {
|
|
|
12540
12578
|
if (event.durationMs !== void 0 && Number.isFinite(event.durationMs) && event.durationMs >= 0) {
|
|
12541
12579
|
out.durationMs = event.durationMs;
|
|
12542
12580
|
}
|
|
12581
|
+
if (event.startedAt !== void 0) {
|
|
12582
|
+
const started = parseIsoToMs3(event.startedAt);
|
|
12583
|
+
if (!started.invalidTimestamp) {
|
|
12584
|
+
attrs.startedAtMs = started.ms;
|
|
12585
|
+
out.timestamp = started.ms;
|
|
12586
|
+
}
|
|
12587
|
+
}
|
|
12588
|
+
if (event.endedAt !== void 0) {
|
|
12589
|
+
const ended = parseIsoToMs3(event.endedAt);
|
|
12590
|
+
if (!ended.invalidTimestamp) {
|
|
12591
|
+
attrs.endedAtMs = ended.ms;
|
|
12592
|
+
if (out.durationMs === void 0 && typeof attrs.startedAtMs === "number" && ended.ms >= attrs.startedAtMs) {
|
|
12593
|
+
out.durationMs = ended.ms - attrs.startedAtMs;
|
|
12594
|
+
}
|
|
12595
|
+
}
|
|
12596
|
+
}
|
|
12597
|
+
out.attributes = compactAttributes3(attrs);
|
|
12543
12598
|
return out;
|
|
12544
12599
|
}
|
|
12545
12600
|
function persistedInspectEventsToInspectEvents(events, options) {
|
|
@@ -13461,20 +13516,38 @@ function extractOtlpDocument(root) {
|
|
|
13461
13516
|
function mapOtlpStatus(status) {
|
|
13462
13517
|
if (!isRecord11(status)) return void 0;
|
|
13463
13518
|
const rawCode = status.code;
|
|
13464
|
-
if (typeof rawCode
|
|
13465
|
-
|
|
13466
|
-
|
|
13467
|
-
|
|
13468
|
-
|
|
13469
|
-
|
|
13470
|
-
|
|
13471
|
-
|
|
13472
|
-
|
|
13473
|
-
|
|
13474
|
-
|
|
13475
|
-
|
|
13476
|
-
|
|
13519
|
+
if (typeof rawCode === "number" && Number.isFinite(rawCode)) {
|
|
13520
|
+
switch (rawCode) {
|
|
13521
|
+
case 0:
|
|
13522
|
+
return "unknown";
|
|
13523
|
+
case 1:
|
|
13524
|
+
return "ok";
|
|
13525
|
+
case 2:
|
|
13526
|
+
return "error";
|
|
13527
|
+
default:
|
|
13528
|
+
return "unknown";
|
|
13529
|
+
}
|
|
13530
|
+
}
|
|
13531
|
+
if (typeof rawCode === "string") {
|
|
13532
|
+
const trimmed = rawCode.trim();
|
|
13533
|
+
if (/^\d+$/.test(trimmed)) {
|
|
13534
|
+
return mapOtlpStatus({ code: Number(trimmed) });
|
|
13535
|
+
}
|
|
13536
|
+
switch (trimmed.toUpperCase()) {
|
|
13537
|
+
case "STATUS_CODE_OK":
|
|
13538
|
+
case "OK":
|
|
13539
|
+
return "ok";
|
|
13540
|
+
case "STATUS_CODE_ERROR":
|
|
13541
|
+
case "ERROR":
|
|
13542
|
+
return "error";
|
|
13543
|
+
case "STATUS_CODE_UNSET":
|
|
13544
|
+
case "UNSET":
|
|
13545
|
+
return "unknown";
|
|
13546
|
+
default:
|
|
13547
|
+
return "unknown";
|
|
13548
|
+
}
|
|
13477
13549
|
}
|
|
13550
|
+
return void 0;
|
|
13478
13551
|
}
|
|
13479
13552
|
function readOtlpKind(attributes, pathPrefix) {
|
|
13480
13553
|
const warnings = [];
|
|
@@ -16162,7 +16235,7 @@ var init_src = __esm({
|
|
|
16162
16235
|
});
|
|
16163
16236
|
|
|
16164
16237
|
// package.json
|
|
16165
|
-
var version = "6.31.
|
|
16238
|
+
var version = "6.31.7";
|
|
16166
16239
|
|
|
16167
16240
|
// packages/cli/src/list.ts
|
|
16168
16241
|
init_advanced();
|
|
@@ -16511,7 +16584,7 @@ function mapReaderFormat(format) {
|
|
|
16511
16584
|
function isMissingFileError(error) {
|
|
16512
16585
|
return error !== null && typeof error === "object" && "code" in error && error.code === "ENOENT";
|
|
16513
16586
|
}
|
|
16514
|
-
async function
|
|
16587
|
+
async function readRunPersistedEvents(runId, traceDir) {
|
|
16515
16588
|
const filePath = getTraceFilePath(runId, traceDir);
|
|
16516
16589
|
try {
|
|
16517
16590
|
await promises.access(filePath);
|
|
@@ -16519,16 +16592,24 @@ async function readRunTraceEvents(runId, traceDir) {
|
|
|
16519
16592
|
{ type: "file", path: filePath },
|
|
16520
16593
|
{ format: "agent-inspect-jsonl" }
|
|
16521
16594
|
);
|
|
16522
|
-
const events = persistedInspectEventsToTraceEvents(result.events);
|
|
16523
16595
|
return {
|
|
16524
|
-
events,
|
|
16525
|
-
format: events.length > 0 ? mapReaderFormat(result.format) : "empty"
|
|
16596
|
+
events: result.events,
|
|
16597
|
+
format: result.events.length > 0 ? mapReaderFormat(result.format) : "empty"
|
|
16526
16598
|
};
|
|
16527
16599
|
} catch (error) {
|
|
16528
16600
|
if (isMissingFileError(error)) return void 0;
|
|
16529
16601
|
throw error;
|
|
16530
16602
|
}
|
|
16531
16603
|
}
|
|
16604
|
+
async function readRunTraceEvents(runId, traceDir) {
|
|
16605
|
+
const persisted = await readRunPersistedEvents(runId, traceDir);
|
|
16606
|
+
if (persisted === void 0) return void 0;
|
|
16607
|
+
const events = persistedInspectEventsToTraceEvents(persisted.events);
|
|
16608
|
+
return {
|
|
16609
|
+
events,
|
|
16610
|
+
format: events.length > 0 ? persisted.format : "empty"
|
|
16611
|
+
};
|
|
16612
|
+
}
|
|
16532
16613
|
|
|
16533
16614
|
// packages/cli/src/view.ts
|
|
16534
16615
|
function isModuleNotFound(e) {
|
|
@@ -18760,6 +18841,10 @@ function exportOpenInference(tree, options) {
|
|
|
18760
18841
|
|
|
18761
18842
|
// packages/core/src/exporters/otlp-json-exporter.ts
|
|
18762
18843
|
init_helpers();
|
|
18844
|
+
var OTLP_STATUS_CODE_UNSET = 0;
|
|
18845
|
+
var OTLP_STATUS_CODE_OK = 1;
|
|
18846
|
+
var OTLP_STATUS_CODE_ERROR = 2;
|
|
18847
|
+
var OTLP_SPAN_KIND_INTERNAL = 1;
|
|
18763
18848
|
function hexFrom2(seed, byteLen) {
|
|
18764
18849
|
return crypto__default.default.createHash("sha256").update(seed, "utf8").digest("hex").slice(0, byteLen * 2);
|
|
18765
18850
|
}
|
|
@@ -18772,7 +18857,19 @@ function stringAttr2(key, value) {
|
|
|
18772
18857
|
return { key, value: { stringValue: value } };
|
|
18773
18858
|
}
|
|
18774
18859
|
function intAttr(key, value) {
|
|
18775
|
-
return { key, value: { intValue: String(value) } };
|
|
18860
|
+
return { key, value: { intValue: String(Math.trunc(value)) } };
|
|
18861
|
+
}
|
|
18862
|
+
function doubleAttr(key, value) {
|
|
18863
|
+
return { key, value: { doubleValue: value } };
|
|
18864
|
+
}
|
|
18865
|
+
function boolAttr(key, value) {
|
|
18866
|
+
return { key, value: { boolValue: value } };
|
|
18867
|
+
}
|
|
18868
|
+
function numberAttr(key, value) {
|
|
18869
|
+
if (Number.isFinite(value) && !Number.isInteger(value)) {
|
|
18870
|
+
return doubleAttr(key, value);
|
|
18871
|
+
}
|
|
18872
|
+
return intAttr(key, value);
|
|
18776
18873
|
}
|
|
18777
18874
|
function genAiOperationName(kind) {
|
|
18778
18875
|
switch (kind) {
|
|
@@ -18786,10 +18883,27 @@ function genAiOperationName(kind) {
|
|
|
18786
18883
|
return void 0;
|
|
18787
18884
|
}
|
|
18788
18885
|
}
|
|
18886
|
+
function resolveSpanTimes(ev) {
|
|
18887
|
+
const startedAtMs = typeof ev.attributes?.startedAtMs === "number" && Number.isFinite(ev.attributes.startedAtMs) ? ev.attributes.startedAtMs : void 0;
|
|
18888
|
+
const endedAtMs = typeof ev.attributes?.endedAtMs === "number" && Number.isFinite(ev.attributes.endedAtMs) ? ev.attributes.endedAtMs : void 0;
|
|
18889
|
+
const startMs = startedAtMs ?? ev.timestamp;
|
|
18890
|
+
const startNs = String(unixNano2(startMs));
|
|
18891
|
+
if (endedAtMs !== void 0) {
|
|
18892
|
+
return { startNs, endNs: String(unixNano2(endedAtMs)) };
|
|
18893
|
+
}
|
|
18894
|
+
if (ev.durationMs !== void 0 && Number.isFinite(ev.durationMs)) {
|
|
18895
|
+
return {
|
|
18896
|
+
startNs,
|
|
18897
|
+
endNs: String(unixNano2(startMs) + unixNano2(ev.durationMs))
|
|
18898
|
+
};
|
|
18899
|
+
}
|
|
18900
|
+
return { startNs };
|
|
18901
|
+
}
|
|
18789
18902
|
function exportOtlpJson(tree, options) {
|
|
18790
18903
|
const warnings = [
|
|
18791
18904
|
"OTLP JSON export uses OTel GenAI-aligned attributes where applicable; experimental until verified against specific collectors.",
|
|
18792
|
-
"Not OTLP gRPC/protobuf \u2014 JSON mapping only. Generated locally; no network upload."
|
|
18905
|
+
"Not OTLP gRPC/protobuf \u2014 JSON mapping only. Generated locally; no network upload.",
|
|
18906
|
+
"Status and span kind use OTLP numeric enums (StatusCode 0/1/2, SpanKind INTERNAL=1)."
|
|
18793
18907
|
];
|
|
18794
18908
|
const traceId = hexFrom2(`trace:${tree.runId}`, 16);
|
|
18795
18909
|
const includeAttributes = options?.includeAttributes ?? false;
|
|
@@ -18801,11 +18915,7 @@ function exportOtlpJson(tree, options) {
|
|
|
18801
18915
|
const ev = n.event;
|
|
18802
18916
|
const spanId = hexFrom2(`${tree.runId}:${ev.eventId}`, 8);
|
|
18803
18917
|
const parentSpanId = ev.parentId ? hexFrom2(`${tree.runId}:${ev.parentId}`, 8) : void 0;
|
|
18804
|
-
const startNs =
|
|
18805
|
-
let endNs;
|
|
18806
|
-
if (ev.durationMs !== void 0 && Number.isFinite(ev.durationMs)) {
|
|
18807
|
-
endNs = String(unixNano2(ev.timestamp) + unixNano2(ev.durationMs));
|
|
18808
|
-
}
|
|
18918
|
+
const { startNs, endNs } = resolveSpanTimes(ev);
|
|
18809
18919
|
const attrs = [
|
|
18810
18920
|
stringAttr2("agent_inspect.kind", ev.kind),
|
|
18811
18921
|
stringAttr2("agent_inspect.confidence", ev.confidence),
|
|
@@ -18835,29 +18945,28 @@ function exportOtlpJson(tree, options) {
|
|
|
18835
18945
|
if (includeAttributes && meta2 && typeof meta2 === "object") {
|
|
18836
18946
|
for (const [k, v] of Object.entries(meta2)) {
|
|
18837
18947
|
if (k === "tokens" || k === "model") continue;
|
|
18838
|
-
if (typeof v === "string"
|
|
18839
|
-
attrs.push(
|
|
18840
|
-
|
|
18841
|
-
|
|
18842
|
-
|
|
18843
|
-
|
|
18844
|
-
);
|
|
18948
|
+
if (typeof v === "string") {
|
|
18949
|
+
attrs.push(stringAttr2(`agent_inspect.preview.${k}`, v.slice(0, maxLen)));
|
|
18950
|
+
} else if (typeof v === "number" && Number.isFinite(v)) {
|
|
18951
|
+
attrs.push(numberAttr(`agent_inspect.preview.${k}`, v));
|
|
18952
|
+
} else if (typeof v === "boolean") {
|
|
18953
|
+
attrs.push(boolAttr(`agent_inspect.preview.${k}`, v));
|
|
18845
18954
|
}
|
|
18846
18955
|
}
|
|
18847
18956
|
}
|
|
18848
|
-
let statusCode =
|
|
18957
|
+
let statusCode = OTLP_STATUS_CODE_UNSET;
|
|
18849
18958
|
let statusMessage;
|
|
18850
18959
|
if (ev.status === "error") {
|
|
18851
|
-
statusCode =
|
|
18960
|
+
statusCode = OTLP_STATUS_CODE_ERROR;
|
|
18852
18961
|
statusMessage = meta2 && typeof meta2.error === "object" && meta2.error !== null ? String(meta2.error.message ?? "error").slice(0, maxLen) : "error";
|
|
18853
18962
|
} else if (ev.status === "ok") {
|
|
18854
|
-
statusCode =
|
|
18963
|
+
statusCode = OTLP_STATUS_CODE_OK;
|
|
18855
18964
|
}
|
|
18856
18965
|
const spanJson = {
|
|
18857
18966
|
traceId,
|
|
18858
18967
|
spanId,
|
|
18859
18968
|
name: ev.name,
|
|
18860
|
-
kind:
|
|
18969
|
+
kind: OTLP_SPAN_KIND_INTERNAL,
|
|
18861
18970
|
startTimeUnixNano: startNs,
|
|
18862
18971
|
attributes: attrs,
|
|
18863
18972
|
status: {
|
|
@@ -18899,6 +19008,136 @@ function exportOtlpJson(tree, options) {
|
|
|
18899
19008
|
|
|
18900
19009
|
// packages/core/src/exporters/validation.ts
|
|
18901
19010
|
var EXPERIMENTAL = "Experimental compatibility export \u2014 verify against your target tooling before relying on it.";
|
|
19011
|
+
function pushPath(errors, path44, message) {
|
|
19012
|
+
errors.push(`${path44}: ${message}`);
|
|
19013
|
+
}
|
|
19014
|
+
function isRecord16(value) {
|
|
19015
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
19016
|
+
}
|
|
19017
|
+
function validateOtlpJson(content) {
|
|
19018
|
+
const errors = [];
|
|
19019
|
+
const warnings = [
|
|
19020
|
+
EXPERIMENTAL,
|
|
19021
|
+
"OTLP JSON mapping uses OTel GenAI-aligned attributes where applicable; collectors may require transformation.",
|
|
19022
|
+
"protocol-valid \u2260 profile-complete \u2260 fixture-complete \u2014 nested path diagnostics report protocol shape only."
|
|
19023
|
+
];
|
|
19024
|
+
let parsed;
|
|
19025
|
+
try {
|
|
19026
|
+
parsed = JSON.parse(content);
|
|
19027
|
+
} catch {
|
|
19028
|
+
pushPath(errors, "$", "OTLP JSON export is not valid JSON");
|
|
19029
|
+
return { ok: false, format: "otlp-json", errors, warnings };
|
|
19030
|
+
}
|
|
19031
|
+
if (!isRecord16(parsed)) {
|
|
19032
|
+
pushPath(errors, "$", "OTLP JSON export must be an object");
|
|
19033
|
+
return { ok: false, format: "otlp-json", errors, warnings };
|
|
19034
|
+
}
|
|
19035
|
+
if (!Array.isArray(parsed.resourceSpans)) {
|
|
19036
|
+
pushPath(errors, "$.resourceSpans", "must be an array");
|
|
19037
|
+
return { ok: false, format: "otlp-json", errors, warnings };
|
|
19038
|
+
}
|
|
19039
|
+
parsed.resourceSpans.forEach((resourceSpan, rsi) => {
|
|
19040
|
+
const rsPath = `$.resourceSpans[${rsi}]`;
|
|
19041
|
+
if (!isRecord16(resourceSpan)) {
|
|
19042
|
+
pushPath(errors, rsPath, "must be an object");
|
|
19043
|
+
return;
|
|
19044
|
+
}
|
|
19045
|
+
if (!Array.isArray(resourceSpan.scopeSpans)) {
|
|
19046
|
+
pushPath(errors, `${rsPath}.scopeSpans`, "must be an array");
|
|
19047
|
+
return;
|
|
19048
|
+
}
|
|
19049
|
+
resourceSpan.scopeSpans.forEach((scopeSpan, ssi) => {
|
|
19050
|
+
const ssPath = `${rsPath}.scopeSpans[${ssi}]`;
|
|
19051
|
+
if (!isRecord16(scopeSpan)) {
|
|
19052
|
+
pushPath(errors, ssPath, "must be an object");
|
|
19053
|
+
return;
|
|
19054
|
+
}
|
|
19055
|
+
if (!Array.isArray(scopeSpan.spans)) {
|
|
19056
|
+
pushPath(errors, `${ssPath}.spans`, "must be an array");
|
|
19057
|
+
return;
|
|
19058
|
+
}
|
|
19059
|
+
scopeSpan.spans.forEach((span, spi) => {
|
|
19060
|
+
const spanPath = `${ssPath}.spans[${spi}]`;
|
|
19061
|
+
if (!isRecord16(span)) {
|
|
19062
|
+
pushPath(errors, spanPath, "must be an object");
|
|
19063
|
+
return;
|
|
19064
|
+
}
|
|
19065
|
+
if (typeof span.traceId !== "string" || span.traceId.length === 0) {
|
|
19066
|
+
pushPath(errors, `${spanPath}.traceId`, "must be a non-empty string");
|
|
19067
|
+
}
|
|
19068
|
+
if (typeof span.spanId !== "string" || span.spanId.length === 0) {
|
|
19069
|
+
pushPath(errors, `${spanPath}.spanId`, "must be a non-empty string");
|
|
19070
|
+
}
|
|
19071
|
+
if (typeof span.name !== "string") {
|
|
19072
|
+
pushPath(errors, `${spanPath}.name`, "must be a string");
|
|
19073
|
+
}
|
|
19074
|
+
if (typeof span.startTimeUnixNano !== "string" || !/^\d+$/.test(span.startTimeUnixNano)) {
|
|
19075
|
+
pushPath(
|
|
19076
|
+
errors,
|
|
19077
|
+
`${spanPath}.startTimeUnixNano`,
|
|
19078
|
+
"must be a decimal-string 64-bit integer"
|
|
19079
|
+
);
|
|
19080
|
+
}
|
|
19081
|
+
if (span.endTimeUnixNano !== void 0 && (typeof span.endTimeUnixNano !== "string" || !/^\d+$/.test(span.endTimeUnixNano))) {
|
|
19082
|
+
pushPath(
|
|
19083
|
+
errors,
|
|
19084
|
+
`${spanPath}.endTimeUnixNano`,
|
|
19085
|
+
"must be a decimal-string 64-bit integer when present"
|
|
19086
|
+
);
|
|
19087
|
+
}
|
|
19088
|
+
if (typeof span.kind === "number") {
|
|
19089
|
+
if (!Number.isInteger(span.kind)) {
|
|
19090
|
+
pushPath(errors, `${spanPath}.kind`, "must be an integer SpanKind enum");
|
|
19091
|
+
}
|
|
19092
|
+
} else if (typeof span.kind === "string") {
|
|
19093
|
+
warnings.push(
|
|
19094
|
+
`${spanPath}.kind: string SpanKind enum is legacy; prefer numeric (INTERNAL=1)`
|
|
19095
|
+
);
|
|
19096
|
+
} else if (span.kind !== void 0) {
|
|
19097
|
+
pushPath(
|
|
19098
|
+
errors,
|
|
19099
|
+
`${spanPath}.kind`,
|
|
19100
|
+
"must be numeric SpanKind or historical string enum"
|
|
19101
|
+
);
|
|
19102
|
+
}
|
|
19103
|
+
if (!isRecord16(span.status)) {
|
|
19104
|
+
pushPath(errors, `${spanPath}.status`, "must be an object");
|
|
19105
|
+
} else {
|
|
19106
|
+
const code = span.status.code;
|
|
19107
|
+
if (typeof code === "number") {
|
|
19108
|
+
if (![0, 1, 2].includes(code)) {
|
|
19109
|
+
pushPath(
|
|
19110
|
+
errors,
|
|
19111
|
+
`${spanPath}.status.code`,
|
|
19112
|
+
"must be numeric StatusCode 0 (UNSET), 1 (OK), or 2 (ERROR)"
|
|
19113
|
+
);
|
|
19114
|
+
}
|
|
19115
|
+
} else if (typeof code === "string") {
|
|
19116
|
+
const upper = code.toUpperCase();
|
|
19117
|
+
if (upper !== "STATUS_CODE_UNSET" && upper !== "STATUS_CODE_OK" && upper !== "STATUS_CODE_ERROR" && upper !== "UNSET" && upper !== "OK" && upper !== "ERROR" && !/^[012]$/.test(code.trim())) {
|
|
19118
|
+
pushPath(
|
|
19119
|
+
errors,
|
|
19120
|
+
`${spanPath}.status.code`,
|
|
19121
|
+
"unrecognized StatusCode string"
|
|
19122
|
+
);
|
|
19123
|
+
} else {
|
|
19124
|
+
warnings.push(
|
|
19125
|
+
`${spanPath}.status.code: string StatusCode is legacy; prefer numeric 0/1/2`
|
|
19126
|
+
);
|
|
19127
|
+
}
|
|
19128
|
+
} else {
|
|
19129
|
+
pushPath(
|
|
19130
|
+
errors,
|
|
19131
|
+
`${spanPath}.status.code`,
|
|
19132
|
+
"must be numeric StatusCode 0/1/2 or historical string enum"
|
|
19133
|
+
);
|
|
19134
|
+
}
|
|
19135
|
+
}
|
|
19136
|
+
});
|
|
19137
|
+
});
|
|
19138
|
+
});
|
|
19139
|
+
return { ok: errors.length === 0, format: "otlp-json", errors, warnings };
|
|
19140
|
+
}
|
|
18902
19141
|
function validateExportContent(format, content) {
|
|
18903
19142
|
const errors = [];
|
|
18904
19143
|
const warnings = [EXPERIMENTAL];
|
|
@@ -18944,25 +19183,7 @@ function validateExportContent(format, content) {
|
|
|
18944
19183
|
return { ok: errors.length === 0, format, errors, warnings };
|
|
18945
19184
|
}
|
|
18946
19185
|
if (format === "otlp-json") {
|
|
18947
|
-
|
|
18948
|
-
try {
|
|
18949
|
-
parsed = JSON.parse(content);
|
|
18950
|
-
} catch {
|
|
18951
|
-
errors.push("OTLP JSON export is not valid JSON");
|
|
18952
|
-
return { ok: false, format, errors, warnings };
|
|
18953
|
-
}
|
|
18954
|
-
if (!parsed || typeof parsed !== "object") {
|
|
18955
|
-
errors.push("OTLP JSON export must be an object");
|
|
18956
|
-
return { ok: false, format, errors, warnings };
|
|
18957
|
-
}
|
|
18958
|
-
const o = parsed;
|
|
18959
|
-
if (!Array.isArray(o.resourceSpans)) {
|
|
18960
|
-
errors.push("OTLP JSON export must include resourceSpans array");
|
|
18961
|
-
}
|
|
18962
|
-
warnings.push(
|
|
18963
|
-
"OTLP JSON mapping uses OTel GenAI-aligned attributes where applicable; collectors may require transformation."
|
|
18964
|
-
);
|
|
18965
|
-
return { ok: errors.length === 0, format, errors, warnings };
|
|
19186
|
+
return validateOtlpJson(content);
|
|
18966
19187
|
}
|
|
18967
19188
|
errors.push(`Unsupported export format`);
|
|
18968
19189
|
return { ok: false, format, errors, warnings };
|
|
@@ -19366,7 +19587,7 @@ async function exportCommand(runId, options = {}) {
|
|
|
19366
19587
|
const traceDir = resolveTraceDir({ dir: options.dir });
|
|
19367
19588
|
let events;
|
|
19368
19589
|
try {
|
|
19369
|
-
const result2 = await
|
|
19590
|
+
const result2 = await readRunPersistedEvents(id, traceDir);
|
|
19370
19591
|
events = result2?.events ?? [];
|
|
19371
19592
|
} catch (e) {
|
|
19372
19593
|
const msg = e instanceof Error ? e.message : String(e);
|
|
@@ -19382,7 +19603,11 @@ Trace directory: ${traceDir}`);
|
|
|
19382
19603
|
}
|
|
19383
19604
|
let tree;
|
|
19384
19605
|
try {
|
|
19385
|
-
|
|
19606
|
+
const trees = persistedInspectEventsToRunTrees(events);
|
|
19607
|
+
tree = trees.find((candidate) => candidate.runId === id) ?? trees[0];
|
|
19608
|
+
if (tree === void 0) {
|
|
19609
|
+
throw new Error("No run tree could be built from persisted events");
|
|
19610
|
+
}
|
|
19386
19611
|
} catch (e) {
|
|
19387
19612
|
const msg = e instanceof Error ? e.message : String(e);
|
|
19388
19613
|
console.error(`[AgentInspect] export failed: ${msg}`);
|
|
@@ -19410,7 +19635,9 @@ Trace directory: ${traceDir}`);
|
|
|
19410
19635
|
await promises.mkdir(path33__default.default.dirname(outPath), { recursive: true });
|
|
19411
19636
|
await promises.writeFile(outPath, result.content, "utf-8");
|
|
19412
19637
|
const vlabel = validation !== void 0 ? validation.ok ? "ok" : "failed" : "skipped";
|
|
19413
|
-
console.
|
|
19638
|
+
console.error(
|
|
19639
|
+
`Wrote ${result.fileExtension} export to ${outPath} (validation: ${vlabel})`
|
|
19640
|
+
);
|
|
19414
19641
|
if (validation !== void 0 && !validation.ok) {
|
|
19415
19642
|
console.error("Validation errors:", validation.errors.join("; "));
|
|
19416
19643
|
}
|
|
@@ -19423,7 +19650,9 @@ Trace directory: ${traceDir}`);
|
|
|
19423
19650
|
warnings: [...result.warnings, ...validation?.warnings ?? []],
|
|
19424
19651
|
validation
|
|
19425
19652
|
};
|
|
19426
|
-
if (outPath
|
|
19653
|
+
if (outPath !== void 0) {
|
|
19654
|
+
payload.out = outPath;
|
|
19655
|
+
} else {
|
|
19427
19656
|
payload.content = result.content;
|
|
19428
19657
|
}
|
|
19429
19658
|
console.log(JSON.stringify(payload, null, 2));
|
|
@@ -20535,7 +20764,7 @@ var STRICT_PROFILE_EXTRA_KEYS2 = [
|
|
|
20535
20764
|
"retrieval",
|
|
20536
20765
|
"query"
|
|
20537
20766
|
];
|
|
20538
|
-
function
|
|
20767
|
+
function isRecord17(value) {
|
|
20539
20768
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20540
20769
|
}
|
|
20541
20770
|
function toKey2(key) {
|
|
@@ -20964,7 +21193,7 @@ var Redactor2 = class {
|
|
|
20964
21193
|
});
|
|
20965
21194
|
return out;
|
|
20966
21195
|
}
|
|
20967
|
-
if (
|
|
21196
|
+
if (isRecord17(value)) {
|
|
20968
21197
|
if (state.seen.has(value)) return state.seen.get(value);
|
|
20969
21198
|
const out = {};
|
|
20970
21199
|
state.seen.set(value, out);
|
|
@@ -20999,7 +21228,7 @@ var REDACTION_POLICY_LIMITS = {
|
|
|
20999
21228
|
};
|
|
21000
21229
|
var ALLOWED_TOP_LEVEL = /* @__PURE__ */ new Set(["version", "extraKeys", "patterns"]);
|
|
21001
21230
|
var ALLOWED_PATTERN_FIELDS = /* @__PURE__ */ new Set(["id", "type", "value", "severity"]);
|
|
21002
|
-
function
|
|
21231
|
+
function isRecord18(value) {
|
|
21003
21232
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
21004
21233
|
}
|
|
21005
21234
|
function rejectRemotePolicyPath(policyPath) {
|
|
@@ -21039,7 +21268,7 @@ function rejectUnknownFields(record, allowed, label) {
|
|
|
21039
21268
|
}
|
|
21040
21269
|
function compilePatternDetector(input3, index) {
|
|
21041
21270
|
const label = `patterns[${index}]`;
|
|
21042
|
-
if (!
|
|
21271
|
+
if (!isRecord18(input3)) throw new Error(`${label} must be an object.`);
|
|
21043
21272
|
const typeEarly = input3.type;
|
|
21044
21273
|
if (typeEarly === "typed") {
|
|
21045
21274
|
throw new Error(
|
|
@@ -21094,7 +21323,7 @@ function compilePatternDetector(input3, index) {
|
|
|
21094
21323
|
};
|
|
21095
21324
|
}
|
|
21096
21325
|
function compileRedactionPolicy(raw, policyPath) {
|
|
21097
|
-
if (!
|
|
21326
|
+
if (!isRecord18(raw)) {
|
|
21098
21327
|
throw new Error(`Redaction policy must be a JSON object (${policyPath}).`);
|
|
21099
21328
|
}
|
|
21100
21329
|
rejectUnknownFields(raw, ALLOWED_TOP_LEVEL, "Redaction policy");
|
|
@@ -22130,7 +22359,7 @@ async function openCommand(input3, options = {}, stdin = process.stdin) {
|
|
|
22130
22359
|
|
|
22131
22360
|
// packages/cli/src/migrate.ts
|
|
22132
22361
|
init_advanced();
|
|
22133
|
-
function
|
|
22362
|
+
function isRecord19(value) {
|
|
22134
22363
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
22135
22364
|
}
|
|
22136
22365
|
function parseTarget(value) {
|
|
@@ -22139,7 +22368,7 @@ function parseTarget(value) {
|
|
|
22139
22368
|
throw new Error('Unsupported migration target. Use "--to 1.0".');
|
|
22140
22369
|
}
|
|
22141
22370
|
function formatOf(value) {
|
|
22142
|
-
if (!
|
|
22371
|
+
if (!isRecord19(value)) return "unknown";
|
|
22143
22372
|
if (value.schemaVersion === "0.1") return "0.1";
|
|
22144
22373
|
if (value.schemaVersion === "0.2") return "0.2";
|
|
22145
22374
|
if (value.schemaVersion === "1.0") return "1.0";
|
|
@@ -28663,16 +28892,120 @@ function demoTemplate(framework) {
|
|
|
28663
28892
|
switch (framework) {
|
|
28664
28893
|
case "ai-sdk":
|
|
28665
28894
|
return `/**
|
|
28666
|
-
* AI SDK starter \u2014
|
|
28667
|
-
* Install: npm install agent-inspect @agent-inspect/ai-sdk ai
|
|
28895
|
+
* AI SDK starter \u2014 keyless MockLanguageModelV3 + @agent-inspect/ai-sdk telemetry.
|
|
28896
|
+
* Install: npm install agent-inspect @agent-inspect/ai-sdk ai@6.0.210 zod
|
|
28668
28897
|
*/
|
|
28669
|
-
import {
|
|
28898
|
+
import { generateText, stepCountIs, tool } from "ai";
|
|
28899
|
+
import { MockLanguageModelV3 } from "ai/test";
|
|
28900
|
+
import { agentInspect } from "@agent-inspect/ai-sdk";
|
|
28901
|
+
import { z } from "zod";
|
|
28902
|
+
import { readdirSync, readFileSync } from "node:fs";
|
|
28903
|
+
import path from "node:path";
|
|
28904
|
+
|
|
28905
|
+
const TRACE_DIR = ".agent-inspect";
|
|
28906
|
+
const ANSWER = "You have 2 orders";
|
|
28907
|
+
const CORRECT_RUN = "ai-sdk-demo-correct";
|
|
28908
|
+
const WRONG_RUN = "ai-sdk-demo-wrong";
|
|
28909
|
+
|
|
28910
|
+
const usage = {
|
|
28911
|
+
inputTokens: { total: 4, noCache: 4, cacheRead: 0, cacheWrite: 0 },
|
|
28912
|
+
outputTokens: { total: 3, text: 3, reasoning: 0 },
|
|
28913
|
+
};
|
|
28914
|
+
|
|
28915
|
+
const lookupOrders = tool({
|
|
28916
|
+
description: "Look up orders for a user",
|
|
28917
|
+
inputSchema: z.object({ userId: z.string() }),
|
|
28918
|
+
execute: async () => ({ orders: 2 }),
|
|
28919
|
+
});
|
|
28920
|
+
|
|
28921
|
+
const deleteOrders = tool({
|
|
28922
|
+
description: "Delete orders for a user (wrong path)",
|
|
28923
|
+
inputSchema: z.object({ userId: z.string() }),
|
|
28924
|
+
execute: async () => ({ orders: 2 }),
|
|
28925
|
+
});
|
|
28926
|
+
|
|
28927
|
+
async function runPath(runName, toolName) {
|
|
28928
|
+
const integration = agentInspect({
|
|
28929
|
+
traceDir: TRACE_DIR,
|
|
28930
|
+
runName,
|
|
28931
|
+
capture: "metadata-only",
|
|
28932
|
+
});
|
|
28933
|
+
let step = 0;
|
|
28934
|
+
try {
|
|
28935
|
+
const result = await generateText({
|
|
28936
|
+
model: new MockLanguageModelV3({
|
|
28937
|
+
provider: "fixture-provider",
|
|
28938
|
+
modelId: "fixture-tools",
|
|
28939
|
+
doGenerate: async () => {
|
|
28940
|
+
step += 1;
|
|
28941
|
+
if (step === 1) {
|
|
28942
|
+
return {
|
|
28943
|
+
content: [
|
|
28944
|
+
{
|
|
28945
|
+
type: "tool-call",
|
|
28946
|
+
toolCallId: \`call-\${toolName}\`,
|
|
28947
|
+
toolName,
|
|
28948
|
+
input: { userId: "u1" },
|
|
28949
|
+
},
|
|
28950
|
+
],
|
|
28951
|
+
finishReason: { unified: "tool-calls", raw: "tool-calls" },
|
|
28952
|
+
usage,
|
|
28953
|
+
warnings: [],
|
|
28954
|
+
};
|
|
28955
|
+
}
|
|
28956
|
+
return {
|
|
28957
|
+
content: [{ type: "text", text: ANSWER }],
|
|
28958
|
+
finishReason: { unified: "stop", raw: "stop" },
|
|
28959
|
+
usage,
|
|
28960
|
+
warnings: [],
|
|
28961
|
+
};
|
|
28962
|
+
},
|
|
28963
|
+
}),
|
|
28964
|
+
tools: { lookup_orders: lookupOrders, delete_orders: deleteOrders },
|
|
28965
|
+
prompt: "How many orders do I have?",
|
|
28966
|
+
stopWhen: stepCountIs(5),
|
|
28967
|
+
experimental_telemetry: {
|
|
28968
|
+
isEnabled: true,
|
|
28969
|
+
recordInputs: false,
|
|
28970
|
+
recordOutputs: false,
|
|
28971
|
+
integrations: [integration],
|
|
28972
|
+
},
|
|
28973
|
+
});
|
|
28974
|
+
if (result.text !== ANSWER) {
|
|
28975
|
+
throw new Error(\`unexpected answer for \${runName}: \${result.text}\`);
|
|
28976
|
+
}
|
|
28977
|
+
} finally {
|
|
28978
|
+
await integration.flush();
|
|
28979
|
+
await integration.close();
|
|
28980
|
+
}
|
|
28981
|
+
}
|
|
28982
|
+
|
|
28983
|
+
function selectRunIdByName(runName) {
|
|
28984
|
+
const files = readdirSync(TRACE_DIR).filter((f) => f.endsWith(".jsonl"));
|
|
28985
|
+
const matches = [];
|
|
28986
|
+
for (const file of files) {
|
|
28987
|
+
const text = readFileSync(path.join(TRACE_DIR, file), "utf8");
|
|
28988
|
+
if (text.includes(\`"name":"\${runName}"\`) || text.includes(\`"name": "\${runName}"\`)) {
|
|
28989
|
+
matches.push(file.replace(/\\.jsonl$/, ""));
|
|
28990
|
+
}
|
|
28991
|
+
}
|
|
28992
|
+
if (matches.length !== 1) {
|
|
28993
|
+
throw new Error(
|
|
28994
|
+
\`expected exactly one run named \${runName}, found \${matches.length}\`,
|
|
28995
|
+
);
|
|
28996
|
+
}
|
|
28997
|
+
return matches[0];
|
|
28998
|
+
}
|
|
28670
28999
|
|
|
28671
29000
|
async function main() {
|
|
28672
|
-
await
|
|
28673
|
-
|
|
28674
|
-
|
|
29001
|
+
await runPath(CORRECT_RUN, "lookup_orders");
|
|
29002
|
+
await runPath(WRONG_RUN, "delete_orders");
|
|
29003
|
+
const correctId = selectRunIdByName(CORRECT_RUN);
|
|
29004
|
+
const wrongId = selectRunIdByName(WRONG_RUN);
|
|
28675
29005
|
console.log("Trace written to .agent-inspect/");
|
|
29006
|
+
console.log(\`Correct path runId: \${correctId}\`);
|
|
29007
|
+
console.log(\`Wrong path runId: \${wrongId}\`);
|
|
29008
|
+
console.log(\`Next: npx agent-inspect check \${correctId} --required-tool lookup_orders\`);
|
|
28676
29009
|
}
|
|
28677
29010
|
|
|
28678
29011
|
main().catch((error) => {
|