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
|
@@ -261,7 +261,7 @@ function stringContainsHighConfidenceCredential(value) {
|
|
|
261
261
|
var KEY_VALUE_SECRET_PATTERN, HIGH_CONFIDENCE_CREDENTIAL_PATTERNS;
|
|
262
262
|
var init_credential_value_patterns = __esm({
|
|
263
263
|
"packages/core/src/safety/credential-value-patterns.ts"() {
|
|
264
|
-
KEY_VALUE_SECRET_PATTERN = /\b(?:api[_-]?key|internal[_-]?token|access[_-]?token|auth[_-]?token|password|secret|token)=(?!\[(?:REDACTED(?::[^\]]*)?|HASH:[0-9a-f]{8})\](?![^\s"'
|
|
264
|
+
KEY_VALUE_SECRET_PATTERN = /\b(?:api[_-]?key|internal[_-]?token|access[_-]?token|auth[_-]?token|password|secret|token)=(?!\[(?:REDACTED(?::[^\]]*)?|HASH:[0-9a-f]{8})\](?![^\s"'\\&#?]))([^\s"'\\]{8,})/i;
|
|
265
265
|
HIGH_CONFIDENCE_CREDENTIAL_PATTERNS = [
|
|
266
266
|
/^(?:basic|bearer|digest|apikey)\s+[a-z0-9._~+/=-]+$/i,
|
|
267
267
|
/\bbearer\s+[a-z0-9._~+/=-]{12,}\b/i,
|
|
@@ -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;
|
|
2727
|
+
}
|
|
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}"`);
|
|
2699
2736
|
}
|
|
2700
|
-
|
|
2701
|
-
depthCache.set(stepId, d);
|
|
2702
|
-
return d;
|
|
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
|
|
|
@@ -5848,9 +5886,6 @@ function limitFindings(findings, maxFindings) {
|
|
|
5848
5886
|
if (maxFindings === void 0 || findings.length <= maxFindings) return findings;
|
|
5849
5887
|
return findings.slice(0, Math.max(0, maxFindings));
|
|
5850
5888
|
}
|
|
5851
|
-
function hasRedactionMarker(value, markers) {
|
|
5852
|
-
return markers.some((marker) => value.includes(marker)) || /^\[HASH:[A-Za-z0-9_-]+\]$/.test(value);
|
|
5853
|
-
}
|
|
5854
5889
|
function isFullyRedactedValue(value, markers = ["[REDACTED]", "[REDACTED:"]) {
|
|
5855
5890
|
if (typeof value !== "string") return false;
|
|
5856
5891
|
const trimmed = value.trim();
|
|
@@ -6837,7 +6872,7 @@ function createSafetyRedactionRule(options = {}) {
|
|
|
6837
6872
|
for (const event of context.events) {
|
|
6838
6873
|
for (const entry of eventValueEntries(event, { includeSummaries: true, includeError: true })) {
|
|
6839
6874
|
if (!isSensitiveKey(entry.key ?? lastPathSegment(entry.path), sensitiveKeys)) continue;
|
|
6840
|
-
if (
|
|
6875
|
+
if (isFullyRedactedValue(entry.value, markers)) continue;
|
|
6841
6876
|
findings.push(
|
|
6842
6877
|
failFinding(
|
|
6843
6878
|
"safety.redaction",
|
|
@@ -7362,7 +7397,7 @@ var init_checks2 = __esm({
|
|
|
7362
7397
|
// Keep in sync with packages/redact/src/key-value-secret.ts (KEY_VALUE_SECRET_PATTERN_SOURCE).
|
|
7363
7398
|
{
|
|
7364
7399
|
id: "key-value-secret",
|
|
7365
|
-
pattern: /\b(?:api[_-]?key|internal[_-]?token|access[_-]?token|auth[_-]?token|password|secret|token)=(?!\[(?:REDACTED(?::[^\]]*)?|HASH:[0-9a-f]{8})\](?![^\s"'
|
|
7400
|
+
pattern: /\b(?:api[_-]?key|internal[_-]?token|access[_-]?token|auth[_-]?token|password|secret|token)=(?!\[(?:REDACTED(?::[^\]]*)?|HASH:[0-9a-f]{8})\](?![^\s"'\\&#?]))([^\s"'\\]{8,})/i
|
|
7366
7401
|
}
|
|
7367
7402
|
];
|
|
7368
7403
|
}
|
|
@@ -12543,6 +12578,23 @@ function persistedInspectEventToInspectEvent(event) {
|
|
|
12543
12578
|
if (event.durationMs !== void 0 && Number.isFinite(event.durationMs) && event.durationMs >= 0) {
|
|
12544
12579
|
out.durationMs = event.durationMs;
|
|
12545
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);
|
|
12546
12598
|
return out;
|
|
12547
12599
|
}
|
|
12548
12600
|
function persistedInspectEventsToInspectEvents(events, options) {
|
|
@@ -13464,20 +13516,38 @@ function extractOtlpDocument(root) {
|
|
|
13464
13516
|
function mapOtlpStatus(status) {
|
|
13465
13517
|
if (!isRecord11(status)) return void 0;
|
|
13466
13518
|
const rawCode = status.code;
|
|
13467
|
-
if (typeof rawCode
|
|
13468
|
-
|
|
13469
|
-
|
|
13470
|
-
|
|
13471
|
-
|
|
13472
|
-
|
|
13473
|
-
|
|
13474
|
-
|
|
13475
|
-
|
|
13476
|
-
|
|
13477
|
-
|
|
13478
|
-
|
|
13479
|
-
|
|
13519
|
+
if (typeof rawCode === "number" && Number.isFinite(rawCode)) {
|
|
13520
|
+
switch (rawCode) {
|
|
13521
|
+
case 0:
|
|
13522
|
+
return "unknown";
|
|
13523
|
+
case 1:
|
|
13524
|
+
return "ok";
|
|
13525
|
+
case 2:
|
|
13526
|
+
return "error";
|
|
13527
|
+
default:
|
|
13528
|
+
return "unknown";
|
|
13529
|
+
}
|
|
13530
|
+
}
|
|
13531
|
+
if (typeof rawCode === "string") {
|
|
13532
|
+
const trimmed = rawCode.trim();
|
|
13533
|
+
if (/^\d+$/.test(trimmed)) {
|
|
13534
|
+
return mapOtlpStatus({ code: Number(trimmed) });
|
|
13535
|
+
}
|
|
13536
|
+
switch (trimmed.toUpperCase()) {
|
|
13537
|
+
case "STATUS_CODE_OK":
|
|
13538
|
+
case "OK":
|
|
13539
|
+
return "ok";
|
|
13540
|
+
case "STATUS_CODE_ERROR":
|
|
13541
|
+
case "ERROR":
|
|
13542
|
+
return "error";
|
|
13543
|
+
case "STATUS_CODE_UNSET":
|
|
13544
|
+
case "UNSET":
|
|
13545
|
+
return "unknown";
|
|
13546
|
+
default:
|
|
13547
|
+
return "unknown";
|
|
13548
|
+
}
|
|
13480
13549
|
}
|
|
13550
|
+
return void 0;
|
|
13481
13551
|
}
|
|
13482
13552
|
function readOtlpKind(attributes, pathPrefix) {
|
|
13483
13553
|
const warnings = [];
|
|
@@ -16165,7 +16235,7 @@ var init_src = __esm({
|
|
|
16165
16235
|
});
|
|
16166
16236
|
|
|
16167
16237
|
// package.json
|
|
16168
|
-
var version = "6.31.
|
|
16238
|
+
var version = "6.31.7";
|
|
16169
16239
|
|
|
16170
16240
|
// packages/cli/src/list.ts
|
|
16171
16241
|
init_advanced();
|
|
@@ -16514,7 +16584,7 @@ function mapReaderFormat(format) {
|
|
|
16514
16584
|
function isMissingFileError(error) {
|
|
16515
16585
|
return error !== null && typeof error === "object" && "code" in error && error.code === "ENOENT";
|
|
16516
16586
|
}
|
|
16517
|
-
async function
|
|
16587
|
+
async function readRunPersistedEvents(runId, traceDir) {
|
|
16518
16588
|
const filePath = getTraceFilePath(runId, traceDir);
|
|
16519
16589
|
try {
|
|
16520
16590
|
await promises.access(filePath);
|
|
@@ -16522,16 +16592,24 @@ async function readRunTraceEvents(runId, traceDir) {
|
|
|
16522
16592
|
{ type: "file", path: filePath },
|
|
16523
16593
|
{ format: "agent-inspect-jsonl" }
|
|
16524
16594
|
);
|
|
16525
|
-
const events = persistedInspectEventsToTraceEvents(result.events);
|
|
16526
16595
|
return {
|
|
16527
|
-
events,
|
|
16528
|
-
format: events.length > 0 ? mapReaderFormat(result.format) : "empty"
|
|
16596
|
+
events: result.events,
|
|
16597
|
+
format: result.events.length > 0 ? mapReaderFormat(result.format) : "empty"
|
|
16529
16598
|
};
|
|
16530
16599
|
} catch (error) {
|
|
16531
16600
|
if (isMissingFileError(error)) return void 0;
|
|
16532
16601
|
throw error;
|
|
16533
16602
|
}
|
|
16534
16603
|
}
|
|
16604
|
+
async function readRunTraceEvents(runId, traceDir) {
|
|
16605
|
+
const persisted = await readRunPersistedEvents(runId, traceDir);
|
|
16606
|
+
if (persisted === void 0) return void 0;
|
|
16607
|
+
const events = persistedInspectEventsToTraceEvents(persisted.events);
|
|
16608
|
+
return {
|
|
16609
|
+
events,
|
|
16610
|
+
format: events.length > 0 ? persisted.format : "empty"
|
|
16611
|
+
};
|
|
16612
|
+
}
|
|
16535
16613
|
|
|
16536
16614
|
// packages/cli/src/view.ts
|
|
16537
16615
|
function isModuleNotFound(e) {
|
|
@@ -17975,6 +18053,8 @@ var CONNECTION_PROTOCOLS = /* @__PURE__ */ new Set([
|
|
|
17975
18053
|
"amqps:"
|
|
17976
18054
|
]);
|
|
17977
18055
|
var CONNECTION_URI = /^(?:postgres|postgresql|mysql|mariadb|mongodb(?:\+srv)?|rediss?|amqps?):\/\/[^\s]+$/i;
|
|
18056
|
+
var CONNECTION_USERINFO = /^(postgres|postgresql|mysql|mariadb|mongodb(?:\+srv)?|rediss?|amqps?):\/\/([^@/?#]+)@(.+)$/i;
|
|
18057
|
+
var CONNECTION_HAS_USERINFO = /^(?:postgres|postgresql|mysql|mariadb|mongodb(?:\+srv)?|rediss?|amqps?):\/\/[^@/?#]+@/i;
|
|
17978
18058
|
var UUID_SEGMENT = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
17979
18059
|
var HEX_SEGMENT = /^[0-9a-f]{12,}$/i;
|
|
17980
18060
|
var NUMERIC_SEGMENT = /^\d{5,}$/;
|
|
@@ -17998,6 +18078,28 @@ function parseRedactableUrl(value) {
|
|
|
17998
18078
|
return void 0;
|
|
17999
18079
|
}
|
|
18000
18080
|
}
|
|
18081
|
+
function redactConnectionUserinfoFallback(value, replacement) {
|
|
18082
|
+
const trimmed = value.trim();
|
|
18083
|
+
const match = CONNECTION_USERINFO.exec(trimmed);
|
|
18084
|
+
if (match) {
|
|
18085
|
+
const [, scheme, , rest] = match;
|
|
18086
|
+
if (scheme && rest && rest.length > 0) {
|
|
18087
|
+
return {
|
|
18088
|
+
value: `${scheme}://${rest}`,
|
|
18089
|
+
credentialRedacted: true,
|
|
18090
|
+
identifiersMasked: false
|
|
18091
|
+
};
|
|
18092
|
+
}
|
|
18093
|
+
}
|
|
18094
|
+
if (looksLikeConnectionUri(trimmed) && CONNECTION_HAS_USERINFO.test(trimmed)) {
|
|
18095
|
+
return {
|
|
18096
|
+
value: replacement,
|
|
18097
|
+
credentialRedacted: true,
|
|
18098
|
+
identifiersMasked: false
|
|
18099
|
+
};
|
|
18100
|
+
}
|
|
18101
|
+
return void 0;
|
|
18102
|
+
}
|
|
18001
18103
|
function isHttpProtocol(protocol) {
|
|
18002
18104
|
return protocol === "http:" || protocol === "https:";
|
|
18003
18105
|
}
|
|
@@ -18039,9 +18141,11 @@ function redactUrlString(value, options) {
|
|
|
18039
18141
|
identifiersMasked: false
|
|
18040
18142
|
};
|
|
18041
18143
|
if (!looksLikeUrlForRedaction(value)) return unchanged;
|
|
18042
|
-
const url = parseRedactableUrl(value);
|
|
18043
|
-
if (!url) return unchanged;
|
|
18044
18144
|
const replacement = options.replacement ?? "[REDACTED]";
|
|
18145
|
+
const url = parseRedactableUrl(value);
|
|
18146
|
+
if (!url) {
|
|
18147
|
+
return redactConnectionUserinfoFallback(value, replacement) ?? unchanged;
|
|
18148
|
+
}
|
|
18045
18149
|
const idPlaceholder = options.idPlaceholder ?? "[id]";
|
|
18046
18150
|
const http = isHttpProtocol(url.protocol);
|
|
18047
18151
|
let credentialRedacted = url.username.length > 0 || url.password.length > 0;
|
|
@@ -18737,6 +18841,10 @@ function exportOpenInference(tree, options) {
|
|
|
18737
18841
|
|
|
18738
18842
|
// packages/core/src/exporters/otlp-json-exporter.ts
|
|
18739
18843
|
init_helpers();
|
|
18844
|
+
var OTLP_STATUS_CODE_UNSET = 0;
|
|
18845
|
+
var OTLP_STATUS_CODE_OK = 1;
|
|
18846
|
+
var OTLP_STATUS_CODE_ERROR = 2;
|
|
18847
|
+
var OTLP_SPAN_KIND_INTERNAL = 1;
|
|
18740
18848
|
function hexFrom2(seed, byteLen) {
|
|
18741
18849
|
return crypto__default.default.createHash("sha256").update(seed, "utf8").digest("hex").slice(0, byteLen * 2);
|
|
18742
18850
|
}
|
|
@@ -18749,7 +18857,19 @@ function stringAttr2(key, value) {
|
|
|
18749
18857
|
return { key, value: { stringValue: value } };
|
|
18750
18858
|
}
|
|
18751
18859
|
function intAttr(key, value) {
|
|
18752
|
-
return { key, value: { intValue: String(value) } };
|
|
18860
|
+
return { key, value: { intValue: String(Math.trunc(value)) } };
|
|
18861
|
+
}
|
|
18862
|
+
function doubleAttr(key, value) {
|
|
18863
|
+
return { key, value: { doubleValue: value } };
|
|
18864
|
+
}
|
|
18865
|
+
function boolAttr(key, value) {
|
|
18866
|
+
return { key, value: { boolValue: value } };
|
|
18867
|
+
}
|
|
18868
|
+
function numberAttr(key, value) {
|
|
18869
|
+
if (Number.isFinite(value) && !Number.isInteger(value)) {
|
|
18870
|
+
return doubleAttr(key, value);
|
|
18871
|
+
}
|
|
18872
|
+
return intAttr(key, value);
|
|
18753
18873
|
}
|
|
18754
18874
|
function genAiOperationName(kind) {
|
|
18755
18875
|
switch (kind) {
|
|
@@ -18763,10 +18883,27 @@ function genAiOperationName(kind) {
|
|
|
18763
18883
|
return void 0;
|
|
18764
18884
|
}
|
|
18765
18885
|
}
|
|
18886
|
+
function resolveSpanTimes(ev) {
|
|
18887
|
+
const startedAtMs = typeof ev.attributes?.startedAtMs === "number" && Number.isFinite(ev.attributes.startedAtMs) ? ev.attributes.startedAtMs : void 0;
|
|
18888
|
+
const endedAtMs = typeof ev.attributes?.endedAtMs === "number" && Number.isFinite(ev.attributes.endedAtMs) ? ev.attributes.endedAtMs : void 0;
|
|
18889
|
+
const startMs = startedAtMs ?? ev.timestamp;
|
|
18890
|
+
const startNs = String(unixNano2(startMs));
|
|
18891
|
+
if (endedAtMs !== void 0) {
|
|
18892
|
+
return { startNs, endNs: String(unixNano2(endedAtMs)) };
|
|
18893
|
+
}
|
|
18894
|
+
if (ev.durationMs !== void 0 && Number.isFinite(ev.durationMs)) {
|
|
18895
|
+
return {
|
|
18896
|
+
startNs,
|
|
18897
|
+
endNs: String(unixNano2(startMs) + unixNano2(ev.durationMs))
|
|
18898
|
+
};
|
|
18899
|
+
}
|
|
18900
|
+
return { startNs };
|
|
18901
|
+
}
|
|
18766
18902
|
function exportOtlpJson(tree, options) {
|
|
18767
18903
|
const warnings = [
|
|
18768
18904
|
"OTLP JSON export uses OTel GenAI-aligned attributes where applicable; experimental until verified against specific collectors.",
|
|
18769
|
-
"Not OTLP gRPC/protobuf \u2014 JSON mapping only. Generated locally; no network upload."
|
|
18905
|
+
"Not OTLP gRPC/protobuf \u2014 JSON mapping only. Generated locally; no network upload.",
|
|
18906
|
+
"Status and span kind use OTLP numeric enums (StatusCode 0/1/2, SpanKind INTERNAL=1)."
|
|
18770
18907
|
];
|
|
18771
18908
|
const traceId = hexFrom2(`trace:${tree.runId}`, 16);
|
|
18772
18909
|
const includeAttributes = options?.includeAttributes ?? false;
|
|
@@ -18778,11 +18915,7 @@ function exportOtlpJson(tree, options) {
|
|
|
18778
18915
|
const ev = n.event;
|
|
18779
18916
|
const spanId = hexFrom2(`${tree.runId}:${ev.eventId}`, 8);
|
|
18780
18917
|
const parentSpanId = ev.parentId ? hexFrom2(`${tree.runId}:${ev.parentId}`, 8) : void 0;
|
|
18781
|
-
const startNs =
|
|
18782
|
-
let endNs;
|
|
18783
|
-
if (ev.durationMs !== void 0 && Number.isFinite(ev.durationMs)) {
|
|
18784
|
-
endNs = String(unixNano2(ev.timestamp) + unixNano2(ev.durationMs));
|
|
18785
|
-
}
|
|
18918
|
+
const { startNs, endNs } = resolveSpanTimes(ev);
|
|
18786
18919
|
const attrs = [
|
|
18787
18920
|
stringAttr2("agent_inspect.kind", ev.kind),
|
|
18788
18921
|
stringAttr2("agent_inspect.confidence", ev.confidence),
|
|
@@ -18812,29 +18945,28 @@ function exportOtlpJson(tree, options) {
|
|
|
18812
18945
|
if (includeAttributes && meta2 && typeof meta2 === "object") {
|
|
18813
18946
|
for (const [k, v] of Object.entries(meta2)) {
|
|
18814
18947
|
if (k === "tokens" || k === "model") continue;
|
|
18815
|
-
if (typeof v === "string"
|
|
18816
|
-
attrs.push(
|
|
18817
|
-
|
|
18818
|
-
|
|
18819
|
-
|
|
18820
|
-
|
|
18821
|
-
);
|
|
18948
|
+
if (typeof v === "string") {
|
|
18949
|
+
attrs.push(stringAttr2(`agent_inspect.preview.${k}`, v.slice(0, maxLen)));
|
|
18950
|
+
} else if (typeof v === "number" && Number.isFinite(v)) {
|
|
18951
|
+
attrs.push(numberAttr(`agent_inspect.preview.${k}`, v));
|
|
18952
|
+
} else if (typeof v === "boolean") {
|
|
18953
|
+
attrs.push(boolAttr(`agent_inspect.preview.${k}`, v));
|
|
18822
18954
|
}
|
|
18823
18955
|
}
|
|
18824
18956
|
}
|
|
18825
|
-
let statusCode =
|
|
18957
|
+
let statusCode = OTLP_STATUS_CODE_UNSET;
|
|
18826
18958
|
let statusMessage;
|
|
18827
18959
|
if (ev.status === "error") {
|
|
18828
|
-
statusCode =
|
|
18960
|
+
statusCode = OTLP_STATUS_CODE_ERROR;
|
|
18829
18961
|
statusMessage = meta2 && typeof meta2.error === "object" && meta2.error !== null ? String(meta2.error.message ?? "error").slice(0, maxLen) : "error";
|
|
18830
18962
|
} else if (ev.status === "ok") {
|
|
18831
|
-
statusCode =
|
|
18963
|
+
statusCode = OTLP_STATUS_CODE_OK;
|
|
18832
18964
|
}
|
|
18833
18965
|
const spanJson = {
|
|
18834
18966
|
traceId,
|
|
18835
18967
|
spanId,
|
|
18836
18968
|
name: ev.name,
|
|
18837
|
-
kind:
|
|
18969
|
+
kind: OTLP_SPAN_KIND_INTERNAL,
|
|
18838
18970
|
startTimeUnixNano: startNs,
|
|
18839
18971
|
attributes: attrs,
|
|
18840
18972
|
status: {
|
|
@@ -18876,6 +19008,136 @@ function exportOtlpJson(tree, options) {
|
|
|
18876
19008
|
|
|
18877
19009
|
// packages/core/src/exporters/validation.ts
|
|
18878
19010
|
var EXPERIMENTAL = "Experimental compatibility export \u2014 verify against your target tooling before relying on it.";
|
|
19011
|
+
function pushPath(errors, path44, message) {
|
|
19012
|
+
errors.push(`${path44}: ${message}`);
|
|
19013
|
+
}
|
|
19014
|
+
function isRecord16(value) {
|
|
19015
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
19016
|
+
}
|
|
19017
|
+
function validateOtlpJson(content) {
|
|
19018
|
+
const errors = [];
|
|
19019
|
+
const warnings = [
|
|
19020
|
+
EXPERIMENTAL,
|
|
19021
|
+
"OTLP JSON mapping uses OTel GenAI-aligned attributes where applicable; collectors may require transformation.",
|
|
19022
|
+
"protocol-valid \u2260 profile-complete \u2260 fixture-complete \u2014 nested path diagnostics report protocol shape only."
|
|
19023
|
+
];
|
|
19024
|
+
let parsed;
|
|
19025
|
+
try {
|
|
19026
|
+
parsed = JSON.parse(content);
|
|
19027
|
+
} catch {
|
|
19028
|
+
pushPath(errors, "$", "OTLP JSON export is not valid JSON");
|
|
19029
|
+
return { ok: false, format: "otlp-json", errors, warnings };
|
|
19030
|
+
}
|
|
19031
|
+
if (!isRecord16(parsed)) {
|
|
19032
|
+
pushPath(errors, "$", "OTLP JSON export must be an object");
|
|
19033
|
+
return { ok: false, format: "otlp-json", errors, warnings };
|
|
19034
|
+
}
|
|
19035
|
+
if (!Array.isArray(parsed.resourceSpans)) {
|
|
19036
|
+
pushPath(errors, "$.resourceSpans", "must be an array");
|
|
19037
|
+
return { ok: false, format: "otlp-json", errors, warnings };
|
|
19038
|
+
}
|
|
19039
|
+
parsed.resourceSpans.forEach((resourceSpan, rsi) => {
|
|
19040
|
+
const rsPath = `$.resourceSpans[${rsi}]`;
|
|
19041
|
+
if (!isRecord16(resourceSpan)) {
|
|
19042
|
+
pushPath(errors, rsPath, "must be an object");
|
|
19043
|
+
return;
|
|
19044
|
+
}
|
|
19045
|
+
if (!Array.isArray(resourceSpan.scopeSpans)) {
|
|
19046
|
+
pushPath(errors, `${rsPath}.scopeSpans`, "must be an array");
|
|
19047
|
+
return;
|
|
19048
|
+
}
|
|
19049
|
+
resourceSpan.scopeSpans.forEach((scopeSpan, ssi) => {
|
|
19050
|
+
const ssPath = `${rsPath}.scopeSpans[${ssi}]`;
|
|
19051
|
+
if (!isRecord16(scopeSpan)) {
|
|
19052
|
+
pushPath(errors, ssPath, "must be an object");
|
|
19053
|
+
return;
|
|
19054
|
+
}
|
|
19055
|
+
if (!Array.isArray(scopeSpan.spans)) {
|
|
19056
|
+
pushPath(errors, `${ssPath}.spans`, "must be an array");
|
|
19057
|
+
return;
|
|
19058
|
+
}
|
|
19059
|
+
scopeSpan.spans.forEach((span, spi) => {
|
|
19060
|
+
const spanPath = `${ssPath}.spans[${spi}]`;
|
|
19061
|
+
if (!isRecord16(span)) {
|
|
19062
|
+
pushPath(errors, spanPath, "must be an object");
|
|
19063
|
+
return;
|
|
19064
|
+
}
|
|
19065
|
+
if (typeof span.traceId !== "string" || span.traceId.length === 0) {
|
|
19066
|
+
pushPath(errors, `${spanPath}.traceId`, "must be a non-empty string");
|
|
19067
|
+
}
|
|
19068
|
+
if (typeof span.spanId !== "string" || span.spanId.length === 0) {
|
|
19069
|
+
pushPath(errors, `${spanPath}.spanId`, "must be a non-empty string");
|
|
19070
|
+
}
|
|
19071
|
+
if (typeof span.name !== "string") {
|
|
19072
|
+
pushPath(errors, `${spanPath}.name`, "must be a string");
|
|
19073
|
+
}
|
|
19074
|
+
if (typeof span.startTimeUnixNano !== "string" || !/^\d+$/.test(span.startTimeUnixNano)) {
|
|
19075
|
+
pushPath(
|
|
19076
|
+
errors,
|
|
19077
|
+
`${spanPath}.startTimeUnixNano`,
|
|
19078
|
+
"must be a decimal-string 64-bit integer"
|
|
19079
|
+
);
|
|
19080
|
+
}
|
|
19081
|
+
if (span.endTimeUnixNano !== void 0 && (typeof span.endTimeUnixNano !== "string" || !/^\d+$/.test(span.endTimeUnixNano))) {
|
|
19082
|
+
pushPath(
|
|
19083
|
+
errors,
|
|
19084
|
+
`${spanPath}.endTimeUnixNano`,
|
|
19085
|
+
"must be a decimal-string 64-bit integer when present"
|
|
19086
|
+
);
|
|
19087
|
+
}
|
|
19088
|
+
if (typeof span.kind === "number") {
|
|
19089
|
+
if (!Number.isInteger(span.kind)) {
|
|
19090
|
+
pushPath(errors, `${spanPath}.kind`, "must be an integer SpanKind enum");
|
|
19091
|
+
}
|
|
19092
|
+
} else if (typeof span.kind === "string") {
|
|
19093
|
+
warnings.push(
|
|
19094
|
+
`${spanPath}.kind: string SpanKind enum is legacy; prefer numeric (INTERNAL=1)`
|
|
19095
|
+
);
|
|
19096
|
+
} else if (span.kind !== void 0) {
|
|
19097
|
+
pushPath(
|
|
19098
|
+
errors,
|
|
19099
|
+
`${spanPath}.kind`,
|
|
19100
|
+
"must be numeric SpanKind or historical string enum"
|
|
19101
|
+
);
|
|
19102
|
+
}
|
|
19103
|
+
if (!isRecord16(span.status)) {
|
|
19104
|
+
pushPath(errors, `${spanPath}.status`, "must be an object");
|
|
19105
|
+
} else {
|
|
19106
|
+
const code = span.status.code;
|
|
19107
|
+
if (typeof code === "number") {
|
|
19108
|
+
if (![0, 1, 2].includes(code)) {
|
|
19109
|
+
pushPath(
|
|
19110
|
+
errors,
|
|
19111
|
+
`${spanPath}.status.code`,
|
|
19112
|
+
"must be numeric StatusCode 0 (UNSET), 1 (OK), or 2 (ERROR)"
|
|
19113
|
+
);
|
|
19114
|
+
}
|
|
19115
|
+
} else if (typeof code === "string") {
|
|
19116
|
+
const upper = code.toUpperCase();
|
|
19117
|
+
if (upper !== "STATUS_CODE_UNSET" && upper !== "STATUS_CODE_OK" && upper !== "STATUS_CODE_ERROR" && upper !== "UNSET" && upper !== "OK" && upper !== "ERROR" && !/^[012]$/.test(code.trim())) {
|
|
19118
|
+
pushPath(
|
|
19119
|
+
errors,
|
|
19120
|
+
`${spanPath}.status.code`,
|
|
19121
|
+
"unrecognized StatusCode string"
|
|
19122
|
+
);
|
|
19123
|
+
} else {
|
|
19124
|
+
warnings.push(
|
|
19125
|
+
`${spanPath}.status.code: string StatusCode is legacy; prefer numeric 0/1/2`
|
|
19126
|
+
);
|
|
19127
|
+
}
|
|
19128
|
+
} else {
|
|
19129
|
+
pushPath(
|
|
19130
|
+
errors,
|
|
19131
|
+
`${spanPath}.status.code`,
|
|
19132
|
+
"must be numeric StatusCode 0/1/2 or historical string enum"
|
|
19133
|
+
);
|
|
19134
|
+
}
|
|
19135
|
+
}
|
|
19136
|
+
});
|
|
19137
|
+
});
|
|
19138
|
+
});
|
|
19139
|
+
return { ok: errors.length === 0, format: "otlp-json", errors, warnings };
|
|
19140
|
+
}
|
|
18879
19141
|
function validateExportContent(format, content) {
|
|
18880
19142
|
const errors = [];
|
|
18881
19143
|
const warnings = [EXPERIMENTAL];
|
|
@@ -18921,25 +19183,7 @@ function validateExportContent(format, content) {
|
|
|
18921
19183
|
return { ok: errors.length === 0, format, errors, warnings };
|
|
18922
19184
|
}
|
|
18923
19185
|
if (format === "otlp-json") {
|
|
18924
|
-
|
|
18925
|
-
try {
|
|
18926
|
-
parsed = JSON.parse(content);
|
|
18927
|
-
} catch {
|
|
18928
|
-
errors.push("OTLP JSON export is not valid JSON");
|
|
18929
|
-
return { ok: false, format, errors, warnings };
|
|
18930
|
-
}
|
|
18931
|
-
if (!parsed || typeof parsed !== "object") {
|
|
18932
|
-
errors.push("OTLP JSON export must be an object");
|
|
18933
|
-
return { ok: false, format, errors, warnings };
|
|
18934
|
-
}
|
|
18935
|
-
const o = parsed;
|
|
18936
|
-
if (!Array.isArray(o.resourceSpans)) {
|
|
18937
|
-
errors.push("OTLP JSON export must include resourceSpans array");
|
|
18938
|
-
}
|
|
18939
|
-
warnings.push(
|
|
18940
|
-
"OTLP JSON mapping uses OTel GenAI-aligned attributes where applicable; collectors may require transformation."
|
|
18941
|
-
);
|
|
18942
|
-
return { ok: errors.length === 0, format, errors, warnings };
|
|
19186
|
+
return validateOtlpJson(content);
|
|
18943
19187
|
}
|
|
18944
19188
|
errors.push(`Unsupported export format`);
|
|
18945
19189
|
return { ok: false, format, errors, warnings };
|
|
@@ -19343,7 +19587,7 @@ async function exportCommand(runId, options = {}) {
|
|
|
19343
19587
|
const traceDir = resolveTraceDir({ dir: options.dir });
|
|
19344
19588
|
let events;
|
|
19345
19589
|
try {
|
|
19346
|
-
const result2 = await
|
|
19590
|
+
const result2 = await readRunPersistedEvents(id, traceDir);
|
|
19347
19591
|
events = result2?.events ?? [];
|
|
19348
19592
|
} catch (e) {
|
|
19349
19593
|
const msg = e instanceof Error ? e.message : String(e);
|
|
@@ -19359,7 +19603,11 @@ Trace directory: ${traceDir}`);
|
|
|
19359
19603
|
}
|
|
19360
19604
|
let tree;
|
|
19361
19605
|
try {
|
|
19362
|
-
|
|
19606
|
+
const trees = persistedInspectEventsToRunTrees(events);
|
|
19607
|
+
tree = trees.find((candidate) => candidate.runId === id) ?? trees[0];
|
|
19608
|
+
if (tree === void 0) {
|
|
19609
|
+
throw new Error("No run tree could be built from persisted events");
|
|
19610
|
+
}
|
|
19363
19611
|
} catch (e) {
|
|
19364
19612
|
const msg = e instanceof Error ? e.message : String(e);
|
|
19365
19613
|
console.error(`[AgentInspect] export failed: ${msg}`);
|
|
@@ -19387,7 +19635,9 @@ Trace directory: ${traceDir}`);
|
|
|
19387
19635
|
await promises.mkdir(path33__default.default.dirname(outPath), { recursive: true });
|
|
19388
19636
|
await promises.writeFile(outPath, result.content, "utf-8");
|
|
19389
19637
|
const vlabel = validation !== void 0 ? validation.ok ? "ok" : "failed" : "skipped";
|
|
19390
|
-
console.
|
|
19638
|
+
console.error(
|
|
19639
|
+
`Wrote ${result.fileExtension} export to ${outPath} (validation: ${vlabel})`
|
|
19640
|
+
);
|
|
19391
19641
|
if (validation !== void 0 && !validation.ok) {
|
|
19392
19642
|
console.error("Validation errors:", validation.errors.join("; "));
|
|
19393
19643
|
}
|
|
@@ -19400,7 +19650,9 @@ Trace directory: ${traceDir}`);
|
|
|
19400
19650
|
warnings: [...result.warnings, ...validation?.warnings ?? []],
|
|
19401
19651
|
validation
|
|
19402
19652
|
};
|
|
19403
|
-
if (outPath
|
|
19653
|
+
if (outPath !== void 0) {
|
|
19654
|
+
payload.out = outPath;
|
|
19655
|
+
} else {
|
|
19404
19656
|
payload.content = result.content;
|
|
19405
19657
|
}
|
|
19406
19658
|
console.log(JSON.stringify(payload, null, 2));
|
|
@@ -20302,7 +20554,7 @@ function isCredentialSensitiveKey2(key, sensitiveKeys) {
|
|
|
20302
20554
|
}
|
|
20303
20555
|
|
|
20304
20556
|
// packages/redact/src/key-value-secret.ts
|
|
20305
|
-
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"'
|
|
20557
|
+
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,})`;
|
|
20306
20558
|
var KEY_VALUE_SECRET_PATTERN2 = new RegExp(
|
|
20307
20559
|
KEY_VALUE_SECRET_PATTERN_SOURCE,
|
|
20308
20560
|
"i"
|
|
@@ -20327,6 +20579,8 @@ var CONNECTION_PROTOCOLS2 = /* @__PURE__ */ new Set([
|
|
|
20327
20579
|
"amqps:"
|
|
20328
20580
|
]);
|
|
20329
20581
|
var CONNECTION_URI2 = /^(?:postgres|postgresql|mysql|mariadb|mongodb(?:\+srv)?|rediss?|amqps?):\/\/[^\s]+$/i;
|
|
20582
|
+
var CONNECTION_USERINFO2 = /^(postgres|postgresql|mysql|mariadb|mongodb(?:\+srv)?|rediss?|amqps?):\/\/([^@/?#]+)@(.+)$/i;
|
|
20583
|
+
var CONNECTION_HAS_USERINFO2 = /^(?:postgres|postgresql|mysql|mariadb|mongodb(?:\+srv)?|rediss?|amqps?):\/\/[^@/?#]+@/i;
|
|
20330
20584
|
var UUID_SEGMENT2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
20331
20585
|
var HEX_SEGMENT2 = /^[0-9a-f]{12,}$/i;
|
|
20332
20586
|
var NUMERIC_SEGMENT2 = /^\d{5,}$/;
|
|
@@ -20350,6 +20604,28 @@ function parseRedactableUrl2(value) {
|
|
|
20350
20604
|
return void 0;
|
|
20351
20605
|
}
|
|
20352
20606
|
}
|
|
20607
|
+
function redactConnectionUserinfoFallback2(value, replacement) {
|
|
20608
|
+
const trimmed = value.trim();
|
|
20609
|
+
const match = CONNECTION_USERINFO2.exec(trimmed);
|
|
20610
|
+
if (match) {
|
|
20611
|
+
const [, scheme, , rest] = match;
|
|
20612
|
+
if (scheme && rest && rest.length > 0) {
|
|
20613
|
+
return {
|
|
20614
|
+
value: `${scheme}://${rest}`,
|
|
20615
|
+
credentialRedacted: true,
|
|
20616
|
+
identifiersMasked: false
|
|
20617
|
+
};
|
|
20618
|
+
}
|
|
20619
|
+
}
|
|
20620
|
+
if (looksLikeConnectionUri2(trimmed) && CONNECTION_HAS_USERINFO2.test(trimmed)) {
|
|
20621
|
+
return {
|
|
20622
|
+
value: replacement,
|
|
20623
|
+
credentialRedacted: true,
|
|
20624
|
+
identifiersMasked: false
|
|
20625
|
+
};
|
|
20626
|
+
}
|
|
20627
|
+
return void 0;
|
|
20628
|
+
}
|
|
20353
20629
|
function isHttpProtocol2(protocol) {
|
|
20354
20630
|
return protocol === "http:" || protocol === "https:";
|
|
20355
20631
|
}
|
|
@@ -20391,9 +20667,11 @@ function redactUrlString2(value, options) {
|
|
|
20391
20667
|
identifiersMasked: false
|
|
20392
20668
|
};
|
|
20393
20669
|
if (!looksLikeUrlForRedaction2(value)) return unchanged;
|
|
20394
|
-
const url = parseRedactableUrl2(value);
|
|
20395
|
-
if (!url) return unchanged;
|
|
20396
20670
|
const replacement = options.replacement ?? "[REDACTED]";
|
|
20671
|
+
const url = parseRedactableUrl2(value);
|
|
20672
|
+
if (!url) {
|
|
20673
|
+
return redactConnectionUserinfoFallback2(value, replacement) ?? unchanged;
|
|
20674
|
+
}
|
|
20397
20675
|
const idPlaceholder = options.idPlaceholder ?? "[id]";
|
|
20398
20676
|
const http = isHttpProtocol2(url.protocol);
|
|
20399
20677
|
let credentialRedacted = url.username.length > 0 || url.password.length > 0;
|
|
@@ -20486,7 +20764,7 @@ var STRICT_PROFILE_EXTRA_KEYS2 = [
|
|
|
20486
20764
|
"retrieval",
|
|
20487
20765
|
"query"
|
|
20488
20766
|
];
|
|
20489
|
-
function
|
|
20767
|
+
function isRecord17(value) {
|
|
20490
20768
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20491
20769
|
}
|
|
20492
20770
|
function toKey2(key) {
|
|
@@ -20915,7 +21193,7 @@ var Redactor2 = class {
|
|
|
20915
21193
|
});
|
|
20916
21194
|
return out;
|
|
20917
21195
|
}
|
|
20918
|
-
if (
|
|
21196
|
+
if (isRecord17(value)) {
|
|
20919
21197
|
if (state.seen.has(value)) return state.seen.get(value);
|
|
20920
21198
|
const out = {};
|
|
20921
21199
|
state.seen.set(value, out);
|
|
@@ -20950,7 +21228,7 @@ var REDACTION_POLICY_LIMITS = {
|
|
|
20950
21228
|
};
|
|
20951
21229
|
var ALLOWED_TOP_LEVEL = /* @__PURE__ */ new Set(["version", "extraKeys", "patterns"]);
|
|
20952
21230
|
var ALLOWED_PATTERN_FIELDS = /* @__PURE__ */ new Set(["id", "type", "value", "severity"]);
|
|
20953
|
-
function
|
|
21231
|
+
function isRecord18(value) {
|
|
20954
21232
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
20955
21233
|
}
|
|
20956
21234
|
function rejectRemotePolicyPath(policyPath) {
|
|
@@ -20990,7 +21268,7 @@ function rejectUnknownFields(record, allowed, label) {
|
|
|
20990
21268
|
}
|
|
20991
21269
|
function compilePatternDetector(input3, index) {
|
|
20992
21270
|
const label = `patterns[${index}]`;
|
|
20993
|
-
if (!
|
|
21271
|
+
if (!isRecord18(input3)) throw new Error(`${label} must be an object.`);
|
|
20994
21272
|
const typeEarly = input3.type;
|
|
20995
21273
|
if (typeEarly === "typed") {
|
|
20996
21274
|
throw new Error(
|
|
@@ -21045,7 +21323,7 @@ function compilePatternDetector(input3, index) {
|
|
|
21045
21323
|
};
|
|
21046
21324
|
}
|
|
21047
21325
|
function compileRedactionPolicy(raw, policyPath) {
|
|
21048
|
-
if (!
|
|
21326
|
+
if (!isRecord18(raw)) {
|
|
21049
21327
|
throw new Error(`Redaction policy must be a JSON object (${policyPath}).`);
|
|
21050
21328
|
}
|
|
21051
21329
|
rejectUnknownFields(raw, ALLOWED_TOP_LEVEL, "Redaction policy");
|
|
@@ -22081,7 +22359,7 @@ async function openCommand(input3, options = {}, stdin = process.stdin) {
|
|
|
22081
22359
|
|
|
22082
22360
|
// packages/cli/src/migrate.ts
|
|
22083
22361
|
init_advanced();
|
|
22084
|
-
function
|
|
22362
|
+
function isRecord19(value) {
|
|
22085
22363
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
22086
22364
|
}
|
|
22087
22365
|
function parseTarget(value) {
|
|
@@ -22090,7 +22368,7 @@ function parseTarget(value) {
|
|
|
22090
22368
|
throw new Error('Unsupported migration target. Use "--to 1.0".');
|
|
22091
22369
|
}
|
|
22092
22370
|
function formatOf(value) {
|
|
22093
|
-
if (!
|
|
22371
|
+
if (!isRecord19(value)) return "unknown";
|
|
22094
22372
|
if (value.schemaVersion === "0.1") return "0.1";
|
|
22095
22373
|
if (value.schemaVersion === "0.2") return "0.2";
|
|
22096
22374
|
if (value.schemaVersion === "1.0") return "1.0";
|
|
@@ -28614,16 +28892,120 @@ function demoTemplate(framework) {
|
|
|
28614
28892
|
switch (framework) {
|
|
28615
28893
|
case "ai-sdk":
|
|
28616
28894
|
return `/**
|
|
28617
|
-
* AI SDK starter \u2014
|
|
28618
|
-
* Install: npm install agent-inspect @agent-inspect/ai-sdk ai
|
|
28895
|
+
* AI SDK starter \u2014 keyless MockLanguageModelV3 + @agent-inspect/ai-sdk telemetry.
|
|
28896
|
+
* Install: npm install agent-inspect @agent-inspect/ai-sdk ai@6.0.210 zod
|
|
28619
28897
|
*/
|
|
28620
|
-
import {
|
|
28898
|
+
import { generateText, stepCountIs, tool } from "ai";
|
|
28899
|
+
import { MockLanguageModelV3 } from "ai/test";
|
|
28900
|
+
import { agentInspect } from "@agent-inspect/ai-sdk";
|
|
28901
|
+
import { z } from "zod";
|
|
28902
|
+
import { readdirSync, readFileSync } from "node:fs";
|
|
28903
|
+
import path from "node:path";
|
|
28904
|
+
|
|
28905
|
+
const TRACE_DIR = ".agent-inspect";
|
|
28906
|
+
const ANSWER = "You have 2 orders";
|
|
28907
|
+
const CORRECT_RUN = "ai-sdk-demo-correct";
|
|
28908
|
+
const WRONG_RUN = "ai-sdk-demo-wrong";
|
|
28909
|
+
|
|
28910
|
+
const usage = {
|
|
28911
|
+
inputTokens: { total: 4, noCache: 4, cacheRead: 0, cacheWrite: 0 },
|
|
28912
|
+
outputTokens: { total: 3, text: 3, reasoning: 0 },
|
|
28913
|
+
};
|
|
28914
|
+
|
|
28915
|
+
const lookupOrders = tool({
|
|
28916
|
+
description: "Look up orders for a user",
|
|
28917
|
+
inputSchema: z.object({ userId: z.string() }),
|
|
28918
|
+
execute: async () => ({ orders: 2 }),
|
|
28919
|
+
});
|
|
28920
|
+
|
|
28921
|
+
const deleteOrders = tool({
|
|
28922
|
+
description: "Delete orders for a user (wrong path)",
|
|
28923
|
+
inputSchema: z.object({ userId: z.string() }),
|
|
28924
|
+
execute: async () => ({ orders: 2 }),
|
|
28925
|
+
});
|
|
28926
|
+
|
|
28927
|
+
async function runPath(runName, toolName) {
|
|
28928
|
+
const integration = agentInspect({
|
|
28929
|
+
traceDir: TRACE_DIR,
|
|
28930
|
+
runName,
|
|
28931
|
+
capture: "metadata-only",
|
|
28932
|
+
});
|
|
28933
|
+
let step = 0;
|
|
28934
|
+
try {
|
|
28935
|
+
const result = await generateText({
|
|
28936
|
+
model: new MockLanguageModelV3({
|
|
28937
|
+
provider: "fixture-provider",
|
|
28938
|
+
modelId: "fixture-tools",
|
|
28939
|
+
doGenerate: async () => {
|
|
28940
|
+
step += 1;
|
|
28941
|
+
if (step === 1) {
|
|
28942
|
+
return {
|
|
28943
|
+
content: [
|
|
28944
|
+
{
|
|
28945
|
+
type: "tool-call",
|
|
28946
|
+
toolCallId: \`call-\${toolName}\`,
|
|
28947
|
+
toolName,
|
|
28948
|
+
input: { userId: "u1" },
|
|
28949
|
+
},
|
|
28950
|
+
],
|
|
28951
|
+
finishReason: { unified: "tool-calls", raw: "tool-calls" },
|
|
28952
|
+
usage,
|
|
28953
|
+
warnings: [],
|
|
28954
|
+
};
|
|
28955
|
+
}
|
|
28956
|
+
return {
|
|
28957
|
+
content: [{ type: "text", text: ANSWER }],
|
|
28958
|
+
finishReason: { unified: "stop", raw: "stop" },
|
|
28959
|
+
usage,
|
|
28960
|
+
warnings: [],
|
|
28961
|
+
};
|
|
28962
|
+
},
|
|
28963
|
+
}),
|
|
28964
|
+
tools: { lookup_orders: lookupOrders, delete_orders: deleteOrders },
|
|
28965
|
+
prompt: "How many orders do I have?",
|
|
28966
|
+
stopWhen: stepCountIs(5),
|
|
28967
|
+
experimental_telemetry: {
|
|
28968
|
+
isEnabled: true,
|
|
28969
|
+
recordInputs: false,
|
|
28970
|
+
recordOutputs: false,
|
|
28971
|
+
integrations: [integration],
|
|
28972
|
+
},
|
|
28973
|
+
});
|
|
28974
|
+
if (result.text !== ANSWER) {
|
|
28975
|
+
throw new Error(\`unexpected answer for \${runName}: \${result.text}\`);
|
|
28976
|
+
}
|
|
28977
|
+
} finally {
|
|
28978
|
+
await integration.flush();
|
|
28979
|
+
await integration.close();
|
|
28980
|
+
}
|
|
28981
|
+
}
|
|
28982
|
+
|
|
28983
|
+
function selectRunIdByName(runName) {
|
|
28984
|
+
const files = readdirSync(TRACE_DIR).filter((f) => f.endsWith(".jsonl"));
|
|
28985
|
+
const matches = [];
|
|
28986
|
+
for (const file of files) {
|
|
28987
|
+
const text = readFileSync(path.join(TRACE_DIR, file), "utf8");
|
|
28988
|
+
if (text.includes(\`"name":"\${runName}"\`) || text.includes(\`"name": "\${runName}"\`)) {
|
|
28989
|
+
matches.push(file.replace(/\\.jsonl$/, ""));
|
|
28990
|
+
}
|
|
28991
|
+
}
|
|
28992
|
+
if (matches.length !== 1) {
|
|
28993
|
+
throw new Error(
|
|
28994
|
+
\`expected exactly one run named \${runName}, found \${matches.length}\`,
|
|
28995
|
+
);
|
|
28996
|
+
}
|
|
28997
|
+
return matches[0];
|
|
28998
|
+
}
|
|
28621
28999
|
|
|
28622
29000
|
async function main() {
|
|
28623
|
-
await
|
|
28624
|
-
|
|
28625
|
-
|
|
29001
|
+
await runPath(CORRECT_RUN, "lookup_orders");
|
|
29002
|
+
await runPath(WRONG_RUN, "delete_orders");
|
|
29003
|
+
const correctId = selectRunIdByName(CORRECT_RUN);
|
|
29004
|
+
const wrongId = selectRunIdByName(WRONG_RUN);
|
|
28626
29005
|
console.log("Trace written to .agent-inspect/");
|
|
29006
|
+
console.log(\`Correct path runId: \${correctId}\`);
|
|
29007
|
+
console.log(\`Wrong path runId: \${wrongId}\`);
|
|
29008
|
+
console.log(\`Next: npx agent-inspect check \${correctId} --required-tool lookup_orders\`);
|
|
28627
29009
|
}
|
|
28628
29010
|
|
|
28629
29011
|
main().catch((error) => {
|