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
|
@@ -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-6FE47XSF.mjs';
|
|
3
3
|
import { realpathSync, constants as constants$1, existsSync, readFileSync } from 'fs';
|
|
4
4
|
import path19 from 'path';
|
|
5
5
|
import { fileURLToPath, pathToFileURL } from 'url';
|
|
@@ -14,7 +14,7 @@ import { createServer } from 'http';
|
|
|
14
14
|
import { createRequire } from 'module';
|
|
15
15
|
|
|
16
16
|
// package.json
|
|
17
|
-
var version = "6.31.
|
|
17
|
+
var version = "6.31.8";
|
|
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) {
|
|
@@ -2488,11 +2496,13 @@ function exportOpenInference(tree, options) {
|
|
|
2488
2496
|
endNs = startNs + unixNano(ev.durationMs);
|
|
2489
2497
|
}
|
|
2490
2498
|
const { openInferenceKind } = mapInspectKindToOI(ev.kind, warnings);
|
|
2499
|
+
const meta = ev.attributes;
|
|
2500
|
+
const originalSource = typeof meta?.originalSourceType === "string" && meta.originalSourceType.trim() !== "" ? meta.originalSourceType.trim() : ev.source.type;
|
|
2491
2501
|
const attrs = {
|
|
2492
2502
|
"openinference.span.kind": openInferenceKind,
|
|
2493
2503
|
"agent_inspect.kind": ev.kind,
|
|
2494
2504
|
"agent_inspect.confidence": ev.confidence,
|
|
2495
|
-
"agent_inspect.source.type":
|
|
2505
|
+
"agent_inspect.source.type": originalSource,
|
|
2496
2506
|
"agent_inspect.run_id": tree.runId,
|
|
2497
2507
|
"agent_inspect.event_id": ev.eventId,
|
|
2498
2508
|
"agent_inspect.status": ev.status ?? "unset"
|
|
@@ -2500,9 +2510,9 @@ function exportOpenInference(tree, options) {
|
|
|
2500
2510
|
if (ev.durationMs !== void 0) {
|
|
2501
2511
|
attrs["agent_inspect.duration_ms"] = ev.durationMs;
|
|
2502
2512
|
}
|
|
2503
|
-
const
|
|
2504
|
-
if (
|
|
2505
|
-
attrs["llm.model_name"] =
|
|
2513
|
+
const requestModel = (typeof meta?.model === "string" && meta.model.trim() !== "" ? meta.model : void 0) ?? (typeof meta?.modelId === "string" && meta.modelId.trim() !== "" ? meta.modelId : void 0);
|
|
2514
|
+
if (requestModel !== void 0) {
|
|
2515
|
+
attrs["llm.model_name"] = requestModel;
|
|
2506
2516
|
}
|
|
2507
2517
|
const tokens = meta?.tokens;
|
|
2508
2518
|
if (tokens && typeof tokens === "object" && tokens !== null) {
|
|
@@ -2512,8 +2522,9 @@ function exportOpenInference(tree, options) {
|
|
|
2512
2522
|
if (typeof outp === "number") attrs["llm.token_count.completion"] = outp;
|
|
2513
2523
|
}
|
|
2514
2524
|
if (includeAttributes && meta && typeof meta === "object") {
|
|
2525
|
+
const skipKeys = /* @__PURE__ */ new Set(["tokens", "model", "modelId", "originalSourceType"]);
|
|
2515
2526
|
for (const [k, v] of Object.entries(meta)) {
|
|
2516
|
-
if (k
|
|
2527
|
+
if (skipKeys.has(k)) continue;
|
|
2517
2528
|
if (v !== void 0 && v !== null && typeof v !== "object") {
|
|
2518
2529
|
attrs[`agent_inspect.preview.${k}`] = typeof v === "string" ? v.slice(0, maxLen) : v;
|
|
2519
2530
|
}
|
|
@@ -2556,6 +2567,10 @@ function exportOpenInference(tree, options) {
|
|
|
2556
2567
|
warnings
|
|
2557
2568
|
};
|
|
2558
2569
|
}
|
|
2570
|
+
var OTLP_STATUS_CODE_UNSET = 0;
|
|
2571
|
+
var OTLP_STATUS_CODE_OK = 1;
|
|
2572
|
+
var OTLP_STATUS_CODE_ERROR = 2;
|
|
2573
|
+
var OTLP_SPAN_KIND_INTERNAL = 1;
|
|
2559
2574
|
function hexFrom2(seed, byteLen) {
|
|
2560
2575
|
return crypto.createHash("sha256").update(seed, "utf8").digest("hex").slice(0, byteLen * 2);
|
|
2561
2576
|
}
|
|
@@ -2568,7 +2583,19 @@ function stringAttr(key, value) {
|
|
|
2568
2583
|
return { key, value: { stringValue: value } };
|
|
2569
2584
|
}
|
|
2570
2585
|
function intAttr(key, value) {
|
|
2571
|
-
return { key, value: { intValue: String(value) } };
|
|
2586
|
+
return { key, value: { intValue: String(Math.trunc(value)) } };
|
|
2587
|
+
}
|
|
2588
|
+
function doubleAttr(key, value) {
|
|
2589
|
+
return { key, value: { doubleValue: value } };
|
|
2590
|
+
}
|
|
2591
|
+
function boolAttr(key, value) {
|
|
2592
|
+
return { key, value: { boolValue: value } };
|
|
2593
|
+
}
|
|
2594
|
+
function numberAttr(key, value) {
|
|
2595
|
+
if (Number.isFinite(value) && !Number.isInteger(value)) {
|
|
2596
|
+
return doubleAttr(key, value);
|
|
2597
|
+
}
|
|
2598
|
+
return intAttr(key, value);
|
|
2572
2599
|
}
|
|
2573
2600
|
function genAiOperationName(kind) {
|
|
2574
2601
|
switch (kind) {
|
|
@@ -2582,10 +2609,27 @@ function genAiOperationName(kind) {
|
|
|
2582
2609
|
return void 0;
|
|
2583
2610
|
}
|
|
2584
2611
|
}
|
|
2612
|
+
function resolveSpanTimes(ev) {
|
|
2613
|
+
const startedAtMs = typeof ev.attributes?.startedAtMs === "number" && Number.isFinite(ev.attributes.startedAtMs) ? ev.attributes.startedAtMs : void 0;
|
|
2614
|
+
const endedAtMs = typeof ev.attributes?.endedAtMs === "number" && Number.isFinite(ev.attributes.endedAtMs) ? ev.attributes.endedAtMs : void 0;
|
|
2615
|
+
const startMs = startedAtMs ?? ev.timestamp;
|
|
2616
|
+
const startNs = String(unixNano2(startMs));
|
|
2617
|
+
if (endedAtMs !== void 0) {
|
|
2618
|
+
return { startNs, endNs: String(unixNano2(endedAtMs)) };
|
|
2619
|
+
}
|
|
2620
|
+
if (ev.durationMs !== void 0 && Number.isFinite(ev.durationMs)) {
|
|
2621
|
+
return {
|
|
2622
|
+
startNs,
|
|
2623
|
+
endNs: String(unixNano2(startMs) + unixNano2(ev.durationMs))
|
|
2624
|
+
};
|
|
2625
|
+
}
|
|
2626
|
+
return { startNs };
|
|
2627
|
+
}
|
|
2585
2628
|
function exportOtlpJson(tree, options) {
|
|
2586
2629
|
const warnings = [
|
|
2587
2630
|
"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."
|
|
2631
|
+
"Not OTLP gRPC/protobuf \u2014 JSON mapping only. Generated locally; no network upload.",
|
|
2632
|
+
"Status and span kind use OTLP numeric enums (StatusCode 0/1/2, SpanKind INTERNAL=1)."
|
|
2589
2633
|
];
|
|
2590
2634
|
const traceId = hexFrom2(`trace:${tree.runId}`, 16);
|
|
2591
2635
|
const includeAttributes = options?.includeAttributes ?? false;
|
|
@@ -2597,29 +2641,34 @@ function exportOtlpJson(tree, options) {
|
|
|
2597
2641
|
const ev = n.event;
|
|
2598
2642
|
const spanId = hexFrom2(`${tree.runId}:${ev.eventId}`, 8);
|
|
2599
2643
|
const parentSpanId = ev.parentId ? hexFrom2(`${tree.runId}:${ev.parentId}`, 8) : void 0;
|
|
2600
|
-
const startNs =
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
endNs = String(unixNano2(ev.timestamp) + unixNano2(ev.durationMs));
|
|
2604
|
-
}
|
|
2644
|
+
const { startNs, endNs } = resolveSpanTimes(ev);
|
|
2645
|
+
const meta = ev.attributes;
|
|
2646
|
+
const originalSource = typeof meta?.originalSourceType === "string" && meta.originalSourceType.trim() !== "" ? meta.originalSourceType.trim() : ev.source.type;
|
|
2605
2647
|
const attrs = [
|
|
2606
2648
|
stringAttr("agent_inspect.kind", ev.kind),
|
|
2607
2649
|
stringAttr("agent_inspect.confidence", ev.confidence),
|
|
2608
|
-
stringAttr("agent_inspect.source.type",
|
|
2650
|
+
stringAttr("agent_inspect.source.type", originalSource),
|
|
2609
2651
|
stringAttr("agent_inspect.run_id", tree.runId),
|
|
2610
2652
|
stringAttr("agent_inspect.event_id", ev.eventId),
|
|
2611
2653
|
stringAttr("agent_inspect.status", ev.status ?? "unset")
|
|
2612
2654
|
];
|
|
2613
2655
|
if (ev.durationMs !== void 0) {
|
|
2614
|
-
attrs.push(
|
|
2656
|
+
attrs.push(numberAttr("agent_inspect.duration_ms", ev.durationMs));
|
|
2615
2657
|
}
|
|
2616
2658
|
const op = genAiOperationName(ev.kind);
|
|
2617
2659
|
if (op !== void 0) {
|
|
2618
2660
|
attrs.push(stringAttr("gen_ai.operation.name", op));
|
|
2619
2661
|
}
|
|
2620
|
-
const
|
|
2621
|
-
if (
|
|
2622
|
-
attrs.push(stringAttr("gen_ai.request.model",
|
|
2662
|
+
const requestModel = (typeof meta?.model === "string" && meta.model.trim() !== "" ? meta.model : void 0) ?? (typeof meta?.modelId === "string" && meta.modelId.trim() !== "" ? meta.modelId : void 0);
|
|
2663
|
+
if (requestModel !== void 0) {
|
|
2664
|
+
attrs.push(stringAttr("gen_ai.request.model", requestModel.slice(0, maxLen)));
|
|
2665
|
+
}
|
|
2666
|
+
const responseModel = typeof meta?.responseModelId === "string" && meta.responseModelId.trim() !== "" ? meta.responseModelId : typeof meta?.responseModel === "string" && meta.responseModel.trim() !== "" ? meta.responseModel : void 0;
|
|
2667
|
+
if (responseModel !== void 0) {
|
|
2668
|
+
attrs.push(stringAttr("gen_ai.response.model", responseModel.slice(0, maxLen)));
|
|
2669
|
+
}
|
|
2670
|
+
if (typeof meta?.provider === "string" && meta.provider.trim() !== "") {
|
|
2671
|
+
attrs.push(stringAttr("gen_ai.provider.name", meta.provider.slice(0, maxLen)));
|
|
2623
2672
|
}
|
|
2624
2673
|
const tokens = meta?.tokens;
|
|
2625
2674
|
if (tokens && typeof tokens === "object" && tokens !== null) {
|
|
@@ -2629,31 +2678,39 @@ function exportOtlpJson(tree, options) {
|
|
|
2629
2678
|
if (typeof outp === "number") attrs.push(intAttr("gen_ai.usage.output_tokens", outp));
|
|
2630
2679
|
}
|
|
2631
2680
|
if (includeAttributes && meta && typeof meta === "object") {
|
|
2681
|
+
const skipKeys = /* @__PURE__ */ new Set([
|
|
2682
|
+
"tokens",
|
|
2683
|
+
"model",
|
|
2684
|
+
"modelId",
|
|
2685
|
+
"responseModel",
|
|
2686
|
+
"responseModelId",
|
|
2687
|
+
"provider",
|
|
2688
|
+
"originalSourceType"
|
|
2689
|
+
]);
|
|
2632
2690
|
for (const [k, v] of Object.entries(meta)) {
|
|
2633
|
-
if (k
|
|
2634
|
-
if (typeof v === "string"
|
|
2635
|
-
attrs.push(
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
);
|
|
2691
|
+
if (skipKeys.has(k)) continue;
|
|
2692
|
+
if (typeof v === "string") {
|
|
2693
|
+
attrs.push(stringAttr(`agent_inspect.preview.${k}`, v.slice(0, maxLen)));
|
|
2694
|
+
} else if (typeof v === "number" && Number.isFinite(v)) {
|
|
2695
|
+
attrs.push(numberAttr(`agent_inspect.preview.${k}`, v));
|
|
2696
|
+
} else if (typeof v === "boolean") {
|
|
2697
|
+
attrs.push(boolAttr(`agent_inspect.preview.${k}`, v));
|
|
2641
2698
|
}
|
|
2642
2699
|
}
|
|
2643
2700
|
}
|
|
2644
|
-
let statusCode =
|
|
2701
|
+
let statusCode = OTLP_STATUS_CODE_UNSET;
|
|
2645
2702
|
let statusMessage;
|
|
2646
2703
|
if (ev.status === "error") {
|
|
2647
|
-
statusCode =
|
|
2704
|
+
statusCode = OTLP_STATUS_CODE_ERROR;
|
|
2648
2705
|
statusMessage = meta && typeof meta.error === "object" && meta.error !== null ? String(meta.error.message ?? "error").slice(0, maxLen) : "error";
|
|
2649
2706
|
} else if (ev.status === "ok") {
|
|
2650
|
-
statusCode =
|
|
2707
|
+
statusCode = OTLP_STATUS_CODE_OK;
|
|
2651
2708
|
}
|
|
2652
2709
|
const spanJson = {
|
|
2653
2710
|
traceId,
|
|
2654
2711
|
spanId,
|
|
2655
2712
|
name: ev.name,
|
|
2656
|
-
kind:
|
|
2713
|
+
kind: OTLP_SPAN_KIND_INTERNAL,
|
|
2657
2714
|
startTimeUnixNano: startNs,
|
|
2658
2715
|
attributes: attrs,
|
|
2659
2716
|
status: {
|
|
@@ -2695,6 +2752,207 @@ function exportOtlpJson(tree, options) {
|
|
|
2695
2752
|
|
|
2696
2753
|
// packages/core/src/exporters/validation.ts
|
|
2697
2754
|
var EXPERIMENTAL = "Experimental compatibility export \u2014 verify against your target tooling before relying on it.";
|
|
2755
|
+
function pushPath(errors, path30, message) {
|
|
2756
|
+
errors.push(`${path30}: ${message}`);
|
|
2757
|
+
}
|
|
2758
|
+
function isRecord5(value) {
|
|
2759
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
2760
|
+
}
|
|
2761
|
+
function isHexId(value, byteLen) {
|
|
2762
|
+
return typeof value === "string" && new RegExp(`^[0-9a-fA-F]{${byteLen * 2}}$`).test(value);
|
|
2763
|
+
}
|
|
2764
|
+
function validateAnyValue(errors, path30, value) {
|
|
2765
|
+
if (!isRecord5(value)) {
|
|
2766
|
+
pushPath(errors, path30, "must be an AnyValue object");
|
|
2767
|
+
return;
|
|
2768
|
+
}
|
|
2769
|
+
const variants = [
|
|
2770
|
+
"stringValue",
|
|
2771
|
+
"boolValue",
|
|
2772
|
+
"intValue",
|
|
2773
|
+
"doubleValue",
|
|
2774
|
+
"bytesValue",
|
|
2775
|
+
"arrayValue",
|
|
2776
|
+
"kvlistValue"
|
|
2777
|
+
].filter((key) => value[key] !== void 0);
|
|
2778
|
+
if (variants.length !== 1) {
|
|
2779
|
+
pushPath(
|
|
2780
|
+
errors,
|
|
2781
|
+
path30,
|
|
2782
|
+
`AnyValue must set exactly one variant (found ${variants.length}: ${variants.join(",")})`
|
|
2783
|
+
);
|
|
2784
|
+
}
|
|
2785
|
+
if (value.intValue !== void 0) {
|
|
2786
|
+
if (typeof value.intValue !== "string" || !/^-?\d+$/.test(value.intValue)) {
|
|
2787
|
+
pushPath(errors, `${path30}.intValue`, "must be a decimal integer string");
|
|
2788
|
+
}
|
|
2789
|
+
}
|
|
2790
|
+
}
|
|
2791
|
+
function validateOtlpJson(content) {
|
|
2792
|
+
const errors = [];
|
|
2793
|
+
const warnings = [
|
|
2794
|
+
EXPERIMENTAL,
|
|
2795
|
+
"OTLP JSON mapping uses OTel GenAI-aligned attributes where applicable; collectors may require transformation.",
|
|
2796
|
+
"producer-profile checks IDs, timing, and AnyValue shape; historical string enums are reader-compat warnings only."
|
|
2797
|
+
];
|
|
2798
|
+
let parsed;
|
|
2799
|
+
try {
|
|
2800
|
+
parsed = JSON.parse(content);
|
|
2801
|
+
} catch {
|
|
2802
|
+
pushPath(errors, "$", "OTLP JSON export is not valid JSON");
|
|
2803
|
+
return { ok: false, format: "otlp-json", errors, warnings };
|
|
2804
|
+
}
|
|
2805
|
+
if (!isRecord5(parsed)) {
|
|
2806
|
+
pushPath(errors, "$", "OTLP JSON export must be an object");
|
|
2807
|
+
return { ok: false, format: "otlp-json", errors, warnings };
|
|
2808
|
+
}
|
|
2809
|
+
if (!Array.isArray(parsed.resourceSpans)) {
|
|
2810
|
+
pushPath(errors, "$.resourceSpans", "must be an array");
|
|
2811
|
+
return { ok: false, format: "otlp-json", errors, warnings };
|
|
2812
|
+
}
|
|
2813
|
+
parsed.resourceSpans.forEach((resourceSpan, rsi) => {
|
|
2814
|
+
const rsPath = `$.resourceSpans[${rsi}]`;
|
|
2815
|
+
if (!isRecord5(resourceSpan)) {
|
|
2816
|
+
pushPath(errors, rsPath, "must be an object");
|
|
2817
|
+
return;
|
|
2818
|
+
}
|
|
2819
|
+
if (!Array.isArray(resourceSpan.scopeSpans)) {
|
|
2820
|
+
pushPath(errors, `${rsPath}.scopeSpans`, "must be an array");
|
|
2821
|
+
return;
|
|
2822
|
+
}
|
|
2823
|
+
resourceSpan.scopeSpans.forEach((scopeSpan, ssi) => {
|
|
2824
|
+
const ssPath = `${rsPath}.scopeSpans[${ssi}]`;
|
|
2825
|
+
if (!isRecord5(scopeSpan)) {
|
|
2826
|
+
pushPath(errors, ssPath, "must be an object");
|
|
2827
|
+
return;
|
|
2828
|
+
}
|
|
2829
|
+
if (!Array.isArray(scopeSpan.spans)) {
|
|
2830
|
+
pushPath(errors, `${ssPath}.spans`, "must be an array");
|
|
2831
|
+
return;
|
|
2832
|
+
}
|
|
2833
|
+
scopeSpan.spans.forEach((span, spi) => {
|
|
2834
|
+
const spanPath = `${ssPath}.spans[${spi}]`;
|
|
2835
|
+
if (!isRecord5(span)) {
|
|
2836
|
+
pushPath(errors, spanPath, "must be an object");
|
|
2837
|
+
return;
|
|
2838
|
+
}
|
|
2839
|
+
if (!isHexId(span.traceId, 16)) {
|
|
2840
|
+
pushPath(
|
|
2841
|
+
errors,
|
|
2842
|
+
`${spanPath}.traceId`,
|
|
2843
|
+
"must be a 32-char hex trace id (16 bytes)"
|
|
2844
|
+
);
|
|
2845
|
+
}
|
|
2846
|
+
if (!isHexId(span.spanId, 8)) {
|
|
2847
|
+
pushPath(
|
|
2848
|
+
errors,
|
|
2849
|
+
`${spanPath}.spanId`,
|
|
2850
|
+
"must be a 16-char hex span id (8 bytes)"
|
|
2851
|
+
);
|
|
2852
|
+
}
|
|
2853
|
+
if (span.parentSpanId !== void 0 && !isHexId(span.parentSpanId, 8)) {
|
|
2854
|
+
pushPath(
|
|
2855
|
+
errors,
|
|
2856
|
+
`${spanPath}.parentSpanId`,
|
|
2857
|
+
"must be a 16-char hex span id when present"
|
|
2858
|
+
);
|
|
2859
|
+
}
|
|
2860
|
+
if (typeof span.name !== "string") {
|
|
2861
|
+
pushPath(errors, `${spanPath}.name`, "must be a string");
|
|
2862
|
+
}
|
|
2863
|
+
if (typeof span.startTimeUnixNano !== "string" || !/^\d+$/.test(span.startTimeUnixNano)) {
|
|
2864
|
+
pushPath(
|
|
2865
|
+
errors,
|
|
2866
|
+
`${spanPath}.startTimeUnixNano`,
|
|
2867
|
+
"must be a decimal-string 64-bit integer"
|
|
2868
|
+
);
|
|
2869
|
+
}
|
|
2870
|
+
if (span.endTimeUnixNano !== void 0 && (typeof span.endTimeUnixNano !== "string" || !/^\d+$/.test(span.endTimeUnixNano))) {
|
|
2871
|
+
pushPath(
|
|
2872
|
+
errors,
|
|
2873
|
+
`${spanPath}.endTimeUnixNano`,
|
|
2874
|
+
"must be a decimal-string 64-bit integer when present"
|
|
2875
|
+
);
|
|
2876
|
+
}
|
|
2877
|
+
if (typeof span.startTimeUnixNano === "string" && /^\d+$/.test(span.startTimeUnixNano) && typeof span.endTimeUnixNano === "string" && /^\d+$/.test(span.endTimeUnixNano)) {
|
|
2878
|
+
try {
|
|
2879
|
+
if (BigInt(span.endTimeUnixNano) < BigInt(span.startTimeUnixNano)) {
|
|
2880
|
+
pushPath(
|
|
2881
|
+
errors,
|
|
2882
|
+
`${spanPath}.endTimeUnixNano`,
|
|
2883
|
+
"must be >= startTimeUnixNano"
|
|
2884
|
+
);
|
|
2885
|
+
}
|
|
2886
|
+
} catch {
|
|
2887
|
+
pushPath(errors, `${spanPath}.endTimeUnixNano`, "out of integer range");
|
|
2888
|
+
}
|
|
2889
|
+
}
|
|
2890
|
+
if (Array.isArray(span.attributes)) {
|
|
2891
|
+
span.attributes.forEach((attr, ai) => {
|
|
2892
|
+
const attrPath = `${spanPath}.attributes[${ai}]`;
|
|
2893
|
+
if (!isRecord5(attr)) {
|
|
2894
|
+
pushPath(errors, attrPath, "must be an object");
|
|
2895
|
+
return;
|
|
2896
|
+
}
|
|
2897
|
+
if (typeof attr.key !== "string") {
|
|
2898
|
+
pushPath(errors, `${attrPath}.key`, "must be a string");
|
|
2899
|
+
}
|
|
2900
|
+
validateAnyValue(errors, `${attrPath}.value`, attr.value);
|
|
2901
|
+
});
|
|
2902
|
+
}
|
|
2903
|
+
if (typeof span.kind === "number") {
|
|
2904
|
+
if (!Number.isInteger(span.kind)) {
|
|
2905
|
+
pushPath(errors, `${spanPath}.kind`, "must be an integer SpanKind enum");
|
|
2906
|
+
}
|
|
2907
|
+
} else if (typeof span.kind === "string") {
|
|
2908
|
+
warnings.push(
|
|
2909
|
+
`${spanPath}.kind: string SpanKind is historical reader-compat only; producer wire format uses numeric enums`
|
|
2910
|
+
);
|
|
2911
|
+
} else if (span.kind !== void 0) {
|
|
2912
|
+
pushPath(
|
|
2913
|
+
errors,
|
|
2914
|
+
`${spanPath}.kind`,
|
|
2915
|
+
"must be numeric SpanKind or historical string enum"
|
|
2916
|
+
);
|
|
2917
|
+
}
|
|
2918
|
+
if (!isRecord5(span.status)) {
|
|
2919
|
+
pushPath(errors, `${spanPath}.status`, "must be an object");
|
|
2920
|
+
} else {
|
|
2921
|
+
const code = span.status.code;
|
|
2922
|
+
if (typeof code === "number") {
|
|
2923
|
+
if (![0, 1, 2].includes(code)) {
|
|
2924
|
+
pushPath(
|
|
2925
|
+
errors,
|
|
2926
|
+
`${spanPath}.status.code`,
|
|
2927
|
+
"must be numeric StatusCode 0 (UNSET), 1 (OK), or 2 (ERROR)"
|
|
2928
|
+
);
|
|
2929
|
+
}
|
|
2930
|
+
} else if (typeof code === "string") {
|
|
2931
|
+
const upper = code.toUpperCase();
|
|
2932
|
+
if (upper !== "STATUS_CODE_UNSET" && upper !== "STATUS_CODE_OK" && upper !== "STATUS_CODE_ERROR" && upper !== "UNSET" && upper !== "OK" && upper !== "ERROR" && !/^[012]$/.test(code.trim())) {
|
|
2933
|
+
pushPath(
|
|
2934
|
+
errors,
|
|
2935
|
+
`${spanPath}.status.code`,
|
|
2936
|
+
"unrecognized StatusCode string"
|
|
2937
|
+
);
|
|
2938
|
+
} else {
|
|
2939
|
+
warnings.push(
|
|
2940
|
+
`${spanPath}.status.code: string StatusCode is historical reader-compat only; producer wire format uses numeric 0/1/2`
|
|
2941
|
+
);
|
|
2942
|
+
}
|
|
2943
|
+
} else {
|
|
2944
|
+
pushPath(
|
|
2945
|
+
errors,
|
|
2946
|
+
`${spanPath}.status.code`,
|
|
2947
|
+
"must be numeric StatusCode 0/1/2 or historical string enum"
|
|
2948
|
+
);
|
|
2949
|
+
}
|
|
2950
|
+
}
|
|
2951
|
+
});
|
|
2952
|
+
});
|
|
2953
|
+
});
|
|
2954
|
+
return { ok: errors.length === 0, format: "otlp-json", errors, warnings };
|
|
2955
|
+
}
|
|
2698
2956
|
function validateExportContent(format, content) {
|
|
2699
2957
|
const errors = [];
|
|
2700
2958
|
const warnings = [EXPERIMENTAL];
|
|
@@ -2740,25 +2998,7 @@ function validateExportContent(format, content) {
|
|
|
2740
2998
|
return { ok: errors.length === 0, format, errors, warnings };
|
|
2741
2999
|
}
|
|
2742
3000
|
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 };
|
|
3001
|
+
return validateOtlpJson(content);
|
|
2762
3002
|
}
|
|
2763
3003
|
errors.push(`Unsupported export format`);
|
|
2764
3004
|
return { ok: false, format, errors, warnings };
|
|
@@ -3151,7 +3391,7 @@ async function exportCommand(runId, options = {}) {
|
|
|
3151
3391
|
const traceDir = resolveTraceDir({ dir: options.dir });
|
|
3152
3392
|
let events;
|
|
3153
3393
|
try {
|
|
3154
|
-
const result2 = await
|
|
3394
|
+
const result2 = await readRunPersistedEvents(id, traceDir);
|
|
3155
3395
|
events = result2?.events ?? [];
|
|
3156
3396
|
} catch (e) {
|
|
3157
3397
|
const msg = e instanceof Error ? e.message : String(e);
|
|
@@ -3167,7 +3407,13 @@ Trace directory: ${traceDir}`);
|
|
|
3167
3407
|
}
|
|
3168
3408
|
let tree;
|
|
3169
3409
|
try {
|
|
3170
|
-
|
|
3410
|
+
const trees = persistedInspectEventsToRunTrees(events, {
|
|
3411
|
+
coalesceLifecycle: true
|
|
3412
|
+
});
|
|
3413
|
+
tree = trees.find((candidate) => candidate.runId === id) ?? trees[0];
|
|
3414
|
+
if (tree === void 0) {
|
|
3415
|
+
throw new Error("No run tree could be built from persisted events");
|
|
3416
|
+
}
|
|
3171
3417
|
} catch (e) {
|
|
3172
3418
|
const msg = e instanceof Error ? e.message : String(e);
|
|
3173
3419
|
console.error(`[AgentInspect] export failed: ${msg}`);
|
|
@@ -3195,7 +3441,9 @@ Trace directory: ${traceDir}`);
|
|
|
3195
3441
|
await mkdir(path19.dirname(outPath), { recursive: true });
|
|
3196
3442
|
await writeFile(outPath, result.content, "utf-8");
|
|
3197
3443
|
const vlabel = validation !== void 0 ? validation.ok ? "ok" : "failed" : "skipped";
|
|
3198
|
-
console.
|
|
3444
|
+
console.error(
|
|
3445
|
+
`Wrote ${result.fileExtension} export to ${outPath} (validation: ${vlabel})`
|
|
3446
|
+
);
|
|
3199
3447
|
if (validation !== void 0 && !validation.ok) {
|
|
3200
3448
|
console.error("Validation errors:", validation.errors.join("; "));
|
|
3201
3449
|
}
|
|
@@ -3208,7 +3456,9 @@ Trace directory: ${traceDir}`);
|
|
|
3208
3456
|
warnings: [...result.warnings, ...validation?.warnings ?? []],
|
|
3209
3457
|
validation
|
|
3210
3458
|
};
|
|
3211
|
-
if (outPath
|
|
3459
|
+
if (outPath !== void 0) {
|
|
3460
|
+
payload.out = outPath;
|
|
3461
|
+
} else {
|
|
3212
3462
|
payload.content = result.content;
|
|
3213
3463
|
}
|
|
3214
3464
|
console.log(JSON.stringify(payload, null, 2));
|
|
@@ -3565,7 +3815,7 @@ async function newestTraceMtimeMs(traceDir) {
|
|
|
3565
3815
|
}
|
|
3566
3816
|
async function loadSessionRuns(traceDir) {
|
|
3567
3817
|
try {
|
|
3568
|
-
const mod = await import('./src-
|
|
3818
|
+
const mod = await import('./src-NXAYHG34.mjs');
|
|
3569
3819
|
const dbPath = mod.resolveIndexDbPath(traceDir);
|
|
3570
3820
|
const status = mod.indexStatus(dbPath);
|
|
3571
3821
|
if (!status.healthy) {
|
|
@@ -4298,7 +4548,7 @@ var STRICT_PROFILE_EXTRA_KEYS = [
|
|
|
4298
4548
|
"retrieval",
|
|
4299
4549
|
"query"
|
|
4300
4550
|
];
|
|
4301
|
-
function
|
|
4551
|
+
function isRecord6(value) {
|
|
4302
4552
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4303
4553
|
}
|
|
4304
4554
|
function toKey(key) {
|
|
@@ -4727,7 +4977,7 @@ var Redactor2 = class {
|
|
|
4727
4977
|
});
|
|
4728
4978
|
return out;
|
|
4729
4979
|
}
|
|
4730
|
-
if (
|
|
4980
|
+
if (isRecord6(value)) {
|
|
4731
4981
|
if (state.seen.has(value)) return state.seen.get(value);
|
|
4732
4982
|
const out = {};
|
|
4733
4983
|
state.seen.set(value, out);
|
|
@@ -4762,7 +5012,7 @@ var REDACTION_POLICY_LIMITS = {
|
|
|
4762
5012
|
};
|
|
4763
5013
|
var ALLOWED_TOP_LEVEL = /* @__PURE__ */ new Set(["version", "extraKeys", "patterns"]);
|
|
4764
5014
|
var ALLOWED_PATTERN_FIELDS = /* @__PURE__ */ new Set(["id", "type", "value", "severity"]);
|
|
4765
|
-
function
|
|
5015
|
+
function isRecord7(value) {
|
|
4766
5016
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
4767
5017
|
}
|
|
4768
5018
|
function rejectRemotePolicyPath(policyPath) {
|
|
@@ -4802,7 +5052,7 @@ function rejectUnknownFields(record, allowed, label) {
|
|
|
4802
5052
|
}
|
|
4803
5053
|
function compilePatternDetector(input3, index) {
|
|
4804
5054
|
const label = `patterns[${index}]`;
|
|
4805
|
-
if (!
|
|
5055
|
+
if (!isRecord7(input3)) throw new Error(`${label} must be an object.`);
|
|
4806
5056
|
const typeEarly = input3.type;
|
|
4807
5057
|
if (typeEarly === "typed") {
|
|
4808
5058
|
throw new Error(
|
|
@@ -4857,7 +5107,7 @@ function compilePatternDetector(input3, index) {
|
|
|
4857
5107
|
};
|
|
4858
5108
|
}
|
|
4859
5109
|
function compileRedactionPolicy(raw, policyPath) {
|
|
4860
|
-
if (!
|
|
5110
|
+
if (!isRecord7(raw)) {
|
|
4861
5111
|
throw new Error(`Redaction policy must be a JSON object (${policyPath}).`);
|
|
4862
5112
|
}
|
|
4863
5113
|
rejectUnknownFields(raw, ALLOWED_TOP_LEVEL, "Redaction policy");
|
|
@@ -5879,7 +6129,7 @@ async function openCommand(input3, options = {}, stdin = process.stdin) {
|
|
|
5879
6129
|
}
|
|
5880
6130
|
}
|
|
5881
6131
|
}
|
|
5882
|
-
function
|
|
6132
|
+
function isRecord8(value) {
|
|
5883
6133
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5884
6134
|
}
|
|
5885
6135
|
function parseTarget(value) {
|
|
@@ -5888,7 +6138,7 @@ function parseTarget(value) {
|
|
|
5888
6138
|
throw new Error('Unsupported migration target. Use "--to 1.0".');
|
|
5889
6139
|
}
|
|
5890
6140
|
function formatOf(value) {
|
|
5891
|
-
if (!
|
|
6141
|
+
if (!isRecord8(value)) return "unknown";
|
|
5892
6142
|
if (value.schemaVersion === "0.1") return "0.1";
|
|
5893
6143
|
if (value.schemaVersion === "0.2") return "0.2";
|
|
5894
6144
|
if (value.schemaVersion === "1.0") return "1.0";
|
|
@@ -12389,16 +12639,146 @@ function demoTemplate(framework) {
|
|
|
12389
12639
|
switch (framework) {
|
|
12390
12640
|
case "ai-sdk":
|
|
12391
12641
|
return `/**
|
|
12392
|
-
* AI SDK starter \u2014
|
|
12393
|
-
* Install: npm install agent-inspect @agent-inspect/ai-sdk ai
|
|
12642
|
+
* AI SDK starter \u2014 keyless MockLanguageModelV3 + @agent-inspect/ai-sdk telemetry.
|
|
12643
|
+
* Install: npm install agent-inspect @agent-inspect/ai-sdk ai@6.0.210 zod
|
|
12394
12644
|
*/
|
|
12395
|
-
import {
|
|
12645
|
+
import { generateText, stepCountIs, tool } from "ai";
|
|
12646
|
+
import { MockLanguageModelV3 } from "ai/test";
|
|
12647
|
+
import { agentInspect } from "@agent-inspect/ai-sdk";
|
|
12648
|
+
import { z } from "zod";
|
|
12649
|
+
import { mkdirSync, readdirSync, readFileSync, rmSync } from "node:fs";
|
|
12650
|
+
import path from "node:path";
|
|
12651
|
+
import { randomUUID } from "node:crypto";
|
|
12652
|
+
|
|
12653
|
+
const SESSION = randomUUID().slice(0, 8);
|
|
12654
|
+
const TRACE_DIR = path.join(".agent-inspect", \`demo-\${SESSION}\`);
|
|
12655
|
+
const ANSWER = "You have 2 orders";
|
|
12656
|
+
const CORRECT_RUN = \`ai-sdk-demo-correct-\${SESSION}\`;
|
|
12657
|
+
const WRONG_RUN = \`ai-sdk-demo-wrong-\${SESSION}\`;
|
|
12658
|
+
|
|
12659
|
+
const usage = {
|
|
12660
|
+
inputTokens: { total: 4, noCache: 4, cacheRead: 0, cacheWrite: 0 },
|
|
12661
|
+
outputTokens: { total: 3, text: 3, reasoning: 0 },
|
|
12662
|
+
};
|
|
12663
|
+
|
|
12664
|
+
const lookupOrders = tool({
|
|
12665
|
+
description: "Look up orders for a user",
|
|
12666
|
+
inputSchema: z.object({ userId: z.string() }),
|
|
12667
|
+
execute: async () => ({ orders: 2 }),
|
|
12668
|
+
});
|
|
12669
|
+
|
|
12670
|
+
const deleteOrders = tool({
|
|
12671
|
+
description: "Delete orders for a user (wrong path)",
|
|
12672
|
+
inputSchema: z.object({ userId: z.string() }),
|
|
12673
|
+
execute: async () => ({ orders: 2 }),
|
|
12674
|
+
});
|
|
12675
|
+
|
|
12676
|
+
async function runPath(runName, toolName) {
|
|
12677
|
+
const integration = agentInspect({
|
|
12678
|
+
traceDir: TRACE_DIR,
|
|
12679
|
+
runName,
|
|
12680
|
+
capture: "metadata-only",
|
|
12681
|
+
});
|
|
12682
|
+
let step = 0;
|
|
12683
|
+
try {
|
|
12684
|
+
const result = await generateText({
|
|
12685
|
+
model: new MockLanguageModelV3({
|
|
12686
|
+
provider: "fixture-provider",
|
|
12687
|
+
modelId: "fixture-tools",
|
|
12688
|
+
doGenerate: async () => {
|
|
12689
|
+
step += 1;
|
|
12690
|
+
if (step === 1) {
|
|
12691
|
+
return {
|
|
12692
|
+
content: [
|
|
12693
|
+
{
|
|
12694
|
+
type: "tool-call",
|
|
12695
|
+
toolCallId: \`call-\${toolName}\`,
|
|
12696
|
+
toolName,
|
|
12697
|
+
input: JSON.stringify({ userId: "u1" }),
|
|
12698
|
+
},
|
|
12699
|
+
],
|
|
12700
|
+
finishReason: { unified: "tool-calls", raw: "tool-calls" },
|
|
12701
|
+
usage,
|
|
12702
|
+
warnings: [],
|
|
12703
|
+
};
|
|
12704
|
+
}
|
|
12705
|
+
return {
|
|
12706
|
+
content: [{ type: "text", text: ANSWER }],
|
|
12707
|
+
finishReason: { unified: "stop", raw: "stop" },
|
|
12708
|
+
usage,
|
|
12709
|
+
warnings: [],
|
|
12710
|
+
};
|
|
12711
|
+
},
|
|
12712
|
+
}),
|
|
12713
|
+
tools: { lookup_orders: lookupOrders, delete_orders: deleteOrders },
|
|
12714
|
+
prompt: "How many orders do I have?",
|
|
12715
|
+
stopWhen: stepCountIs(5),
|
|
12716
|
+
experimental_telemetry: {
|
|
12717
|
+
isEnabled: true,
|
|
12718
|
+
recordInputs: false,
|
|
12719
|
+
recordOutputs: false,
|
|
12720
|
+
integrations: [integration],
|
|
12721
|
+
},
|
|
12722
|
+
});
|
|
12723
|
+
if (result.text !== ANSWER) {
|
|
12724
|
+
throw new Error(\`unexpected answer for \${runName}: \${result.text}\`);
|
|
12725
|
+
}
|
|
12726
|
+
} finally {
|
|
12727
|
+
await integration.flush();
|
|
12728
|
+
await integration.close();
|
|
12729
|
+
}
|
|
12730
|
+
}
|
|
12731
|
+
|
|
12732
|
+
function selectRunIdByName(runName) {
|
|
12733
|
+
const files = readdirSync(TRACE_DIR).filter((f) => f.endsWith(".jsonl"));
|
|
12734
|
+
const matches = [];
|
|
12735
|
+
for (const file of files) {
|
|
12736
|
+
const text = readFileSync(path.join(TRACE_DIR, file), "utf8");
|
|
12737
|
+
if (text.includes(\`"name":"\${runName}"\`) || text.includes(\`"name": "\${runName}"\`)) {
|
|
12738
|
+
matches.push(file.replace(/\\.jsonl$/, ""));
|
|
12739
|
+
}
|
|
12740
|
+
}
|
|
12741
|
+
if (matches.length !== 1) {
|
|
12742
|
+
throw new Error(
|
|
12743
|
+
\`expected exactly one run named \${runName}, found \${matches.length}\`,
|
|
12744
|
+
);
|
|
12745
|
+
}
|
|
12746
|
+
return matches[0];
|
|
12747
|
+
}
|
|
12748
|
+
|
|
12749
|
+
function assertToolExecuted(runId, requiredTool) {
|
|
12750
|
+
const text = readFileSync(path.join(TRACE_DIR, \`\${runId}.jsonl\`), "utf8");
|
|
12751
|
+
const toolHits = text
|
|
12752
|
+
.split("\\n")
|
|
12753
|
+
.filter(Boolean)
|
|
12754
|
+
.map((line) => JSON.parse(line))
|
|
12755
|
+
.filter(
|
|
12756
|
+
(ev) =>
|
|
12757
|
+
(ev.kind === "TOOL" || ev.attributes?.stepType === "tool") &&
|
|
12758
|
+
(ev.name === requiredTool || ev.attributes?.toolName === requiredTool),
|
|
12759
|
+
);
|
|
12760
|
+
if (toolHits.length === 0) {
|
|
12761
|
+
throw new Error(\`expected TOOL events for \${requiredTool} in \${runId}\`);
|
|
12762
|
+
}
|
|
12763
|
+
}
|
|
12396
12764
|
|
|
12397
12765
|
async function main() {
|
|
12398
|
-
|
|
12399
|
-
|
|
12400
|
-
|
|
12401
|
-
|
|
12766
|
+
mkdirSync(TRACE_DIR, { recursive: true });
|
|
12767
|
+
try {
|
|
12768
|
+
await runPath(CORRECT_RUN, "lookup_orders");
|
|
12769
|
+
await runPath(WRONG_RUN, "delete_orders");
|
|
12770
|
+
const correctId = selectRunIdByName(CORRECT_RUN);
|
|
12771
|
+
const wrongId = selectRunIdByName(WRONG_RUN);
|
|
12772
|
+
assertToolExecuted(correctId, "lookup_orders");
|
|
12773
|
+
assertToolExecuted(wrongId, "delete_orders");
|
|
12774
|
+
console.log(\`Trace written to \${TRACE_DIR}/\`);
|
|
12775
|
+
console.log(\`Correct path runId: \${correctId}\`);
|
|
12776
|
+
console.log(\`Wrong path runId: \${wrongId}\`);
|
|
12777
|
+
console.log(\`Next: npx agent-inspect check \${correctId} --dir \${TRACE_DIR} --required-tool lookup_orders\`);
|
|
12778
|
+
} catch (error) {
|
|
12779
|
+
rmSync(TRACE_DIR, { recursive: true, force: true });
|
|
12780
|
+
throw error;
|
|
12781
|
+
}
|
|
12402
12782
|
}
|
|
12403
12783
|
|
|
12404
12784
|
main().catch((error) => {
|
|
@@ -13391,7 +13771,7 @@ function isModuleNotFound4(e) {
|
|
|
13391
13771
|
}
|
|
13392
13772
|
async function loadIndexSqlite() {
|
|
13393
13773
|
try {
|
|
13394
|
-
return await import('./src-
|
|
13774
|
+
return await import('./src-NXAYHG34.mjs');
|
|
13395
13775
|
} catch (e) {
|
|
13396
13776
|
if (isModuleNotFound4(e)) {
|
|
13397
13777
|
console.error(
|