agent-inspect 6.31.5 → 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 +13 -0
- package/README.md +1 -1
- package/docs/AI-SDK-ADOPTION.md +62 -34
- package/docs/SAFE-TRACE-SHARING.md +1 -1
- package/package.json +1 -1
- package/packages/cli/dist/{chunk-LKEPABND.mjs → chunk-QV73NM25.mjs} +100 -31
- package/packages/cli/dist/chunk-QV73NM25.mjs.map +1 -0
- package/packages/cli/dist/index.cjs +474 -92
- package/packages/cli/dist/index.cjs.map +1 -1
- package/packages/cli/dist/index.mjs +379 -67
- package/packages/cli/dist/index.mjs.map +1 -1
- package/packages/cli/dist/{src-4WYF5RFI.mjs → src-KFOBXFPN.mjs} +3 -3
- package/packages/cli/dist/{src-4WYF5RFI.mjs.map → src-KFOBXFPN.mjs.map} +1 -1
- package/packages/core/dist/advanced.cjs +95 -23
- package/packages/core/dist/advanced.cjs.map +1 -1
- package/packages/core/dist/advanced.mjs +11 -11
- package/packages/core/dist/checks.cjs +2 -5
- package/packages/core/dist/checks.cjs.map +1 -1
- package/packages/core/dist/checks.mjs +3 -3
- 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-NY4ILMXK.mjs → chunk-7YYS742B.mjs} +50 -13
- package/packages/core/dist/chunk-7YYS742B.mjs.map +1 -0
- package/packages/core/dist/{chunk-2KJR6X4V.mjs → chunk-DK3OW6UI.mjs} +3 -3
- package/packages/core/dist/chunk-DK3OW6UI.mjs.map +1 -0
- package/packages/core/dist/{chunk-PKDBFBJ7.mjs → chunk-LXYPM2ZO.mjs} +5 -8
- package/packages/core/dist/{chunk-PKDBFBJ7.mjs.map → chunk-LXYPM2ZO.mjs.map} +1 -1
- package/packages/core/dist/{chunk-INE5IWLN.mjs → chunk-N5PZAI6Q.mjs} +3 -3
- package/packages/core/dist/{chunk-INE5IWLN.mjs.map → chunk-N5PZAI6Q.mjs.map} +1 -1
- 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/{chunk-MTMTXTJL.mjs → chunk-VQUB3WRI.mjs} +4 -4
- package/packages/core/dist/{chunk-MTMTXTJL.mjs.map → chunk-VQUB3WRI.mjs.map} +1 -1
- package/packages/core/dist/exporters.cjs +253 -50
- package/packages/core/dist/exporters.cjs.map +1 -1
- package/packages/core/dist/exporters.mjs +208 -42
- package/packages/core/dist/exporters.mjs.map +1 -1
- package/packages/core/dist/index.cjs +1 -1
- package/packages/core/dist/index.cjs.map +1 -1
- package/packages/core/dist/index.mjs +4 -4
- 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/core/dist/writers.cjs +1 -1
- package/packages/core/dist/writers.cjs.map +1 -1
- package/packages/core/dist/writers.mjs +1 -1
- package/packages/cli/dist/chunk-LKEPABND.mjs.map +0 -1
- package/packages/core/dist/chunk-2KJR6X4V.mjs.map +0 -1
- package/packages/core/dist/chunk-NY4ILMXK.mjs.map +0 -1
- package/packages/core/dist/chunk-OSGNGRHF.mjs.map +0 -1
- package/packages/core/dist/chunk-Q5SLKV2Y.mjs.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { ATTRIBUTION_CONFIDENCES, createSafetyRawContentRule, createSafetyRedactionRule, createSafetySecretPatternRule, createSafetyOversizedAttributeRule, resolveTraceDir, parseDuration, buildSessionIndex, resolveBundleRunIds, getTraceFilePath, openTrace, sha256Hex, collectTraceSchemaVersions, aggregateBundleSafeStatus, bundleFailsOnSafety, bundleRunAssetRelativePath, buildPlaceholderArtifact, EVIDENCE_HTML_FILENAME, EVIDENCE_MANIFEST_FILENAME, buildBundleMetadata, buildBundleSummaryMarkdown, buildEvidenceHtmlShell, buildEvidenceProvenanceViewHtml, EVIDENCE_FORMAT_VERSION, inferEvidenceFileRole, buildEvidenceSafetyViewHtml, buildEvidenceDiffViewHtml, buildEvidenceCircuitViewHtml, buildEvidenceOutcomesViewHtml, buildEvidenceContractsViewHtml, buildEvidenceToolsLlmViewHtml, buildEvidenceCausalFailureViewHtml, buildEvidenceTimelineViewHtml, buildEvidenceTreeViewHtml, buildEvidenceManifest, serializeEvidenceManifest, buildZipArchive, assertBundlePathContained, enrichSessionRunRecord, normalizeBundleOutputPath, sanitizeBundleRunId, defaultBundleOutputPath, runTraceChecks, assertEvidenceRelativePath, TraceDirectory, loadTraceMetadataList, loadSessionRunRecords, TraceReadError, resolveRedactionProfile, applyProfileMetadataCaps, Redactor, flattenTree, escapeHtml, safeString, compactAttributes, stableJson, escapeMarkdown, DEFAULT_REDACT_KEYS, truncateStringForProfile, stringContainsHighConfidenceCredential, isCredentialSensitiveKey, extractMetadata, filterTraces, truncateName, buildRunSummary, formatDuration, formatTimestamp, renderErrorLine, isAgentInspectTrace, defineTraceContract, filterMetasBySessionScope, evaluateTraceContract, aggregateSessionCheckResults, createBaselineRegressionRule, summarizeSemanticParity, buildEvidenceCiPackage, verifyEvidenceDirectory, diffTraceEvents, renderRunDiff, buildRunTimeline, renderTimeline, buildTraceStats, renderTraceStats, parseDurationFilter, searchTraces, formatStepLabel, buildActivitySummary, renderActivitySummaryHuman, buildRunWhatSummary, renderRunWhat, buildLocalExplanation, resolveSuiteTemplate, defaultSuiteConfigTemplate, loadSuiteConfig, validateSuiteConfig, runSuite, renderSuiteReport, analyzeCohort, renderCohortReport, gateHasThresholds, runGate, renderGateReport, persistedInspectEventsToTraceEvents, renderStepLine, getIndent, TreeBuilder,
|
|
2
|
+
import { ATTRIBUTION_CONFIDENCES, createSafetyRawContentRule, createSafetyRedactionRule, createSafetySecretPatternRule, createSafetyOversizedAttributeRule, resolveTraceDir, parseDuration, buildSessionIndex, resolveBundleRunIds, getTraceFilePath, openTrace, sha256Hex, collectTraceSchemaVersions, aggregateBundleSafeStatus, bundleFailsOnSafety, bundleRunAssetRelativePath, buildPlaceholderArtifact, EVIDENCE_HTML_FILENAME, EVIDENCE_MANIFEST_FILENAME, buildBundleMetadata, buildBundleSummaryMarkdown, buildEvidenceHtmlShell, buildEvidenceProvenanceViewHtml, EVIDENCE_FORMAT_VERSION, inferEvidenceFileRole, buildEvidenceSafetyViewHtml, buildEvidenceDiffViewHtml, buildEvidenceCircuitViewHtml, buildEvidenceOutcomesViewHtml, buildEvidenceContractsViewHtml, buildEvidenceToolsLlmViewHtml, buildEvidenceCausalFailureViewHtml, buildEvidenceTimelineViewHtml, buildEvidenceTreeViewHtml, buildEvidenceManifest, serializeEvidenceManifest, buildZipArchive, assertBundlePathContained, enrichSessionRunRecord, normalizeBundleOutputPath, sanitizeBundleRunId, defaultBundleOutputPath, runTraceChecks, assertEvidenceRelativePath, TraceDirectory, loadTraceMetadataList, loadSessionRunRecords, TraceReadError, resolveRedactionProfile, applyProfileMetadataCaps, Redactor, flattenTree, escapeHtml, safeString, compactAttributes, stableJson, escapeMarkdown, DEFAULT_REDACT_KEYS, truncateStringForProfile, stringContainsHighConfidenceCredential, isCredentialSensitiveKey, extractMetadata, filterTraces, truncateName, buildRunSummary, formatDuration, formatTimestamp, renderErrorLine, isAgentInspectTrace, persistedInspectEventsToRunTrees, defineTraceContract, filterMetasBySessionScope, evaluateTraceContract, aggregateSessionCheckResults, createBaselineRegressionRule, summarizeSemanticParity, buildEvidenceCiPackage, verifyEvidenceDirectory, diffTraceEvents, renderRunDiff, buildRunTimeline, renderTimeline, buildTraceStats, renderTraceStats, parseDurationFilter, searchTraces, formatStepLabel, buildActivitySummary, renderActivitySummaryHuman, buildRunWhatSummary, renderRunWhat, buildLocalExplanation, resolveSuiteTemplate, defaultSuiteConfigTemplate, loadSuiteConfig, validateSuiteConfig, runSuite, renderSuiteReport, analyzeCohort, renderCohortReport, gateHasThresholds, runGate, renderGateReport, persistedInspectEventsToTraceEvents, renderStepLine, getIndent, TreeBuilder, validateEvent, traceEventToPersistedInspectEvent, isPersistedInspectEvent, createRunStatusRule, createStructureOrphanRule, createStructureCycleRule, createRunDurationRule, createMaxStepDurationRule, createRequireCompletedRule, createStallDetectionRule, createObservedOutcomeRule, createRunDepthRule, createToolUsageRule, createLlmUsageRule, createStructureRelationshipRule, createStructureParallelWidthRule, projectLogicalEvents, summarizeObservedOutcomes, extractOutcomesFromTraceEvents, renderObservedOutcomesMarkdown, renderObservedOutcomesHtml, DEFAULT_SUITE_ARTIFACTS_DIR, parseCohortMetricList, COHORT_METRIC_IDS, parseGateList, nanoid, isAttributionConfidence, zeroKinds, diffRuns, manualTraceEventsToComparableRun } from './chunk-QV73NM25.mjs';
|
|
3
3
|
import { realpathSync, constants as constants$1, existsSync, readFileSync } from 'fs';
|
|
4
4
|
import path19 from 'path';
|
|
5
5
|
import { fileURLToPath, pathToFileURL } from 'url';
|
|
@@ -14,7 +14,7 @@ import { createServer } from 'http';
|
|
|
14
14
|
import { createRequire } from 'module';
|
|
15
15
|
|
|
16
16
|
// package.json
|
|
17
|
-
var version = "6.31.
|
|
17
|
+
var version = "6.31.7";
|
|
18
18
|
|
|
19
19
|
// packages/cli/src/trace-dir-scale.ts
|
|
20
20
|
var TRACE_COUNT_WARN = 1e3;
|
|
@@ -333,7 +333,7 @@ function mapReaderFormat(format) {
|
|
|
333
333
|
function isMissingFileError(error) {
|
|
334
334
|
return error !== null && typeof error === "object" && "code" in error && error.code === "ENOENT";
|
|
335
335
|
}
|
|
336
|
-
async function
|
|
336
|
+
async function readRunPersistedEvents(runId, traceDir) {
|
|
337
337
|
const filePath = getTraceFilePath(runId, traceDir);
|
|
338
338
|
try {
|
|
339
339
|
await access(filePath);
|
|
@@ -341,16 +341,24 @@ async function readRunTraceEvents(runId, traceDir) {
|
|
|
341
341
|
{ type: "file", path: filePath },
|
|
342
342
|
{ format: "agent-inspect-jsonl" }
|
|
343
343
|
);
|
|
344
|
-
const events = persistedInspectEventsToTraceEvents(result.events);
|
|
345
344
|
return {
|
|
346
|
-
events,
|
|
347
|
-
format: events.length > 0 ? mapReaderFormat(result.format) : "empty"
|
|
345
|
+
events: result.events,
|
|
346
|
+
format: result.events.length > 0 ? mapReaderFormat(result.format) : "empty"
|
|
348
347
|
};
|
|
349
348
|
} catch (error) {
|
|
350
349
|
if (isMissingFileError(error)) return void 0;
|
|
351
350
|
throw error;
|
|
352
351
|
}
|
|
353
352
|
}
|
|
353
|
+
async function readRunTraceEvents(runId, traceDir) {
|
|
354
|
+
const persisted = await readRunPersistedEvents(runId, traceDir);
|
|
355
|
+
if (persisted === void 0) return void 0;
|
|
356
|
+
const events = persistedInspectEventsToTraceEvents(persisted.events);
|
|
357
|
+
return {
|
|
358
|
+
events,
|
|
359
|
+
format: events.length > 0 ? persisted.format : "empty"
|
|
360
|
+
};
|
|
361
|
+
}
|
|
354
362
|
|
|
355
363
|
// packages/cli/src/view.ts
|
|
356
364
|
function isModuleNotFound(e) {
|
|
@@ -1775,6 +1783,8 @@ var CONNECTION_PROTOCOLS = /* @__PURE__ */ new Set([
|
|
|
1775
1783
|
"amqps:"
|
|
1776
1784
|
]);
|
|
1777
1785
|
var CONNECTION_URI = /^(?:postgres|postgresql|mysql|mariadb|mongodb(?:\+srv)?|rediss?|amqps?):\/\/[^\s]+$/i;
|
|
1786
|
+
var CONNECTION_USERINFO = /^(postgres|postgresql|mysql|mariadb|mongodb(?:\+srv)?|rediss?|amqps?):\/\/([^@/?#]+)@(.+)$/i;
|
|
1787
|
+
var CONNECTION_HAS_USERINFO = /^(?:postgres|postgresql|mysql|mariadb|mongodb(?:\+srv)?|rediss?|amqps?):\/\/[^@/?#]+@/i;
|
|
1778
1788
|
var UUID_SEGMENT = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
1779
1789
|
var HEX_SEGMENT = /^[0-9a-f]{12,}$/i;
|
|
1780
1790
|
var NUMERIC_SEGMENT = /^\d{5,}$/;
|
|
@@ -1798,6 +1808,28 @@ function parseRedactableUrl(value) {
|
|
|
1798
1808
|
return void 0;
|
|
1799
1809
|
}
|
|
1800
1810
|
}
|
|
1811
|
+
function redactConnectionUserinfoFallback(value, replacement) {
|
|
1812
|
+
const trimmed = value.trim();
|
|
1813
|
+
const match = CONNECTION_USERINFO.exec(trimmed);
|
|
1814
|
+
if (match) {
|
|
1815
|
+
const [, scheme, , rest] = match;
|
|
1816
|
+
if (scheme && rest && rest.length > 0) {
|
|
1817
|
+
return {
|
|
1818
|
+
value: `${scheme}://${rest}`,
|
|
1819
|
+
credentialRedacted: true,
|
|
1820
|
+
identifiersMasked: false
|
|
1821
|
+
};
|
|
1822
|
+
}
|
|
1823
|
+
}
|
|
1824
|
+
if (looksLikeConnectionUri(trimmed) && CONNECTION_HAS_USERINFO.test(trimmed)) {
|
|
1825
|
+
return {
|
|
1826
|
+
value: replacement,
|
|
1827
|
+
credentialRedacted: true,
|
|
1828
|
+
identifiersMasked: false
|
|
1829
|
+
};
|
|
1830
|
+
}
|
|
1831
|
+
return void 0;
|
|
1832
|
+
}
|
|
1801
1833
|
function isHttpProtocol(protocol) {
|
|
1802
1834
|
return protocol === "http:" || protocol === "https:";
|
|
1803
1835
|
}
|
|
@@ -1839,9 +1871,11 @@ function redactUrlString(value, options) {
|
|
|
1839
1871
|
identifiersMasked: false
|
|
1840
1872
|
};
|
|
1841
1873
|
if (!looksLikeUrlForRedaction(value)) return unchanged;
|
|
1842
|
-
const url = parseRedactableUrl(value);
|
|
1843
|
-
if (!url) return unchanged;
|
|
1844
1874
|
const replacement = options.replacement ?? "[REDACTED]";
|
|
1875
|
+
const url = parseRedactableUrl(value);
|
|
1876
|
+
if (!url) {
|
|
1877
|
+
return redactConnectionUserinfoFallback(value, replacement) ?? unchanged;
|
|
1878
|
+
}
|
|
1845
1879
|
const idPlaceholder = options.idPlaceholder ?? "[id]";
|
|
1846
1880
|
const http = isHttpProtocol(url.protocol);
|
|
1847
1881
|
let credentialRedacted = url.username.length > 0 || url.password.length > 0;
|
|
@@ -2530,6 +2564,10 @@ function exportOpenInference(tree, options) {
|
|
|
2530
2564
|
warnings
|
|
2531
2565
|
};
|
|
2532
2566
|
}
|
|
2567
|
+
var OTLP_STATUS_CODE_UNSET = 0;
|
|
2568
|
+
var OTLP_STATUS_CODE_OK = 1;
|
|
2569
|
+
var OTLP_STATUS_CODE_ERROR = 2;
|
|
2570
|
+
var OTLP_SPAN_KIND_INTERNAL = 1;
|
|
2533
2571
|
function hexFrom2(seed, byteLen) {
|
|
2534
2572
|
return crypto.createHash("sha256").update(seed, "utf8").digest("hex").slice(0, byteLen * 2);
|
|
2535
2573
|
}
|
|
@@ -2542,7 +2580,19 @@ function stringAttr(key, value) {
|
|
|
2542
2580
|
return { key, value: { stringValue: value } };
|
|
2543
2581
|
}
|
|
2544
2582
|
function intAttr(key, value) {
|
|
2545
|
-
return { key, value: { intValue: String(value) } };
|
|
2583
|
+
return { key, value: { intValue: String(Math.trunc(value)) } };
|
|
2584
|
+
}
|
|
2585
|
+
function doubleAttr(key, value) {
|
|
2586
|
+
return { key, value: { doubleValue: value } };
|
|
2587
|
+
}
|
|
2588
|
+
function boolAttr(key, value) {
|
|
2589
|
+
return { key, value: { boolValue: value } };
|
|
2590
|
+
}
|
|
2591
|
+
function numberAttr(key, value) {
|
|
2592
|
+
if (Number.isFinite(value) && !Number.isInteger(value)) {
|
|
2593
|
+
return doubleAttr(key, value);
|
|
2594
|
+
}
|
|
2595
|
+
return intAttr(key, value);
|
|
2546
2596
|
}
|
|
2547
2597
|
function genAiOperationName(kind) {
|
|
2548
2598
|
switch (kind) {
|
|
@@ -2556,10 +2606,27 @@ function genAiOperationName(kind) {
|
|
|
2556
2606
|
return void 0;
|
|
2557
2607
|
}
|
|
2558
2608
|
}
|
|
2609
|
+
function resolveSpanTimes(ev) {
|
|
2610
|
+
const startedAtMs = typeof ev.attributes?.startedAtMs === "number" && Number.isFinite(ev.attributes.startedAtMs) ? ev.attributes.startedAtMs : void 0;
|
|
2611
|
+
const endedAtMs = typeof ev.attributes?.endedAtMs === "number" && Number.isFinite(ev.attributes.endedAtMs) ? ev.attributes.endedAtMs : void 0;
|
|
2612
|
+
const startMs = startedAtMs ?? ev.timestamp;
|
|
2613
|
+
const startNs = String(unixNano2(startMs));
|
|
2614
|
+
if (endedAtMs !== void 0) {
|
|
2615
|
+
return { startNs, endNs: String(unixNano2(endedAtMs)) };
|
|
2616
|
+
}
|
|
2617
|
+
if (ev.durationMs !== void 0 && Number.isFinite(ev.durationMs)) {
|
|
2618
|
+
return {
|
|
2619
|
+
startNs,
|
|
2620
|
+
endNs: String(unixNano2(startMs) + unixNano2(ev.durationMs))
|
|
2621
|
+
};
|
|
2622
|
+
}
|
|
2623
|
+
return { startNs };
|
|
2624
|
+
}
|
|
2559
2625
|
function exportOtlpJson(tree, options) {
|
|
2560
2626
|
const warnings = [
|
|
2561
2627
|
"OTLP JSON export uses OTel GenAI-aligned attributes where applicable; experimental until verified against specific collectors.",
|
|
2562
|
-
"Not OTLP gRPC/protobuf \u2014 JSON mapping only. Generated locally; no network upload."
|
|
2628
|
+
"Not OTLP gRPC/protobuf \u2014 JSON mapping only. Generated locally; no network upload.",
|
|
2629
|
+
"Status and span kind use OTLP numeric enums (StatusCode 0/1/2, SpanKind INTERNAL=1)."
|
|
2563
2630
|
];
|
|
2564
2631
|
const traceId = hexFrom2(`trace:${tree.runId}`, 16);
|
|
2565
2632
|
const includeAttributes = options?.includeAttributes ?? false;
|
|
@@ -2571,11 +2638,7 @@ function exportOtlpJson(tree, options) {
|
|
|
2571
2638
|
const ev = n.event;
|
|
2572
2639
|
const spanId = hexFrom2(`${tree.runId}:${ev.eventId}`, 8);
|
|
2573
2640
|
const parentSpanId = ev.parentId ? hexFrom2(`${tree.runId}:${ev.parentId}`, 8) : void 0;
|
|
2574
|
-
const startNs =
|
|
2575
|
-
let endNs;
|
|
2576
|
-
if (ev.durationMs !== void 0 && Number.isFinite(ev.durationMs)) {
|
|
2577
|
-
endNs = String(unixNano2(ev.timestamp) + unixNano2(ev.durationMs));
|
|
2578
|
-
}
|
|
2641
|
+
const { startNs, endNs } = resolveSpanTimes(ev);
|
|
2579
2642
|
const attrs = [
|
|
2580
2643
|
stringAttr("agent_inspect.kind", ev.kind),
|
|
2581
2644
|
stringAttr("agent_inspect.confidence", ev.confidence),
|
|
@@ -2605,29 +2668,28 @@ function exportOtlpJson(tree, options) {
|
|
|
2605
2668
|
if (includeAttributes && meta && typeof meta === "object") {
|
|
2606
2669
|
for (const [k, v] of Object.entries(meta)) {
|
|
2607
2670
|
if (k === "tokens" || k === "model") continue;
|
|
2608
|
-
if (typeof v === "string"
|
|
2609
|
-
attrs.push(
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
);
|
|
2671
|
+
if (typeof v === "string") {
|
|
2672
|
+
attrs.push(stringAttr(`agent_inspect.preview.${k}`, v.slice(0, maxLen)));
|
|
2673
|
+
} else if (typeof v === "number" && Number.isFinite(v)) {
|
|
2674
|
+
attrs.push(numberAttr(`agent_inspect.preview.${k}`, v));
|
|
2675
|
+
} else if (typeof v === "boolean") {
|
|
2676
|
+
attrs.push(boolAttr(`agent_inspect.preview.${k}`, v));
|
|
2615
2677
|
}
|
|
2616
2678
|
}
|
|
2617
2679
|
}
|
|
2618
|
-
let statusCode =
|
|
2680
|
+
let statusCode = OTLP_STATUS_CODE_UNSET;
|
|
2619
2681
|
let statusMessage;
|
|
2620
2682
|
if (ev.status === "error") {
|
|
2621
|
-
statusCode =
|
|
2683
|
+
statusCode = OTLP_STATUS_CODE_ERROR;
|
|
2622
2684
|
statusMessage = meta && typeof meta.error === "object" && meta.error !== null ? String(meta.error.message ?? "error").slice(0, maxLen) : "error";
|
|
2623
2685
|
} else if (ev.status === "ok") {
|
|
2624
|
-
statusCode =
|
|
2686
|
+
statusCode = OTLP_STATUS_CODE_OK;
|
|
2625
2687
|
}
|
|
2626
2688
|
const spanJson = {
|
|
2627
2689
|
traceId,
|
|
2628
2690
|
spanId,
|
|
2629
2691
|
name: ev.name,
|
|
2630
|
-
kind:
|
|
2692
|
+
kind: OTLP_SPAN_KIND_INTERNAL,
|
|
2631
2693
|
startTimeUnixNano: startNs,
|
|
2632
2694
|
attributes: attrs,
|
|
2633
2695
|
status: {
|
|
@@ -2669,6 +2731,136 @@ function exportOtlpJson(tree, options) {
|
|
|
2669
2731
|
|
|
2670
2732
|
// packages/core/src/exporters/validation.ts
|
|
2671
2733
|
var EXPERIMENTAL = "Experimental compatibility export \u2014 verify against your target tooling before relying on it.";
|
|
2734
|
+
function pushPath(errors, path30, message) {
|
|
2735
|
+
errors.push(`${path30}: ${message}`);
|
|
2736
|
+
}
|
|
2737
|
+
function isRecord5(value) {
|
|
2738
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
2739
|
+
}
|
|
2740
|
+
function validateOtlpJson(content) {
|
|
2741
|
+
const errors = [];
|
|
2742
|
+
const warnings = [
|
|
2743
|
+
EXPERIMENTAL,
|
|
2744
|
+
"OTLP JSON mapping uses OTel GenAI-aligned attributes where applicable; collectors may require transformation.",
|
|
2745
|
+
"protocol-valid \u2260 profile-complete \u2260 fixture-complete \u2014 nested path diagnostics report protocol shape only."
|
|
2746
|
+
];
|
|
2747
|
+
let parsed;
|
|
2748
|
+
try {
|
|
2749
|
+
parsed = JSON.parse(content);
|
|
2750
|
+
} catch {
|
|
2751
|
+
pushPath(errors, "$", "OTLP JSON export is not valid JSON");
|
|
2752
|
+
return { ok: false, format: "otlp-json", errors, warnings };
|
|
2753
|
+
}
|
|
2754
|
+
if (!isRecord5(parsed)) {
|
|
2755
|
+
pushPath(errors, "$", "OTLP JSON export must be an object");
|
|
2756
|
+
return { ok: false, format: "otlp-json", errors, warnings };
|
|
2757
|
+
}
|
|
2758
|
+
if (!Array.isArray(parsed.resourceSpans)) {
|
|
2759
|
+
pushPath(errors, "$.resourceSpans", "must be an array");
|
|
2760
|
+
return { ok: false, format: "otlp-json", errors, warnings };
|
|
2761
|
+
}
|
|
2762
|
+
parsed.resourceSpans.forEach((resourceSpan, rsi) => {
|
|
2763
|
+
const rsPath = `$.resourceSpans[${rsi}]`;
|
|
2764
|
+
if (!isRecord5(resourceSpan)) {
|
|
2765
|
+
pushPath(errors, rsPath, "must be an object");
|
|
2766
|
+
return;
|
|
2767
|
+
}
|
|
2768
|
+
if (!Array.isArray(resourceSpan.scopeSpans)) {
|
|
2769
|
+
pushPath(errors, `${rsPath}.scopeSpans`, "must be an array");
|
|
2770
|
+
return;
|
|
2771
|
+
}
|
|
2772
|
+
resourceSpan.scopeSpans.forEach((scopeSpan, ssi) => {
|
|
2773
|
+
const ssPath = `${rsPath}.scopeSpans[${ssi}]`;
|
|
2774
|
+
if (!isRecord5(scopeSpan)) {
|
|
2775
|
+
pushPath(errors, ssPath, "must be an object");
|
|
2776
|
+
return;
|
|
2777
|
+
}
|
|
2778
|
+
if (!Array.isArray(scopeSpan.spans)) {
|
|
2779
|
+
pushPath(errors, `${ssPath}.spans`, "must be an array");
|
|
2780
|
+
return;
|
|
2781
|
+
}
|
|
2782
|
+
scopeSpan.spans.forEach((span, spi) => {
|
|
2783
|
+
const spanPath = `${ssPath}.spans[${spi}]`;
|
|
2784
|
+
if (!isRecord5(span)) {
|
|
2785
|
+
pushPath(errors, spanPath, "must be an object");
|
|
2786
|
+
return;
|
|
2787
|
+
}
|
|
2788
|
+
if (typeof span.traceId !== "string" || span.traceId.length === 0) {
|
|
2789
|
+
pushPath(errors, `${spanPath}.traceId`, "must be a non-empty string");
|
|
2790
|
+
}
|
|
2791
|
+
if (typeof span.spanId !== "string" || span.spanId.length === 0) {
|
|
2792
|
+
pushPath(errors, `${spanPath}.spanId`, "must be a non-empty string");
|
|
2793
|
+
}
|
|
2794
|
+
if (typeof span.name !== "string") {
|
|
2795
|
+
pushPath(errors, `${spanPath}.name`, "must be a string");
|
|
2796
|
+
}
|
|
2797
|
+
if (typeof span.startTimeUnixNano !== "string" || !/^\d+$/.test(span.startTimeUnixNano)) {
|
|
2798
|
+
pushPath(
|
|
2799
|
+
errors,
|
|
2800
|
+
`${spanPath}.startTimeUnixNano`,
|
|
2801
|
+
"must be a decimal-string 64-bit integer"
|
|
2802
|
+
);
|
|
2803
|
+
}
|
|
2804
|
+
if (span.endTimeUnixNano !== void 0 && (typeof span.endTimeUnixNano !== "string" || !/^\d+$/.test(span.endTimeUnixNano))) {
|
|
2805
|
+
pushPath(
|
|
2806
|
+
errors,
|
|
2807
|
+
`${spanPath}.endTimeUnixNano`,
|
|
2808
|
+
"must be a decimal-string 64-bit integer when present"
|
|
2809
|
+
);
|
|
2810
|
+
}
|
|
2811
|
+
if (typeof span.kind === "number") {
|
|
2812
|
+
if (!Number.isInteger(span.kind)) {
|
|
2813
|
+
pushPath(errors, `${spanPath}.kind`, "must be an integer SpanKind enum");
|
|
2814
|
+
}
|
|
2815
|
+
} else if (typeof span.kind === "string") {
|
|
2816
|
+
warnings.push(
|
|
2817
|
+
`${spanPath}.kind: string SpanKind enum is legacy; prefer numeric (INTERNAL=1)`
|
|
2818
|
+
);
|
|
2819
|
+
} else if (span.kind !== void 0) {
|
|
2820
|
+
pushPath(
|
|
2821
|
+
errors,
|
|
2822
|
+
`${spanPath}.kind`,
|
|
2823
|
+
"must be numeric SpanKind or historical string enum"
|
|
2824
|
+
);
|
|
2825
|
+
}
|
|
2826
|
+
if (!isRecord5(span.status)) {
|
|
2827
|
+
pushPath(errors, `${spanPath}.status`, "must be an object");
|
|
2828
|
+
} else {
|
|
2829
|
+
const code = span.status.code;
|
|
2830
|
+
if (typeof code === "number") {
|
|
2831
|
+
if (![0, 1, 2].includes(code)) {
|
|
2832
|
+
pushPath(
|
|
2833
|
+
errors,
|
|
2834
|
+
`${spanPath}.status.code`,
|
|
2835
|
+
"must be numeric StatusCode 0 (UNSET), 1 (OK), or 2 (ERROR)"
|
|
2836
|
+
);
|
|
2837
|
+
}
|
|
2838
|
+
} else if (typeof code === "string") {
|
|
2839
|
+
const upper = code.toUpperCase();
|
|
2840
|
+
if (upper !== "STATUS_CODE_UNSET" && upper !== "STATUS_CODE_OK" && upper !== "STATUS_CODE_ERROR" && upper !== "UNSET" && upper !== "OK" && upper !== "ERROR" && !/^[012]$/.test(code.trim())) {
|
|
2841
|
+
pushPath(
|
|
2842
|
+
errors,
|
|
2843
|
+
`${spanPath}.status.code`,
|
|
2844
|
+
"unrecognized StatusCode string"
|
|
2845
|
+
);
|
|
2846
|
+
} else {
|
|
2847
|
+
warnings.push(
|
|
2848
|
+
`${spanPath}.status.code: string StatusCode is legacy; prefer numeric 0/1/2`
|
|
2849
|
+
);
|
|
2850
|
+
}
|
|
2851
|
+
} else {
|
|
2852
|
+
pushPath(
|
|
2853
|
+
errors,
|
|
2854
|
+
`${spanPath}.status.code`,
|
|
2855
|
+
"must be numeric StatusCode 0/1/2 or historical string enum"
|
|
2856
|
+
);
|
|
2857
|
+
}
|
|
2858
|
+
}
|
|
2859
|
+
});
|
|
2860
|
+
});
|
|
2861
|
+
});
|
|
2862
|
+
return { ok: errors.length === 0, format: "otlp-json", errors, warnings };
|
|
2863
|
+
}
|
|
2672
2864
|
function validateExportContent(format, content) {
|
|
2673
2865
|
const errors = [];
|
|
2674
2866
|
const warnings = [EXPERIMENTAL];
|
|
@@ -2714,25 +2906,7 @@ function validateExportContent(format, content) {
|
|
|
2714
2906
|
return { ok: errors.length === 0, format, errors, warnings };
|
|
2715
2907
|
}
|
|
2716
2908
|
if (format === "otlp-json") {
|
|
2717
|
-
|
|
2718
|
-
try {
|
|
2719
|
-
parsed = JSON.parse(content);
|
|
2720
|
-
} catch {
|
|
2721
|
-
errors.push("OTLP JSON export is not valid JSON");
|
|
2722
|
-
return { ok: false, format, errors, warnings };
|
|
2723
|
-
}
|
|
2724
|
-
if (!parsed || typeof parsed !== "object") {
|
|
2725
|
-
errors.push("OTLP JSON export must be an object");
|
|
2726
|
-
return { ok: false, format, errors, warnings };
|
|
2727
|
-
}
|
|
2728
|
-
const o = parsed;
|
|
2729
|
-
if (!Array.isArray(o.resourceSpans)) {
|
|
2730
|
-
errors.push("OTLP JSON export must include resourceSpans array");
|
|
2731
|
-
}
|
|
2732
|
-
warnings.push(
|
|
2733
|
-
"OTLP JSON mapping uses OTel GenAI-aligned attributes where applicable; collectors may require transformation."
|
|
2734
|
-
);
|
|
2735
|
-
return { ok: errors.length === 0, format, errors, warnings };
|
|
2909
|
+
return validateOtlpJson(content);
|
|
2736
2910
|
}
|
|
2737
2911
|
errors.push(`Unsupported export format`);
|
|
2738
2912
|
return { ok: false, format, errors, warnings };
|
|
@@ -3125,7 +3299,7 @@ async function exportCommand(runId, options = {}) {
|
|
|
3125
3299
|
const traceDir = resolveTraceDir({ dir: options.dir });
|
|
3126
3300
|
let events;
|
|
3127
3301
|
try {
|
|
3128
|
-
const result2 = await
|
|
3302
|
+
const result2 = await readRunPersistedEvents(id, traceDir);
|
|
3129
3303
|
events = result2?.events ?? [];
|
|
3130
3304
|
} catch (e) {
|
|
3131
3305
|
const msg = e instanceof Error ? e.message : String(e);
|
|
@@ -3141,7 +3315,11 @@ Trace directory: ${traceDir}`);
|
|
|
3141
3315
|
}
|
|
3142
3316
|
let tree;
|
|
3143
3317
|
try {
|
|
3144
|
-
|
|
3318
|
+
const trees = persistedInspectEventsToRunTrees(events);
|
|
3319
|
+
tree = trees.find((candidate) => candidate.runId === id) ?? trees[0];
|
|
3320
|
+
if (tree === void 0) {
|
|
3321
|
+
throw new Error("No run tree could be built from persisted events");
|
|
3322
|
+
}
|
|
3145
3323
|
} catch (e) {
|
|
3146
3324
|
const msg = e instanceof Error ? e.message : String(e);
|
|
3147
3325
|
console.error(`[AgentInspect] export failed: ${msg}`);
|
|
@@ -3169,7 +3347,9 @@ Trace directory: ${traceDir}`);
|
|
|
3169
3347
|
await mkdir(path19.dirname(outPath), { recursive: true });
|
|
3170
3348
|
await writeFile(outPath, result.content, "utf-8");
|
|
3171
3349
|
const vlabel = validation !== void 0 ? validation.ok ? "ok" : "failed" : "skipped";
|
|
3172
|
-
console.
|
|
3350
|
+
console.error(
|
|
3351
|
+
`Wrote ${result.fileExtension} export to ${outPath} (validation: ${vlabel})`
|
|
3352
|
+
);
|
|
3173
3353
|
if (validation !== void 0 && !validation.ok) {
|
|
3174
3354
|
console.error("Validation errors:", validation.errors.join("; "));
|
|
3175
3355
|
}
|
|
@@ -3182,7 +3362,9 @@ Trace directory: ${traceDir}`);
|
|
|
3182
3362
|
warnings: [...result.warnings, ...validation?.warnings ?? []],
|
|
3183
3363
|
validation
|
|
3184
3364
|
};
|
|
3185
|
-
if (outPath
|
|
3365
|
+
if (outPath !== void 0) {
|
|
3366
|
+
payload.out = outPath;
|
|
3367
|
+
} else {
|
|
3186
3368
|
payload.content = result.content;
|
|
3187
3369
|
}
|
|
3188
3370
|
console.log(JSON.stringify(payload, null, 2));
|
|
@@ -3539,7 +3721,7 @@ async function newestTraceMtimeMs(traceDir) {
|
|
|
3539
3721
|
}
|
|
3540
3722
|
async function loadSessionRuns(traceDir) {
|
|
3541
3723
|
try {
|
|
3542
|
-
const mod = await import('./src-
|
|
3724
|
+
const mod = await import('./src-KFOBXFPN.mjs');
|
|
3543
3725
|
const dbPath = mod.resolveIndexDbPath(traceDir);
|
|
3544
3726
|
const status = mod.indexStatus(dbPath);
|
|
3545
3727
|
if (!status.healthy) {
|
|
@@ -4062,7 +4244,7 @@ function isCredentialSensitiveKey2(key, sensitiveKeys) {
|
|
|
4062
4244
|
}
|
|
4063
4245
|
|
|
4064
4246
|
// packages/redact/src/key-value-secret.ts
|
|
4065
|
-
var KEY_VALUE_SECRET_PATTERN_SOURCE = String.raw`\b(?:api[_-]?key|internal[_-]?token|access[_-]?token|auth[_-]?token|password|secret|token)=(?!\[(?:REDACTED(?::[^\]]*)?|HASH:[0-9a-f]{8})\](?![^\s"'
|
|
4247
|
+
var KEY_VALUE_SECRET_PATTERN_SOURCE = String.raw`\b(?:api[_-]?key|internal[_-]?token|access[_-]?token|auth[_-]?token|password|secret|token)=(?!\[(?:REDACTED(?::[^\]]*)?|HASH:[0-9a-f]{8})\](?![^\s"'\\&#?]))([^\s"'\\]{8,})`;
|
|
4066
4248
|
var KEY_VALUE_SECRET_PATTERN = new RegExp(
|
|
4067
4249
|
KEY_VALUE_SECRET_PATTERN_SOURCE,
|
|
4068
4250
|
"i"
|
|
@@ -4087,6 +4269,8 @@ var CONNECTION_PROTOCOLS2 = /* @__PURE__ */ new Set([
|
|
|
4087
4269
|
"amqps:"
|
|
4088
4270
|
]);
|
|
4089
4271
|
var CONNECTION_URI2 = /^(?:postgres|postgresql|mysql|mariadb|mongodb(?:\+srv)?|rediss?|amqps?):\/\/[^\s]+$/i;
|
|
4272
|
+
var CONNECTION_USERINFO2 = /^(postgres|postgresql|mysql|mariadb|mongodb(?:\+srv)?|rediss?|amqps?):\/\/([^@/?#]+)@(.+)$/i;
|
|
4273
|
+
var CONNECTION_HAS_USERINFO2 = /^(?:postgres|postgresql|mysql|mariadb|mongodb(?:\+srv)?|rediss?|amqps?):\/\/[^@/?#]+@/i;
|
|
4090
4274
|
var UUID_SEGMENT2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
4091
4275
|
var HEX_SEGMENT2 = /^[0-9a-f]{12,}$/i;
|
|
4092
4276
|
var NUMERIC_SEGMENT2 = /^\d{5,}$/;
|
|
@@ -4110,6 +4294,28 @@ function parseRedactableUrl2(value) {
|
|
|
4110
4294
|
return void 0;
|
|
4111
4295
|
}
|
|
4112
4296
|
}
|
|
4297
|
+
function redactConnectionUserinfoFallback2(value, replacement) {
|
|
4298
|
+
const trimmed = value.trim();
|
|
4299
|
+
const match = CONNECTION_USERINFO2.exec(trimmed);
|
|
4300
|
+
if (match) {
|
|
4301
|
+
const [, scheme, , rest] = match;
|
|
4302
|
+
if (scheme && rest && rest.length > 0) {
|
|
4303
|
+
return {
|
|
4304
|
+
value: `${scheme}://${rest}`,
|
|
4305
|
+
credentialRedacted: true,
|
|
4306
|
+
identifiersMasked: false
|
|
4307
|
+
};
|
|
4308
|
+
}
|
|
4309
|
+
}
|
|
4310
|
+
if (looksLikeConnectionUri2(trimmed) && CONNECTION_HAS_USERINFO2.test(trimmed)) {
|
|
4311
|
+
return {
|
|
4312
|
+
value: replacement,
|
|
4313
|
+
credentialRedacted: true,
|
|
4314
|
+
identifiersMasked: false
|
|
4315
|
+
};
|
|
4316
|
+
}
|
|
4317
|
+
return void 0;
|
|
4318
|
+
}
|
|
4113
4319
|
function isHttpProtocol2(protocol) {
|
|
4114
4320
|
return protocol === "http:" || protocol === "https:";
|
|
4115
4321
|
}
|
|
@@ -4151,9 +4357,11 @@ function redactUrlString2(value, options) {
|
|
|
4151
4357
|
identifiersMasked: false
|
|
4152
4358
|
};
|
|
4153
4359
|
if (!looksLikeUrlForRedaction2(value)) return unchanged;
|
|
4154
|
-
const url = parseRedactableUrl2(value);
|
|
4155
|
-
if (!url) return unchanged;
|
|
4156
4360
|
const replacement = options.replacement ?? "[REDACTED]";
|
|
4361
|
+
const url = parseRedactableUrl2(value);
|
|
4362
|
+
if (!url) {
|
|
4363
|
+
return redactConnectionUserinfoFallback2(value, replacement) ?? unchanged;
|
|
4364
|
+
}
|
|
4157
4365
|
const idPlaceholder = options.idPlaceholder ?? "[id]";
|
|
4158
4366
|
const http = isHttpProtocol2(url.protocol);
|
|
4159
4367
|
let credentialRedacted = url.username.length > 0 || url.password.length > 0;
|
|
@@ -4246,7 +4454,7 @@ var STRICT_PROFILE_EXTRA_KEYS = [
|
|
|
4246
4454
|
"retrieval",
|
|
4247
4455
|
"query"
|
|
4248
4456
|
];
|
|
4249
|
-
function
|
|
4457
|
+
function isRecord6(value) {
|
|
4250
4458
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4251
4459
|
}
|
|
4252
4460
|
function toKey(key) {
|
|
@@ -4675,7 +4883,7 @@ var Redactor2 = class {
|
|
|
4675
4883
|
});
|
|
4676
4884
|
return out;
|
|
4677
4885
|
}
|
|
4678
|
-
if (
|
|
4886
|
+
if (isRecord6(value)) {
|
|
4679
4887
|
if (state.seen.has(value)) return state.seen.get(value);
|
|
4680
4888
|
const out = {};
|
|
4681
4889
|
state.seen.set(value, out);
|
|
@@ -4710,7 +4918,7 @@ var REDACTION_POLICY_LIMITS = {
|
|
|
4710
4918
|
};
|
|
4711
4919
|
var ALLOWED_TOP_LEVEL = /* @__PURE__ */ new Set(["version", "extraKeys", "patterns"]);
|
|
4712
4920
|
var ALLOWED_PATTERN_FIELDS = /* @__PURE__ */ new Set(["id", "type", "value", "severity"]);
|
|
4713
|
-
function
|
|
4921
|
+
function isRecord7(value) {
|
|
4714
4922
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
4715
4923
|
}
|
|
4716
4924
|
function rejectRemotePolicyPath(policyPath) {
|
|
@@ -4750,7 +4958,7 @@ function rejectUnknownFields(record, allowed, label) {
|
|
|
4750
4958
|
}
|
|
4751
4959
|
function compilePatternDetector(input3, index) {
|
|
4752
4960
|
const label = `patterns[${index}]`;
|
|
4753
|
-
if (!
|
|
4961
|
+
if (!isRecord7(input3)) throw new Error(`${label} must be an object.`);
|
|
4754
4962
|
const typeEarly = input3.type;
|
|
4755
4963
|
if (typeEarly === "typed") {
|
|
4756
4964
|
throw new Error(
|
|
@@ -4805,7 +5013,7 @@ function compilePatternDetector(input3, index) {
|
|
|
4805
5013
|
};
|
|
4806
5014
|
}
|
|
4807
5015
|
function compileRedactionPolicy(raw, policyPath) {
|
|
4808
|
-
if (!
|
|
5016
|
+
if (!isRecord7(raw)) {
|
|
4809
5017
|
throw new Error(`Redaction policy must be a JSON object (${policyPath}).`);
|
|
4810
5018
|
}
|
|
4811
5019
|
rejectUnknownFields(raw, ALLOWED_TOP_LEVEL, "Redaction policy");
|
|
@@ -5827,7 +6035,7 @@ async function openCommand(input3, options = {}, stdin = process.stdin) {
|
|
|
5827
6035
|
}
|
|
5828
6036
|
}
|
|
5829
6037
|
}
|
|
5830
|
-
function
|
|
6038
|
+
function isRecord8(value) {
|
|
5831
6039
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5832
6040
|
}
|
|
5833
6041
|
function parseTarget(value) {
|
|
@@ -5836,7 +6044,7 @@ function parseTarget(value) {
|
|
|
5836
6044
|
throw new Error('Unsupported migration target. Use "--to 1.0".');
|
|
5837
6045
|
}
|
|
5838
6046
|
function formatOf(value) {
|
|
5839
|
-
if (!
|
|
6047
|
+
if (!isRecord8(value)) return "unknown";
|
|
5840
6048
|
if (value.schemaVersion === "0.1") return "0.1";
|
|
5841
6049
|
if (value.schemaVersion === "0.2") return "0.2";
|
|
5842
6050
|
if (value.schemaVersion === "1.0") return "1.0";
|
|
@@ -12337,16 +12545,120 @@ function demoTemplate(framework) {
|
|
|
12337
12545
|
switch (framework) {
|
|
12338
12546
|
case "ai-sdk":
|
|
12339
12547
|
return `/**
|
|
12340
|
-
* AI SDK starter \u2014
|
|
12341
|
-
* Install: npm install agent-inspect @agent-inspect/ai-sdk ai
|
|
12548
|
+
* AI SDK starter \u2014 keyless MockLanguageModelV3 + @agent-inspect/ai-sdk telemetry.
|
|
12549
|
+
* Install: npm install agent-inspect @agent-inspect/ai-sdk ai@6.0.210 zod
|
|
12342
12550
|
*/
|
|
12343
|
-
import {
|
|
12551
|
+
import { generateText, stepCountIs, tool } from "ai";
|
|
12552
|
+
import { MockLanguageModelV3 } from "ai/test";
|
|
12553
|
+
import { agentInspect } from "@agent-inspect/ai-sdk";
|
|
12554
|
+
import { z } from "zod";
|
|
12555
|
+
import { readdirSync, readFileSync } from "node:fs";
|
|
12556
|
+
import path from "node:path";
|
|
12557
|
+
|
|
12558
|
+
const TRACE_DIR = ".agent-inspect";
|
|
12559
|
+
const ANSWER = "You have 2 orders";
|
|
12560
|
+
const CORRECT_RUN = "ai-sdk-demo-correct";
|
|
12561
|
+
const WRONG_RUN = "ai-sdk-demo-wrong";
|
|
12562
|
+
|
|
12563
|
+
const usage = {
|
|
12564
|
+
inputTokens: { total: 4, noCache: 4, cacheRead: 0, cacheWrite: 0 },
|
|
12565
|
+
outputTokens: { total: 3, text: 3, reasoning: 0 },
|
|
12566
|
+
};
|
|
12567
|
+
|
|
12568
|
+
const lookupOrders = tool({
|
|
12569
|
+
description: "Look up orders for a user",
|
|
12570
|
+
inputSchema: z.object({ userId: z.string() }),
|
|
12571
|
+
execute: async () => ({ orders: 2 }),
|
|
12572
|
+
});
|
|
12573
|
+
|
|
12574
|
+
const deleteOrders = tool({
|
|
12575
|
+
description: "Delete orders for a user (wrong path)",
|
|
12576
|
+
inputSchema: z.object({ userId: z.string() }),
|
|
12577
|
+
execute: async () => ({ orders: 2 }),
|
|
12578
|
+
});
|
|
12579
|
+
|
|
12580
|
+
async function runPath(runName, toolName) {
|
|
12581
|
+
const integration = agentInspect({
|
|
12582
|
+
traceDir: TRACE_DIR,
|
|
12583
|
+
runName,
|
|
12584
|
+
capture: "metadata-only",
|
|
12585
|
+
});
|
|
12586
|
+
let step = 0;
|
|
12587
|
+
try {
|
|
12588
|
+
const result = await generateText({
|
|
12589
|
+
model: new MockLanguageModelV3({
|
|
12590
|
+
provider: "fixture-provider",
|
|
12591
|
+
modelId: "fixture-tools",
|
|
12592
|
+
doGenerate: async () => {
|
|
12593
|
+
step += 1;
|
|
12594
|
+
if (step === 1) {
|
|
12595
|
+
return {
|
|
12596
|
+
content: [
|
|
12597
|
+
{
|
|
12598
|
+
type: "tool-call",
|
|
12599
|
+
toolCallId: \`call-\${toolName}\`,
|
|
12600
|
+
toolName,
|
|
12601
|
+
input: { userId: "u1" },
|
|
12602
|
+
},
|
|
12603
|
+
],
|
|
12604
|
+
finishReason: { unified: "tool-calls", raw: "tool-calls" },
|
|
12605
|
+
usage,
|
|
12606
|
+
warnings: [],
|
|
12607
|
+
};
|
|
12608
|
+
}
|
|
12609
|
+
return {
|
|
12610
|
+
content: [{ type: "text", text: ANSWER }],
|
|
12611
|
+
finishReason: { unified: "stop", raw: "stop" },
|
|
12612
|
+
usage,
|
|
12613
|
+
warnings: [],
|
|
12614
|
+
};
|
|
12615
|
+
},
|
|
12616
|
+
}),
|
|
12617
|
+
tools: { lookup_orders: lookupOrders, delete_orders: deleteOrders },
|
|
12618
|
+
prompt: "How many orders do I have?",
|
|
12619
|
+
stopWhen: stepCountIs(5),
|
|
12620
|
+
experimental_telemetry: {
|
|
12621
|
+
isEnabled: true,
|
|
12622
|
+
recordInputs: false,
|
|
12623
|
+
recordOutputs: false,
|
|
12624
|
+
integrations: [integration],
|
|
12625
|
+
},
|
|
12626
|
+
});
|
|
12627
|
+
if (result.text !== ANSWER) {
|
|
12628
|
+
throw new Error(\`unexpected answer for \${runName}: \${result.text}\`);
|
|
12629
|
+
}
|
|
12630
|
+
} finally {
|
|
12631
|
+
await integration.flush();
|
|
12632
|
+
await integration.close();
|
|
12633
|
+
}
|
|
12634
|
+
}
|
|
12635
|
+
|
|
12636
|
+
function selectRunIdByName(runName) {
|
|
12637
|
+
const files = readdirSync(TRACE_DIR).filter((f) => f.endsWith(".jsonl"));
|
|
12638
|
+
const matches = [];
|
|
12639
|
+
for (const file of files) {
|
|
12640
|
+
const text = readFileSync(path.join(TRACE_DIR, file), "utf8");
|
|
12641
|
+
if (text.includes(\`"name":"\${runName}"\`) || text.includes(\`"name": "\${runName}"\`)) {
|
|
12642
|
+
matches.push(file.replace(/\\.jsonl$/, ""));
|
|
12643
|
+
}
|
|
12644
|
+
}
|
|
12645
|
+
if (matches.length !== 1) {
|
|
12646
|
+
throw new Error(
|
|
12647
|
+
\`expected exactly one run named \${runName}, found \${matches.length}\`,
|
|
12648
|
+
);
|
|
12649
|
+
}
|
|
12650
|
+
return matches[0];
|
|
12651
|
+
}
|
|
12344
12652
|
|
|
12345
12653
|
async function main() {
|
|
12346
|
-
await
|
|
12347
|
-
|
|
12348
|
-
|
|
12654
|
+
await runPath(CORRECT_RUN, "lookup_orders");
|
|
12655
|
+
await runPath(WRONG_RUN, "delete_orders");
|
|
12656
|
+
const correctId = selectRunIdByName(CORRECT_RUN);
|
|
12657
|
+
const wrongId = selectRunIdByName(WRONG_RUN);
|
|
12349
12658
|
console.log("Trace written to .agent-inspect/");
|
|
12659
|
+
console.log(\`Correct path runId: \${correctId}\`);
|
|
12660
|
+
console.log(\`Wrong path runId: \${wrongId}\`);
|
|
12661
|
+
console.log(\`Next: npx agent-inspect check \${correctId} --required-tool lookup_orders\`);
|
|
12350
12662
|
}
|
|
12351
12663
|
|
|
12352
12664
|
main().catch((error) => {
|
|
@@ -13339,7 +13651,7 @@ function isModuleNotFound4(e) {
|
|
|
13339
13651
|
}
|
|
13340
13652
|
async function loadIndexSqlite() {
|
|
13341
13653
|
try {
|
|
13342
|
-
return await import('./src-
|
|
13654
|
+
return await import('./src-KFOBXFPN.mjs');
|
|
13343
13655
|
} catch (e) {
|
|
13344
13656
|
if (isModuleNotFound4(e)) {
|
|
13345
13657
|
console.error(
|