agent-inspect 6.31.6 → 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.
- package/CHANGELOG.md +13 -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-6FE47XSF.mjs} +119 -34
- package/packages/cli/dist/chunk-6FE47XSF.mjs.map +1 -0
- package/packages/cli/dist/index.cjs +569 -102
- package/packages/cli/dist/index.cjs.map +1 -1
- package/packages/cli/dist/index.mjs +454 -74
- package/packages/cli/dist/index.mjs.map +1 -1
- package/packages/cli/dist/{src-H22KNWAZ.mjs → src-NXAYHG34.mjs} +3 -3
- package/packages/cli/dist/{src-H22KNWAZ.mjs.map → src-NXAYHG34.mjs.map} +1 -1
- package/packages/core/dist/advanced.cjs +116 -31
- package/packages/core/dist/advanced.cjs.map +1 -1
- package/packages/core/dist/advanced.mjs +7 -7
- package/packages/core/dist/checks.mjs +2 -2
- package/packages/core/dist/{chunk-LXYPM2ZO.mjs → chunk-2CCRUI42.mjs} +19 -318
- package/packages/core/dist/chunk-2CCRUI42.mjs.map +1 -0
- package/packages/core/dist/{chunk-Q5SLKV2Y.mjs → chunk-2IRRUNIN.mjs} +28 -5
- package/packages/core/dist/chunk-2IRRUNIN.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-OSGNGRHF.mjs → chunk-IJJSPJXV.mjs} +51 -25
- package/packages/core/dist/chunk-IJJSPJXV.mjs.map +1 -0
- package/packages/core/dist/chunk-L5WLVBW4.mjs +355 -0
- package/packages/core/dist/chunk-L5WLVBW4.mjs.map +1 -0
- package/packages/core/dist/exporters.cjs +327 -58
- package/packages/core/dist/exporters.cjs.map +1 -1
- package/packages/core/dist/exporters.mjs +281 -49
- package/packages/core/dist/exporters.mjs.map +1 -1
- package/packages/core/dist/persisted.cjs +361 -9
- package/packages/core/dist/persisted.cjs.map +1 -1
- package/packages/core/dist/persisted.d.cts +8 -1
- package/packages/core/dist/persisted.d.ts +8 -1
- package/packages/core/dist/persisted.mjs +3 -2
- package/packages/core/dist/persisted.mjs.map +1 -1
- package/packages/core/dist/readers.cjs +425 -100
- package/packages/core/dist/readers.cjs.map +1 -1
- package/packages/core/dist/readers.mjs +3 -3
- 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-FWK3Q3OJ.mjs +0 -56
- package/packages/core/dist/chunk-FWK3Q3OJ.mjs.map +0 -1
- package/packages/core/dist/chunk-LXYPM2ZO.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) {
|
|
@@ -12563,14 +12618,20 @@ var init_to_inspect_event = __esm({
|
|
|
12563
12618
|
});
|
|
12564
12619
|
|
|
12565
12620
|
// packages/core/src/persisted/tree-bridge.ts
|
|
12621
|
+
function logicalToPersisted(event) {
|
|
12622
|
+
const { sourceEventIds: _sourceEventIds, projection: _projection, ...rest } = event;
|
|
12623
|
+
return rest;
|
|
12624
|
+
}
|
|
12566
12625
|
function persistedInspectEventsToRunTrees(events, options) {
|
|
12567
|
-
const
|
|
12626
|
+
const sourceEvents = options?.coalesceLifecycle === true ? projectLogicalEvents(events).logicalEvents.map(logicalToPersisted) : events;
|
|
12627
|
+
const inspectEvents = persistedInspectEventsToInspectEvents(sourceEvents, {
|
|
12568
12628
|
skipInvalid: options?.skipInvalid
|
|
12569
12629
|
});
|
|
12570
12630
|
return new TreeBuilder().build(inspectEvents);
|
|
12571
12631
|
}
|
|
12572
12632
|
var init_tree_bridge = __esm({
|
|
12573
12633
|
"packages/core/src/persisted/tree-bridge.ts"() {
|
|
12634
|
+
init_logical_events();
|
|
12574
12635
|
init_tree_builder();
|
|
12575
12636
|
init_from_trace_event();
|
|
12576
12637
|
init_to_inspect_event();
|
|
@@ -13191,7 +13252,7 @@ function mapOpenInferenceSpan(span, index, version2) {
|
|
|
13191
13252
|
const errorMessage = isRecord11(span.status) && typeof span.status.message === "string" ? span.status.message : void 0;
|
|
13192
13253
|
const event = {
|
|
13193
13254
|
schemaVersion: "0.2",
|
|
13194
|
-
eventId: typeof rawAttributes["agent_inspect.event_id"] === "string" ? rawAttributes["agent_inspect.event_id"] : spanId
|
|
13255
|
+
eventId: typeof rawAttributes["agent_inspect.event_id"] === "string" ? rawAttributes["agent_inspect.event_id"] : `${traceId}:${spanId}`,
|
|
13195
13256
|
runId: typeof rawAttributes["agent_inspect.run_id"] === "string" ? rawAttributes["agent_inspect.run_id"] : traceId,
|
|
13196
13257
|
kind,
|
|
13197
13258
|
name,
|
|
@@ -13242,12 +13303,16 @@ function mapOpenInferenceEvents(document) {
|
|
|
13242
13303
|
const mapped = document.spans.map(
|
|
13243
13304
|
(span, index) => mapOpenInferenceSpan(span, index, document.version)
|
|
13244
13305
|
);
|
|
13245
|
-
const
|
|
13246
|
-
mapped.map((span) =>
|
|
13306
|
+
const spanKeyToEventId = new Map(
|
|
13307
|
+
mapped.map((span) => {
|
|
13308
|
+
const traceId = typeof span.event.trace?.traceId === "string" ? span.event.trace.traceId : "";
|
|
13309
|
+
return [`${traceId}:${span.spanId}`, span.event.eventId];
|
|
13310
|
+
})
|
|
13247
13311
|
);
|
|
13248
13312
|
for (const span of mapped) {
|
|
13249
13313
|
if (span.parentSpanId === void 0) continue;
|
|
13250
|
-
span.event.
|
|
13314
|
+
const traceId = typeof span.event.trace?.traceId === "string" ? span.event.trace.traceId : "";
|
|
13315
|
+
span.event.parentId = spanKeyToEventId.get(`${traceId}:${span.parentSpanId}`) ?? span.parentSpanId;
|
|
13251
13316
|
}
|
|
13252
13317
|
return {
|
|
13253
13318
|
events: mapped.map((span) => span.event),
|
|
@@ -13461,20 +13526,38 @@ function extractOtlpDocument(root) {
|
|
|
13461
13526
|
function mapOtlpStatus(status) {
|
|
13462
13527
|
if (!isRecord11(status)) return void 0;
|
|
13463
13528
|
const rawCode = status.code;
|
|
13464
|
-
if (typeof rawCode
|
|
13465
|
-
|
|
13466
|
-
|
|
13467
|
-
|
|
13468
|
-
|
|
13469
|
-
|
|
13470
|
-
|
|
13471
|
-
|
|
13472
|
-
|
|
13473
|
-
|
|
13474
|
-
|
|
13475
|
-
|
|
13476
|
-
|
|
13529
|
+
if (typeof rawCode === "number" && Number.isFinite(rawCode)) {
|
|
13530
|
+
switch (rawCode) {
|
|
13531
|
+
case 0:
|
|
13532
|
+
return "unknown";
|
|
13533
|
+
case 1:
|
|
13534
|
+
return "ok";
|
|
13535
|
+
case 2:
|
|
13536
|
+
return "error";
|
|
13537
|
+
default:
|
|
13538
|
+
return "unknown";
|
|
13539
|
+
}
|
|
13540
|
+
}
|
|
13541
|
+
if (typeof rawCode === "string") {
|
|
13542
|
+
const trimmed = rawCode.trim();
|
|
13543
|
+
if (/^\d+$/.test(trimmed)) {
|
|
13544
|
+
return mapOtlpStatus({ code: Number(trimmed) });
|
|
13545
|
+
}
|
|
13546
|
+
switch (trimmed.toUpperCase()) {
|
|
13547
|
+
case "STATUS_CODE_OK":
|
|
13548
|
+
case "OK":
|
|
13549
|
+
return "ok";
|
|
13550
|
+
case "STATUS_CODE_ERROR":
|
|
13551
|
+
case "ERROR":
|
|
13552
|
+
return "error";
|
|
13553
|
+
case "STATUS_CODE_UNSET":
|
|
13554
|
+
case "UNSET":
|
|
13555
|
+
return "unknown";
|
|
13556
|
+
default:
|
|
13557
|
+
return "unknown";
|
|
13558
|
+
}
|
|
13477
13559
|
}
|
|
13560
|
+
return void 0;
|
|
13478
13561
|
}
|
|
13479
13562
|
function readOtlpKind(attributes, pathPrefix) {
|
|
13480
13563
|
const warnings = [];
|
|
@@ -13700,7 +13783,7 @@ function mapOtlpSpan(context) {
|
|
|
13700
13783
|
const errorMessage = isRecord11(span.status) && typeof span.status.message === "string" ? span.status.message : void 0;
|
|
13701
13784
|
const event = {
|
|
13702
13785
|
schemaVersion: "0.2",
|
|
13703
|
-
eventId: typeof parsedSpanAttributes.attributes["agent_inspect.event_id"] === "string" ? parsedSpanAttributes.attributes["agent_inspect.event_id"] : spanId
|
|
13786
|
+
eventId: typeof parsedSpanAttributes.attributes["agent_inspect.event_id"] === "string" ? parsedSpanAttributes.attributes["agent_inspect.event_id"] : `${traceId}:${spanId}`,
|
|
13704
13787
|
runId: typeof parsedSpanAttributes.attributes["agent_inspect.run_id"] === "string" ? parsedSpanAttributes.attributes["agent_inspect.run_id"] : traceId,
|
|
13705
13788
|
kind,
|
|
13706
13789
|
name: readStringField(span, ["name"]) ?? spanId,
|
|
@@ -13749,12 +13832,16 @@ function mapOtlpSpan(context) {
|
|
|
13749
13832
|
}
|
|
13750
13833
|
function mapOtlpEventsToPersisted(document) {
|
|
13751
13834
|
const mapped = document.spans.map((span) => mapOtlpSpan(span));
|
|
13752
|
-
const
|
|
13753
|
-
mapped.map((span) =>
|
|
13835
|
+
const spanKeyToEventId = new Map(
|
|
13836
|
+
mapped.map((span) => {
|
|
13837
|
+
const traceId = typeof span.event.trace?.traceId === "string" ? span.event.trace.traceId : "";
|
|
13838
|
+
return [`${traceId}:${span.spanId}`, span.event.eventId];
|
|
13839
|
+
})
|
|
13754
13840
|
);
|
|
13755
13841
|
for (const span of mapped) {
|
|
13756
13842
|
if (span.parentSpanId === void 0) continue;
|
|
13757
|
-
span.event.
|
|
13843
|
+
const traceId = typeof span.event.trace?.traceId === "string" ? span.event.trace.traceId : "";
|
|
13844
|
+
span.event.parentId = spanKeyToEventId.get(`${traceId}:${span.parentSpanId}`) ?? span.parentSpanId;
|
|
13758
13845
|
}
|
|
13759
13846
|
return {
|
|
13760
13847
|
events: mapped.map((span) => span.event),
|
|
@@ -16162,7 +16249,7 @@ var init_src = __esm({
|
|
|
16162
16249
|
});
|
|
16163
16250
|
|
|
16164
16251
|
// package.json
|
|
16165
|
-
var version = "6.31.
|
|
16252
|
+
var version = "6.31.8";
|
|
16166
16253
|
|
|
16167
16254
|
// packages/cli/src/list.ts
|
|
16168
16255
|
init_advanced();
|
|
@@ -16511,7 +16598,7 @@ function mapReaderFormat(format) {
|
|
|
16511
16598
|
function isMissingFileError(error) {
|
|
16512
16599
|
return error !== null && typeof error === "object" && "code" in error && error.code === "ENOENT";
|
|
16513
16600
|
}
|
|
16514
|
-
async function
|
|
16601
|
+
async function readRunPersistedEvents(runId, traceDir) {
|
|
16515
16602
|
const filePath = getTraceFilePath(runId, traceDir);
|
|
16516
16603
|
try {
|
|
16517
16604
|
await promises.access(filePath);
|
|
@@ -16519,16 +16606,24 @@ async function readRunTraceEvents(runId, traceDir) {
|
|
|
16519
16606
|
{ type: "file", path: filePath },
|
|
16520
16607
|
{ format: "agent-inspect-jsonl" }
|
|
16521
16608
|
);
|
|
16522
|
-
const events = persistedInspectEventsToTraceEvents(result.events);
|
|
16523
16609
|
return {
|
|
16524
|
-
events,
|
|
16525
|
-
format: events.length > 0 ? mapReaderFormat(result.format) : "empty"
|
|
16610
|
+
events: result.events,
|
|
16611
|
+
format: result.events.length > 0 ? mapReaderFormat(result.format) : "empty"
|
|
16526
16612
|
};
|
|
16527
16613
|
} catch (error) {
|
|
16528
16614
|
if (isMissingFileError(error)) return void 0;
|
|
16529
16615
|
throw error;
|
|
16530
16616
|
}
|
|
16531
16617
|
}
|
|
16618
|
+
async function readRunTraceEvents(runId, traceDir) {
|
|
16619
|
+
const persisted = await readRunPersistedEvents(runId, traceDir);
|
|
16620
|
+
if (persisted === void 0) return void 0;
|
|
16621
|
+
const events = persistedInspectEventsToTraceEvents(persisted.events);
|
|
16622
|
+
return {
|
|
16623
|
+
events,
|
|
16624
|
+
format: events.length > 0 ? persisted.format : "empty"
|
|
16625
|
+
};
|
|
16626
|
+
}
|
|
16532
16627
|
|
|
16533
16628
|
// packages/cli/src/view.ts
|
|
16534
16629
|
function isModuleNotFound(e) {
|
|
@@ -18689,11 +18784,13 @@ function exportOpenInference(tree, options) {
|
|
|
18689
18784
|
endNs = startNs + unixNano(ev.durationMs);
|
|
18690
18785
|
}
|
|
18691
18786
|
const { openInferenceKind } = mapInspectKindToOI(ev.kind, warnings);
|
|
18787
|
+
const meta2 = ev.attributes;
|
|
18788
|
+
const originalSource = typeof meta2?.originalSourceType === "string" && meta2.originalSourceType.trim() !== "" ? meta2.originalSourceType.trim() : ev.source.type;
|
|
18692
18789
|
const attrs = {
|
|
18693
18790
|
"openinference.span.kind": openInferenceKind,
|
|
18694
18791
|
"agent_inspect.kind": ev.kind,
|
|
18695
18792
|
"agent_inspect.confidence": ev.confidence,
|
|
18696
|
-
"agent_inspect.source.type":
|
|
18793
|
+
"agent_inspect.source.type": originalSource,
|
|
18697
18794
|
"agent_inspect.run_id": tree.runId,
|
|
18698
18795
|
"agent_inspect.event_id": ev.eventId,
|
|
18699
18796
|
"agent_inspect.status": ev.status ?? "unset"
|
|
@@ -18701,9 +18798,9 @@ function exportOpenInference(tree, options) {
|
|
|
18701
18798
|
if (ev.durationMs !== void 0) {
|
|
18702
18799
|
attrs["agent_inspect.duration_ms"] = ev.durationMs;
|
|
18703
18800
|
}
|
|
18704
|
-
const
|
|
18705
|
-
if (
|
|
18706
|
-
attrs["llm.model_name"] =
|
|
18801
|
+
const requestModel = (typeof meta2?.model === "string" && meta2.model.trim() !== "" ? meta2.model : void 0) ?? (typeof meta2?.modelId === "string" && meta2.modelId.trim() !== "" ? meta2.modelId : void 0);
|
|
18802
|
+
if (requestModel !== void 0) {
|
|
18803
|
+
attrs["llm.model_name"] = requestModel;
|
|
18707
18804
|
}
|
|
18708
18805
|
const tokens = meta2?.tokens;
|
|
18709
18806
|
if (tokens && typeof tokens === "object" && tokens !== null) {
|
|
@@ -18713,8 +18810,9 @@ function exportOpenInference(tree, options) {
|
|
|
18713
18810
|
if (typeof outp === "number") attrs["llm.token_count.completion"] = outp;
|
|
18714
18811
|
}
|
|
18715
18812
|
if (includeAttributes && meta2 && typeof meta2 === "object") {
|
|
18813
|
+
const skipKeys = /* @__PURE__ */ new Set(["tokens", "model", "modelId", "originalSourceType"]);
|
|
18716
18814
|
for (const [k, v] of Object.entries(meta2)) {
|
|
18717
|
-
if (k
|
|
18815
|
+
if (skipKeys.has(k)) continue;
|
|
18718
18816
|
if (v !== void 0 && v !== null && typeof v !== "object") {
|
|
18719
18817
|
attrs[`agent_inspect.preview.${k}`] = typeof v === "string" ? v.slice(0, maxLen) : v;
|
|
18720
18818
|
}
|
|
@@ -18760,6 +18858,10 @@ function exportOpenInference(tree, options) {
|
|
|
18760
18858
|
|
|
18761
18859
|
// packages/core/src/exporters/otlp-json-exporter.ts
|
|
18762
18860
|
init_helpers();
|
|
18861
|
+
var OTLP_STATUS_CODE_UNSET = 0;
|
|
18862
|
+
var OTLP_STATUS_CODE_OK = 1;
|
|
18863
|
+
var OTLP_STATUS_CODE_ERROR = 2;
|
|
18864
|
+
var OTLP_SPAN_KIND_INTERNAL = 1;
|
|
18763
18865
|
function hexFrom2(seed, byteLen) {
|
|
18764
18866
|
return crypto__default.default.createHash("sha256").update(seed, "utf8").digest("hex").slice(0, byteLen * 2);
|
|
18765
18867
|
}
|
|
@@ -18772,7 +18874,19 @@ function stringAttr2(key, value) {
|
|
|
18772
18874
|
return { key, value: { stringValue: value } };
|
|
18773
18875
|
}
|
|
18774
18876
|
function intAttr(key, value) {
|
|
18775
|
-
return { key, value: { intValue: String(value) } };
|
|
18877
|
+
return { key, value: { intValue: String(Math.trunc(value)) } };
|
|
18878
|
+
}
|
|
18879
|
+
function doubleAttr(key, value) {
|
|
18880
|
+
return { key, value: { doubleValue: value } };
|
|
18881
|
+
}
|
|
18882
|
+
function boolAttr(key, value) {
|
|
18883
|
+
return { key, value: { boolValue: value } };
|
|
18884
|
+
}
|
|
18885
|
+
function numberAttr(key, value) {
|
|
18886
|
+
if (Number.isFinite(value) && !Number.isInteger(value)) {
|
|
18887
|
+
return doubleAttr(key, value);
|
|
18888
|
+
}
|
|
18889
|
+
return intAttr(key, value);
|
|
18776
18890
|
}
|
|
18777
18891
|
function genAiOperationName(kind) {
|
|
18778
18892
|
switch (kind) {
|
|
@@ -18786,10 +18900,27 @@ function genAiOperationName(kind) {
|
|
|
18786
18900
|
return void 0;
|
|
18787
18901
|
}
|
|
18788
18902
|
}
|
|
18903
|
+
function resolveSpanTimes(ev) {
|
|
18904
|
+
const startedAtMs = typeof ev.attributes?.startedAtMs === "number" && Number.isFinite(ev.attributes.startedAtMs) ? ev.attributes.startedAtMs : void 0;
|
|
18905
|
+
const endedAtMs = typeof ev.attributes?.endedAtMs === "number" && Number.isFinite(ev.attributes.endedAtMs) ? ev.attributes.endedAtMs : void 0;
|
|
18906
|
+
const startMs = startedAtMs ?? ev.timestamp;
|
|
18907
|
+
const startNs = String(unixNano2(startMs));
|
|
18908
|
+
if (endedAtMs !== void 0) {
|
|
18909
|
+
return { startNs, endNs: String(unixNano2(endedAtMs)) };
|
|
18910
|
+
}
|
|
18911
|
+
if (ev.durationMs !== void 0 && Number.isFinite(ev.durationMs)) {
|
|
18912
|
+
return {
|
|
18913
|
+
startNs,
|
|
18914
|
+
endNs: String(unixNano2(startMs) + unixNano2(ev.durationMs))
|
|
18915
|
+
};
|
|
18916
|
+
}
|
|
18917
|
+
return { startNs };
|
|
18918
|
+
}
|
|
18789
18919
|
function exportOtlpJson(tree, options) {
|
|
18790
18920
|
const warnings = [
|
|
18791
18921
|
"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."
|
|
18922
|
+
"Not OTLP gRPC/protobuf \u2014 JSON mapping only. Generated locally; no network upload.",
|
|
18923
|
+
"Status and span kind use OTLP numeric enums (StatusCode 0/1/2, SpanKind INTERNAL=1)."
|
|
18793
18924
|
];
|
|
18794
18925
|
const traceId = hexFrom2(`trace:${tree.runId}`, 16);
|
|
18795
18926
|
const includeAttributes = options?.includeAttributes ?? false;
|
|
@@ -18801,29 +18932,34 @@ function exportOtlpJson(tree, options) {
|
|
|
18801
18932
|
const ev = n.event;
|
|
18802
18933
|
const spanId = hexFrom2(`${tree.runId}:${ev.eventId}`, 8);
|
|
18803
18934
|
const parentSpanId = ev.parentId ? hexFrom2(`${tree.runId}:${ev.parentId}`, 8) : void 0;
|
|
18804
|
-
const startNs =
|
|
18805
|
-
|
|
18806
|
-
|
|
18807
|
-
endNs = String(unixNano2(ev.timestamp) + unixNano2(ev.durationMs));
|
|
18808
|
-
}
|
|
18935
|
+
const { startNs, endNs } = resolveSpanTimes(ev);
|
|
18936
|
+
const meta2 = ev.attributes;
|
|
18937
|
+
const originalSource = typeof meta2?.originalSourceType === "string" && meta2.originalSourceType.trim() !== "" ? meta2.originalSourceType.trim() : ev.source.type;
|
|
18809
18938
|
const attrs = [
|
|
18810
18939
|
stringAttr2("agent_inspect.kind", ev.kind),
|
|
18811
18940
|
stringAttr2("agent_inspect.confidence", ev.confidence),
|
|
18812
|
-
stringAttr2("agent_inspect.source.type",
|
|
18941
|
+
stringAttr2("agent_inspect.source.type", originalSource),
|
|
18813
18942
|
stringAttr2("agent_inspect.run_id", tree.runId),
|
|
18814
18943
|
stringAttr2("agent_inspect.event_id", ev.eventId),
|
|
18815
18944
|
stringAttr2("agent_inspect.status", ev.status ?? "unset")
|
|
18816
18945
|
];
|
|
18817
18946
|
if (ev.durationMs !== void 0) {
|
|
18818
|
-
attrs.push(
|
|
18947
|
+
attrs.push(numberAttr("agent_inspect.duration_ms", ev.durationMs));
|
|
18819
18948
|
}
|
|
18820
18949
|
const op = genAiOperationName(ev.kind);
|
|
18821
18950
|
if (op !== void 0) {
|
|
18822
18951
|
attrs.push(stringAttr2("gen_ai.operation.name", op));
|
|
18823
18952
|
}
|
|
18824
|
-
const
|
|
18825
|
-
if (
|
|
18826
|
-
attrs.push(stringAttr2("gen_ai.request.model",
|
|
18953
|
+
const requestModel = (typeof meta2?.model === "string" && meta2.model.trim() !== "" ? meta2.model : void 0) ?? (typeof meta2?.modelId === "string" && meta2.modelId.trim() !== "" ? meta2.modelId : void 0);
|
|
18954
|
+
if (requestModel !== void 0) {
|
|
18955
|
+
attrs.push(stringAttr2("gen_ai.request.model", requestModel.slice(0, maxLen)));
|
|
18956
|
+
}
|
|
18957
|
+
const responseModel = typeof meta2?.responseModelId === "string" && meta2.responseModelId.trim() !== "" ? meta2.responseModelId : typeof meta2?.responseModel === "string" && meta2.responseModel.trim() !== "" ? meta2.responseModel : void 0;
|
|
18958
|
+
if (responseModel !== void 0) {
|
|
18959
|
+
attrs.push(stringAttr2("gen_ai.response.model", responseModel.slice(0, maxLen)));
|
|
18960
|
+
}
|
|
18961
|
+
if (typeof meta2?.provider === "string" && meta2.provider.trim() !== "") {
|
|
18962
|
+
attrs.push(stringAttr2("gen_ai.provider.name", meta2.provider.slice(0, maxLen)));
|
|
18827
18963
|
}
|
|
18828
18964
|
const tokens = meta2?.tokens;
|
|
18829
18965
|
if (tokens && typeof tokens === "object" && tokens !== null) {
|
|
@@ -18833,31 +18969,39 @@ function exportOtlpJson(tree, options) {
|
|
|
18833
18969
|
if (typeof outp === "number") attrs.push(intAttr("gen_ai.usage.output_tokens", outp));
|
|
18834
18970
|
}
|
|
18835
18971
|
if (includeAttributes && meta2 && typeof meta2 === "object") {
|
|
18972
|
+
const skipKeys = /* @__PURE__ */ new Set([
|
|
18973
|
+
"tokens",
|
|
18974
|
+
"model",
|
|
18975
|
+
"modelId",
|
|
18976
|
+
"responseModel",
|
|
18977
|
+
"responseModelId",
|
|
18978
|
+
"provider",
|
|
18979
|
+
"originalSourceType"
|
|
18980
|
+
]);
|
|
18836
18981
|
for (const [k, v] of Object.entries(meta2)) {
|
|
18837
|
-
if (k
|
|
18838
|
-
if (typeof v === "string"
|
|
18839
|
-
attrs.push(
|
|
18840
|
-
|
|
18841
|
-
|
|
18842
|
-
|
|
18843
|
-
|
|
18844
|
-
);
|
|
18982
|
+
if (skipKeys.has(k)) continue;
|
|
18983
|
+
if (typeof v === "string") {
|
|
18984
|
+
attrs.push(stringAttr2(`agent_inspect.preview.${k}`, v.slice(0, maxLen)));
|
|
18985
|
+
} else if (typeof v === "number" && Number.isFinite(v)) {
|
|
18986
|
+
attrs.push(numberAttr(`agent_inspect.preview.${k}`, v));
|
|
18987
|
+
} else if (typeof v === "boolean") {
|
|
18988
|
+
attrs.push(boolAttr(`agent_inspect.preview.${k}`, v));
|
|
18845
18989
|
}
|
|
18846
18990
|
}
|
|
18847
18991
|
}
|
|
18848
|
-
let statusCode =
|
|
18992
|
+
let statusCode = OTLP_STATUS_CODE_UNSET;
|
|
18849
18993
|
let statusMessage;
|
|
18850
18994
|
if (ev.status === "error") {
|
|
18851
|
-
statusCode =
|
|
18995
|
+
statusCode = OTLP_STATUS_CODE_ERROR;
|
|
18852
18996
|
statusMessage = meta2 && typeof meta2.error === "object" && meta2.error !== null ? String(meta2.error.message ?? "error").slice(0, maxLen) : "error";
|
|
18853
18997
|
} else if (ev.status === "ok") {
|
|
18854
|
-
statusCode =
|
|
18998
|
+
statusCode = OTLP_STATUS_CODE_OK;
|
|
18855
18999
|
}
|
|
18856
19000
|
const spanJson = {
|
|
18857
19001
|
traceId,
|
|
18858
19002
|
spanId,
|
|
18859
19003
|
name: ev.name,
|
|
18860
|
-
kind:
|
|
19004
|
+
kind: OTLP_SPAN_KIND_INTERNAL,
|
|
18861
19005
|
startTimeUnixNano: startNs,
|
|
18862
19006
|
attributes: attrs,
|
|
18863
19007
|
status: {
|
|
@@ -18899,6 +19043,207 @@ function exportOtlpJson(tree, options) {
|
|
|
18899
19043
|
|
|
18900
19044
|
// packages/core/src/exporters/validation.ts
|
|
18901
19045
|
var EXPERIMENTAL = "Experimental compatibility export \u2014 verify against your target tooling before relying on it.";
|
|
19046
|
+
function pushPath(errors, path44, message) {
|
|
19047
|
+
errors.push(`${path44}: ${message}`);
|
|
19048
|
+
}
|
|
19049
|
+
function isRecord16(value) {
|
|
19050
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
19051
|
+
}
|
|
19052
|
+
function isHexId(value, byteLen) {
|
|
19053
|
+
return typeof value === "string" && new RegExp(`^[0-9a-fA-F]{${byteLen * 2}}$`).test(value);
|
|
19054
|
+
}
|
|
19055
|
+
function validateAnyValue(errors, path44, value) {
|
|
19056
|
+
if (!isRecord16(value)) {
|
|
19057
|
+
pushPath(errors, path44, "must be an AnyValue object");
|
|
19058
|
+
return;
|
|
19059
|
+
}
|
|
19060
|
+
const variants = [
|
|
19061
|
+
"stringValue",
|
|
19062
|
+
"boolValue",
|
|
19063
|
+
"intValue",
|
|
19064
|
+
"doubleValue",
|
|
19065
|
+
"bytesValue",
|
|
19066
|
+
"arrayValue",
|
|
19067
|
+
"kvlistValue"
|
|
19068
|
+
].filter((key) => value[key] !== void 0);
|
|
19069
|
+
if (variants.length !== 1) {
|
|
19070
|
+
pushPath(
|
|
19071
|
+
errors,
|
|
19072
|
+
path44,
|
|
19073
|
+
`AnyValue must set exactly one variant (found ${variants.length}: ${variants.join(",")})`
|
|
19074
|
+
);
|
|
19075
|
+
}
|
|
19076
|
+
if (value.intValue !== void 0) {
|
|
19077
|
+
if (typeof value.intValue !== "string" || !/^-?\d+$/.test(value.intValue)) {
|
|
19078
|
+
pushPath(errors, `${path44}.intValue`, "must be a decimal integer string");
|
|
19079
|
+
}
|
|
19080
|
+
}
|
|
19081
|
+
}
|
|
19082
|
+
function validateOtlpJson(content) {
|
|
19083
|
+
const errors = [];
|
|
19084
|
+
const warnings = [
|
|
19085
|
+
EXPERIMENTAL,
|
|
19086
|
+
"OTLP JSON mapping uses OTel GenAI-aligned attributes where applicable; collectors may require transformation.",
|
|
19087
|
+
"producer-profile checks IDs, timing, and AnyValue shape; historical string enums are reader-compat warnings only."
|
|
19088
|
+
];
|
|
19089
|
+
let parsed;
|
|
19090
|
+
try {
|
|
19091
|
+
parsed = JSON.parse(content);
|
|
19092
|
+
} catch {
|
|
19093
|
+
pushPath(errors, "$", "OTLP JSON export is not valid JSON");
|
|
19094
|
+
return { ok: false, format: "otlp-json", errors, warnings };
|
|
19095
|
+
}
|
|
19096
|
+
if (!isRecord16(parsed)) {
|
|
19097
|
+
pushPath(errors, "$", "OTLP JSON export must be an object");
|
|
19098
|
+
return { ok: false, format: "otlp-json", errors, warnings };
|
|
19099
|
+
}
|
|
19100
|
+
if (!Array.isArray(parsed.resourceSpans)) {
|
|
19101
|
+
pushPath(errors, "$.resourceSpans", "must be an array");
|
|
19102
|
+
return { ok: false, format: "otlp-json", errors, warnings };
|
|
19103
|
+
}
|
|
19104
|
+
parsed.resourceSpans.forEach((resourceSpan, rsi) => {
|
|
19105
|
+
const rsPath = `$.resourceSpans[${rsi}]`;
|
|
19106
|
+
if (!isRecord16(resourceSpan)) {
|
|
19107
|
+
pushPath(errors, rsPath, "must be an object");
|
|
19108
|
+
return;
|
|
19109
|
+
}
|
|
19110
|
+
if (!Array.isArray(resourceSpan.scopeSpans)) {
|
|
19111
|
+
pushPath(errors, `${rsPath}.scopeSpans`, "must be an array");
|
|
19112
|
+
return;
|
|
19113
|
+
}
|
|
19114
|
+
resourceSpan.scopeSpans.forEach((scopeSpan, ssi) => {
|
|
19115
|
+
const ssPath = `${rsPath}.scopeSpans[${ssi}]`;
|
|
19116
|
+
if (!isRecord16(scopeSpan)) {
|
|
19117
|
+
pushPath(errors, ssPath, "must be an object");
|
|
19118
|
+
return;
|
|
19119
|
+
}
|
|
19120
|
+
if (!Array.isArray(scopeSpan.spans)) {
|
|
19121
|
+
pushPath(errors, `${ssPath}.spans`, "must be an array");
|
|
19122
|
+
return;
|
|
19123
|
+
}
|
|
19124
|
+
scopeSpan.spans.forEach((span, spi) => {
|
|
19125
|
+
const spanPath = `${ssPath}.spans[${spi}]`;
|
|
19126
|
+
if (!isRecord16(span)) {
|
|
19127
|
+
pushPath(errors, spanPath, "must be an object");
|
|
19128
|
+
return;
|
|
19129
|
+
}
|
|
19130
|
+
if (!isHexId(span.traceId, 16)) {
|
|
19131
|
+
pushPath(
|
|
19132
|
+
errors,
|
|
19133
|
+
`${spanPath}.traceId`,
|
|
19134
|
+
"must be a 32-char hex trace id (16 bytes)"
|
|
19135
|
+
);
|
|
19136
|
+
}
|
|
19137
|
+
if (!isHexId(span.spanId, 8)) {
|
|
19138
|
+
pushPath(
|
|
19139
|
+
errors,
|
|
19140
|
+
`${spanPath}.spanId`,
|
|
19141
|
+
"must be a 16-char hex span id (8 bytes)"
|
|
19142
|
+
);
|
|
19143
|
+
}
|
|
19144
|
+
if (span.parentSpanId !== void 0 && !isHexId(span.parentSpanId, 8)) {
|
|
19145
|
+
pushPath(
|
|
19146
|
+
errors,
|
|
19147
|
+
`${spanPath}.parentSpanId`,
|
|
19148
|
+
"must be a 16-char hex span id when present"
|
|
19149
|
+
);
|
|
19150
|
+
}
|
|
19151
|
+
if (typeof span.name !== "string") {
|
|
19152
|
+
pushPath(errors, `${spanPath}.name`, "must be a string");
|
|
19153
|
+
}
|
|
19154
|
+
if (typeof span.startTimeUnixNano !== "string" || !/^\d+$/.test(span.startTimeUnixNano)) {
|
|
19155
|
+
pushPath(
|
|
19156
|
+
errors,
|
|
19157
|
+
`${spanPath}.startTimeUnixNano`,
|
|
19158
|
+
"must be a decimal-string 64-bit integer"
|
|
19159
|
+
);
|
|
19160
|
+
}
|
|
19161
|
+
if (span.endTimeUnixNano !== void 0 && (typeof span.endTimeUnixNano !== "string" || !/^\d+$/.test(span.endTimeUnixNano))) {
|
|
19162
|
+
pushPath(
|
|
19163
|
+
errors,
|
|
19164
|
+
`${spanPath}.endTimeUnixNano`,
|
|
19165
|
+
"must be a decimal-string 64-bit integer when present"
|
|
19166
|
+
);
|
|
19167
|
+
}
|
|
19168
|
+
if (typeof span.startTimeUnixNano === "string" && /^\d+$/.test(span.startTimeUnixNano) && typeof span.endTimeUnixNano === "string" && /^\d+$/.test(span.endTimeUnixNano)) {
|
|
19169
|
+
try {
|
|
19170
|
+
if (BigInt(span.endTimeUnixNano) < BigInt(span.startTimeUnixNano)) {
|
|
19171
|
+
pushPath(
|
|
19172
|
+
errors,
|
|
19173
|
+
`${spanPath}.endTimeUnixNano`,
|
|
19174
|
+
"must be >= startTimeUnixNano"
|
|
19175
|
+
);
|
|
19176
|
+
}
|
|
19177
|
+
} catch {
|
|
19178
|
+
pushPath(errors, `${spanPath}.endTimeUnixNano`, "out of integer range");
|
|
19179
|
+
}
|
|
19180
|
+
}
|
|
19181
|
+
if (Array.isArray(span.attributes)) {
|
|
19182
|
+
span.attributes.forEach((attr, ai) => {
|
|
19183
|
+
const attrPath = `${spanPath}.attributes[${ai}]`;
|
|
19184
|
+
if (!isRecord16(attr)) {
|
|
19185
|
+
pushPath(errors, attrPath, "must be an object");
|
|
19186
|
+
return;
|
|
19187
|
+
}
|
|
19188
|
+
if (typeof attr.key !== "string") {
|
|
19189
|
+
pushPath(errors, `${attrPath}.key`, "must be a string");
|
|
19190
|
+
}
|
|
19191
|
+
validateAnyValue(errors, `${attrPath}.value`, attr.value);
|
|
19192
|
+
});
|
|
19193
|
+
}
|
|
19194
|
+
if (typeof span.kind === "number") {
|
|
19195
|
+
if (!Number.isInteger(span.kind)) {
|
|
19196
|
+
pushPath(errors, `${spanPath}.kind`, "must be an integer SpanKind enum");
|
|
19197
|
+
}
|
|
19198
|
+
} else if (typeof span.kind === "string") {
|
|
19199
|
+
warnings.push(
|
|
19200
|
+
`${spanPath}.kind: string SpanKind is historical reader-compat only; producer wire format uses numeric enums`
|
|
19201
|
+
);
|
|
19202
|
+
} else if (span.kind !== void 0) {
|
|
19203
|
+
pushPath(
|
|
19204
|
+
errors,
|
|
19205
|
+
`${spanPath}.kind`,
|
|
19206
|
+
"must be numeric SpanKind or historical string enum"
|
|
19207
|
+
);
|
|
19208
|
+
}
|
|
19209
|
+
if (!isRecord16(span.status)) {
|
|
19210
|
+
pushPath(errors, `${spanPath}.status`, "must be an object");
|
|
19211
|
+
} else {
|
|
19212
|
+
const code = span.status.code;
|
|
19213
|
+
if (typeof code === "number") {
|
|
19214
|
+
if (![0, 1, 2].includes(code)) {
|
|
19215
|
+
pushPath(
|
|
19216
|
+
errors,
|
|
19217
|
+
`${spanPath}.status.code`,
|
|
19218
|
+
"must be numeric StatusCode 0 (UNSET), 1 (OK), or 2 (ERROR)"
|
|
19219
|
+
);
|
|
19220
|
+
}
|
|
19221
|
+
} else if (typeof code === "string") {
|
|
19222
|
+
const upper = code.toUpperCase();
|
|
19223
|
+
if (upper !== "STATUS_CODE_UNSET" && upper !== "STATUS_CODE_OK" && upper !== "STATUS_CODE_ERROR" && upper !== "UNSET" && upper !== "OK" && upper !== "ERROR" && !/^[012]$/.test(code.trim())) {
|
|
19224
|
+
pushPath(
|
|
19225
|
+
errors,
|
|
19226
|
+
`${spanPath}.status.code`,
|
|
19227
|
+
"unrecognized StatusCode string"
|
|
19228
|
+
);
|
|
19229
|
+
} else {
|
|
19230
|
+
warnings.push(
|
|
19231
|
+
`${spanPath}.status.code: string StatusCode is historical reader-compat only; producer wire format uses numeric 0/1/2`
|
|
19232
|
+
);
|
|
19233
|
+
}
|
|
19234
|
+
} else {
|
|
19235
|
+
pushPath(
|
|
19236
|
+
errors,
|
|
19237
|
+
`${spanPath}.status.code`,
|
|
19238
|
+
"must be numeric StatusCode 0/1/2 or historical string enum"
|
|
19239
|
+
);
|
|
19240
|
+
}
|
|
19241
|
+
}
|
|
19242
|
+
});
|
|
19243
|
+
});
|
|
19244
|
+
});
|
|
19245
|
+
return { ok: errors.length === 0, format: "otlp-json", errors, warnings };
|
|
19246
|
+
}
|
|
18902
19247
|
function validateExportContent(format, content) {
|
|
18903
19248
|
const errors = [];
|
|
18904
19249
|
const warnings = [EXPERIMENTAL];
|
|
@@ -18944,25 +19289,7 @@ function validateExportContent(format, content) {
|
|
|
18944
19289
|
return { ok: errors.length === 0, format, errors, warnings };
|
|
18945
19290
|
}
|
|
18946
19291
|
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 };
|
|
19292
|
+
return validateOtlpJson(content);
|
|
18966
19293
|
}
|
|
18967
19294
|
errors.push(`Unsupported export format`);
|
|
18968
19295
|
return { ok: false, format, errors, warnings };
|
|
@@ -19366,7 +19693,7 @@ async function exportCommand(runId, options = {}) {
|
|
|
19366
19693
|
const traceDir = resolveTraceDir({ dir: options.dir });
|
|
19367
19694
|
let events;
|
|
19368
19695
|
try {
|
|
19369
|
-
const result2 = await
|
|
19696
|
+
const result2 = await readRunPersistedEvents(id, traceDir);
|
|
19370
19697
|
events = result2?.events ?? [];
|
|
19371
19698
|
} catch (e) {
|
|
19372
19699
|
const msg = e instanceof Error ? e.message : String(e);
|
|
@@ -19382,7 +19709,13 @@ Trace directory: ${traceDir}`);
|
|
|
19382
19709
|
}
|
|
19383
19710
|
let tree;
|
|
19384
19711
|
try {
|
|
19385
|
-
|
|
19712
|
+
const trees = persistedInspectEventsToRunTrees(events, {
|
|
19713
|
+
coalesceLifecycle: true
|
|
19714
|
+
});
|
|
19715
|
+
tree = trees.find((candidate) => candidate.runId === id) ?? trees[0];
|
|
19716
|
+
if (tree === void 0) {
|
|
19717
|
+
throw new Error("No run tree could be built from persisted events");
|
|
19718
|
+
}
|
|
19386
19719
|
} catch (e) {
|
|
19387
19720
|
const msg = e instanceof Error ? e.message : String(e);
|
|
19388
19721
|
console.error(`[AgentInspect] export failed: ${msg}`);
|
|
@@ -19410,7 +19743,9 @@ Trace directory: ${traceDir}`);
|
|
|
19410
19743
|
await promises.mkdir(path33__default.default.dirname(outPath), { recursive: true });
|
|
19411
19744
|
await promises.writeFile(outPath, result.content, "utf-8");
|
|
19412
19745
|
const vlabel = validation !== void 0 ? validation.ok ? "ok" : "failed" : "skipped";
|
|
19413
|
-
console.
|
|
19746
|
+
console.error(
|
|
19747
|
+
`Wrote ${result.fileExtension} export to ${outPath} (validation: ${vlabel})`
|
|
19748
|
+
);
|
|
19414
19749
|
if (validation !== void 0 && !validation.ok) {
|
|
19415
19750
|
console.error("Validation errors:", validation.errors.join("; "));
|
|
19416
19751
|
}
|
|
@@ -19423,7 +19758,9 @@ Trace directory: ${traceDir}`);
|
|
|
19423
19758
|
warnings: [...result.warnings, ...validation?.warnings ?? []],
|
|
19424
19759
|
validation
|
|
19425
19760
|
};
|
|
19426
|
-
if (outPath
|
|
19761
|
+
if (outPath !== void 0) {
|
|
19762
|
+
payload.out = outPath;
|
|
19763
|
+
} else {
|
|
19427
19764
|
payload.content = result.content;
|
|
19428
19765
|
}
|
|
19429
19766
|
console.log(JSON.stringify(payload, null, 2));
|
|
@@ -20535,7 +20872,7 @@ var STRICT_PROFILE_EXTRA_KEYS2 = [
|
|
|
20535
20872
|
"retrieval",
|
|
20536
20873
|
"query"
|
|
20537
20874
|
];
|
|
20538
|
-
function
|
|
20875
|
+
function isRecord17(value) {
|
|
20539
20876
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20540
20877
|
}
|
|
20541
20878
|
function toKey2(key) {
|
|
@@ -20964,7 +21301,7 @@ var Redactor2 = class {
|
|
|
20964
21301
|
});
|
|
20965
21302
|
return out;
|
|
20966
21303
|
}
|
|
20967
|
-
if (
|
|
21304
|
+
if (isRecord17(value)) {
|
|
20968
21305
|
if (state.seen.has(value)) return state.seen.get(value);
|
|
20969
21306
|
const out = {};
|
|
20970
21307
|
state.seen.set(value, out);
|
|
@@ -20999,7 +21336,7 @@ var REDACTION_POLICY_LIMITS = {
|
|
|
20999
21336
|
};
|
|
21000
21337
|
var ALLOWED_TOP_LEVEL = /* @__PURE__ */ new Set(["version", "extraKeys", "patterns"]);
|
|
21001
21338
|
var ALLOWED_PATTERN_FIELDS = /* @__PURE__ */ new Set(["id", "type", "value", "severity"]);
|
|
21002
|
-
function
|
|
21339
|
+
function isRecord18(value) {
|
|
21003
21340
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
21004
21341
|
}
|
|
21005
21342
|
function rejectRemotePolicyPath(policyPath) {
|
|
@@ -21039,7 +21376,7 @@ function rejectUnknownFields(record, allowed, label) {
|
|
|
21039
21376
|
}
|
|
21040
21377
|
function compilePatternDetector(input3, index) {
|
|
21041
21378
|
const label = `patterns[${index}]`;
|
|
21042
|
-
if (!
|
|
21379
|
+
if (!isRecord18(input3)) throw new Error(`${label} must be an object.`);
|
|
21043
21380
|
const typeEarly = input3.type;
|
|
21044
21381
|
if (typeEarly === "typed") {
|
|
21045
21382
|
throw new Error(
|
|
@@ -21094,7 +21431,7 @@ function compilePatternDetector(input3, index) {
|
|
|
21094
21431
|
};
|
|
21095
21432
|
}
|
|
21096
21433
|
function compileRedactionPolicy(raw, policyPath) {
|
|
21097
|
-
if (!
|
|
21434
|
+
if (!isRecord18(raw)) {
|
|
21098
21435
|
throw new Error(`Redaction policy must be a JSON object (${policyPath}).`);
|
|
21099
21436
|
}
|
|
21100
21437
|
rejectUnknownFields(raw, ALLOWED_TOP_LEVEL, "Redaction policy");
|
|
@@ -22130,7 +22467,7 @@ async function openCommand(input3, options = {}, stdin = process.stdin) {
|
|
|
22130
22467
|
|
|
22131
22468
|
// packages/cli/src/migrate.ts
|
|
22132
22469
|
init_advanced();
|
|
22133
|
-
function
|
|
22470
|
+
function isRecord19(value) {
|
|
22134
22471
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
22135
22472
|
}
|
|
22136
22473
|
function parseTarget(value) {
|
|
@@ -22139,7 +22476,7 @@ function parseTarget(value) {
|
|
|
22139
22476
|
throw new Error('Unsupported migration target. Use "--to 1.0".');
|
|
22140
22477
|
}
|
|
22141
22478
|
function formatOf(value) {
|
|
22142
|
-
if (!
|
|
22479
|
+
if (!isRecord19(value)) return "unknown";
|
|
22143
22480
|
if (value.schemaVersion === "0.1") return "0.1";
|
|
22144
22481
|
if (value.schemaVersion === "0.2") return "0.2";
|
|
22145
22482
|
if (value.schemaVersion === "1.0") return "1.0";
|
|
@@ -28663,16 +29000,146 @@ function demoTemplate(framework) {
|
|
|
28663
29000
|
switch (framework) {
|
|
28664
29001
|
case "ai-sdk":
|
|
28665
29002
|
return `/**
|
|
28666
|
-
* AI SDK starter \u2014
|
|
28667
|
-
* Install: npm install agent-inspect @agent-inspect/ai-sdk ai
|
|
29003
|
+
* AI SDK starter \u2014 keyless MockLanguageModelV3 + @agent-inspect/ai-sdk telemetry.
|
|
29004
|
+
* Install: npm install agent-inspect @agent-inspect/ai-sdk ai@6.0.210 zod
|
|
28668
29005
|
*/
|
|
28669
|
-
import {
|
|
29006
|
+
import { generateText, stepCountIs, tool } from "ai";
|
|
29007
|
+
import { MockLanguageModelV3 } from "ai/test";
|
|
29008
|
+
import { agentInspect } from "@agent-inspect/ai-sdk";
|
|
29009
|
+
import { z } from "zod";
|
|
29010
|
+
import { mkdirSync, readdirSync, readFileSync, rmSync } from "node:fs";
|
|
29011
|
+
import path from "node:path";
|
|
29012
|
+
import { randomUUID } from "node:crypto";
|
|
29013
|
+
|
|
29014
|
+
const SESSION = randomUUID().slice(0, 8);
|
|
29015
|
+
const TRACE_DIR = path.join(".agent-inspect", \`demo-\${SESSION}\`);
|
|
29016
|
+
const ANSWER = "You have 2 orders";
|
|
29017
|
+
const CORRECT_RUN = \`ai-sdk-demo-correct-\${SESSION}\`;
|
|
29018
|
+
const WRONG_RUN = \`ai-sdk-demo-wrong-\${SESSION}\`;
|
|
29019
|
+
|
|
29020
|
+
const usage = {
|
|
29021
|
+
inputTokens: { total: 4, noCache: 4, cacheRead: 0, cacheWrite: 0 },
|
|
29022
|
+
outputTokens: { total: 3, text: 3, reasoning: 0 },
|
|
29023
|
+
};
|
|
29024
|
+
|
|
29025
|
+
const lookupOrders = tool({
|
|
29026
|
+
description: "Look up orders for a user",
|
|
29027
|
+
inputSchema: z.object({ userId: z.string() }),
|
|
29028
|
+
execute: async () => ({ orders: 2 }),
|
|
29029
|
+
});
|
|
29030
|
+
|
|
29031
|
+
const deleteOrders = tool({
|
|
29032
|
+
description: "Delete orders for a user (wrong path)",
|
|
29033
|
+
inputSchema: z.object({ userId: z.string() }),
|
|
29034
|
+
execute: async () => ({ orders: 2 }),
|
|
29035
|
+
});
|
|
29036
|
+
|
|
29037
|
+
async function runPath(runName, toolName) {
|
|
29038
|
+
const integration = agentInspect({
|
|
29039
|
+
traceDir: TRACE_DIR,
|
|
29040
|
+
runName,
|
|
29041
|
+
capture: "metadata-only",
|
|
29042
|
+
});
|
|
29043
|
+
let step = 0;
|
|
29044
|
+
try {
|
|
29045
|
+
const result = await generateText({
|
|
29046
|
+
model: new MockLanguageModelV3({
|
|
29047
|
+
provider: "fixture-provider",
|
|
29048
|
+
modelId: "fixture-tools",
|
|
29049
|
+
doGenerate: async () => {
|
|
29050
|
+
step += 1;
|
|
29051
|
+
if (step === 1) {
|
|
29052
|
+
return {
|
|
29053
|
+
content: [
|
|
29054
|
+
{
|
|
29055
|
+
type: "tool-call",
|
|
29056
|
+
toolCallId: \`call-\${toolName}\`,
|
|
29057
|
+
toolName,
|
|
29058
|
+
input: JSON.stringify({ userId: "u1" }),
|
|
29059
|
+
},
|
|
29060
|
+
],
|
|
29061
|
+
finishReason: { unified: "tool-calls", raw: "tool-calls" },
|
|
29062
|
+
usage,
|
|
29063
|
+
warnings: [],
|
|
29064
|
+
};
|
|
29065
|
+
}
|
|
29066
|
+
return {
|
|
29067
|
+
content: [{ type: "text", text: ANSWER }],
|
|
29068
|
+
finishReason: { unified: "stop", raw: "stop" },
|
|
29069
|
+
usage,
|
|
29070
|
+
warnings: [],
|
|
29071
|
+
};
|
|
29072
|
+
},
|
|
29073
|
+
}),
|
|
29074
|
+
tools: { lookup_orders: lookupOrders, delete_orders: deleteOrders },
|
|
29075
|
+
prompt: "How many orders do I have?",
|
|
29076
|
+
stopWhen: stepCountIs(5),
|
|
29077
|
+
experimental_telemetry: {
|
|
29078
|
+
isEnabled: true,
|
|
29079
|
+
recordInputs: false,
|
|
29080
|
+
recordOutputs: false,
|
|
29081
|
+
integrations: [integration],
|
|
29082
|
+
},
|
|
29083
|
+
});
|
|
29084
|
+
if (result.text !== ANSWER) {
|
|
29085
|
+
throw new Error(\`unexpected answer for \${runName}: \${result.text}\`);
|
|
29086
|
+
}
|
|
29087
|
+
} finally {
|
|
29088
|
+
await integration.flush();
|
|
29089
|
+
await integration.close();
|
|
29090
|
+
}
|
|
29091
|
+
}
|
|
29092
|
+
|
|
29093
|
+
function selectRunIdByName(runName) {
|
|
29094
|
+
const files = readdirSync(TRACE_DIR).filter((f) => f.endsWith(".jsonl"));
|
|
29095
|
+
const matches = [];
|
|
29096
|
+
for (const file of files) {
|
|
29097
|
+
const text = readFileSync(path.join(TRACE_DIR, file), "utf8");
|
|
29098
|
+
if (text.includes(\`"name":"\${runName}"\`) || text.includes(\`"name": "\${runName}"\`)) {
|
|
29099
|
+
matches.push(file.replace(/\\.jsonl$/, ""));
|
|
29100
|
+
}
|
|
29101
|
+
}
|
|
29102
|
+
if (matches.length !== 1) {
|
|
29103
|
+
throw new Error(
|
|
29104
|
+
\`expected exactly one run named \${runName}, found \${matches.length}\`,
|
|
29105
|
+
);
|
|
29106
|
+
}
|
|
29107
|
+
return matches[0];
|
|
29108
|
+
}
|
|
29109
|
+
|
|
29110
|
+
function assertToolExecuted(runId, requiredTool) {
|
|
29111
|
+
const text = readFileSync(path.join(TRACE_DIR, \`\${runId}.jsonl\`), "utf8");
|
|
29112
|
+
const toolHits = text
|
|
29113
|
+
.split("\\n")
|
|
29114
|
+
.filter(Boolean)
|
|
29115
|
+
.map((line) => JSON.parse(line))
|
|
29116
|
+
.filter(
|
|
29117
|
+
(ev) =>
|
|
29118
|
+
(ev.kind === "TOOL" || ev.attributes?.stepType === "tool") &&
|
|
29119
|
+
(ev.name === requiredTool || ev.attributes?.toolName === requiredTool),
|
|
29120
|
+
);
|
|
29121
|
+
if (toolHits.length === 0) {
|
|
29122
|
+
throw new Error(\`expected TOOL events for \${requiredTool} in \${runId}\`);
|
|
29123
|
+
}
|
|
29124
|
+
}
|
|
28670
29125
|
|
|
28671
29126
|
async function main() {
|
|
28672
|
-
|
|
28673
|
-
|
|
28674
|
-
|
|
28675
|
-
|
|
29127
|
+
mkdirSync(TRACE_DIR, { recursive: true });
|
|
29128
|
+
try {
|
|
29129
|
+
await runPath(CORRECT_RUN, "lookup_orders");
|
|
29130
|
+
await runPath(WRONG_RUN, "delete_orders");
|
|
29131
|
+
const correctId = selectRunIdByName(CORRECT_RUN);
|
|
29132
|
+
const wrongId = selectRunIdByName(WRONG_RUN);
|
|
29133
|
+
assertToolExecuted(correctId, "lookup_orders");
|
|
29134
|
+
assertToolExecuted(wrongId, "delete_orders");
|
|
29135
|
+
console.log(\`Trace written to \${TRACE_DIR}/\`);
|
|
29136
|
+
console.log(\`Correct path runId: \${correctId}\`);
|
|
29137
|
+
console.log(\`Wrong path runId: \${wrongId}\`);
|
|
29138
|
+
console.log(\`Next: npx agent-inspect check \${correctId} --dir \${TRACE_DIR} --required-tool lookup_orders\`);
|
|
29139
|
+
} catch (error) {
|
|
29140
|
+
rmSync(TRACE_DIR, { recursive: true, force: true });
|
|
29141
|
+
throw error;
|
|
29142
|
+
}
|
|
28676
29143
|
}
|
|
28677
29144
|
|
|
28678
29145
|
main().catch((error) => {
|