@agent-inspect/viewer 6.14.1 → 6.15.0
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/dist/index.cjs +267 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +267 -24
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -2216,6 +2216,81 @@ async function resolveSuiteCaseTrace(suiteCase, options) {
|
|
|
2216
2216
|
};
|
|
2217
2217
|
}
|
|
2218
2218
|
|
|
2219
|
+
// packages/core/src/diagnostics/programmatic.ts
|
|
2220
|
+
var PROGRAMMATIC_DIAGNOSTIC_SPECS = Object.freeze({
|
|
2221
|
+
AI_TRACE_INPUT_INVALID: {
|
|
2222
|
+
code: "AI_TRACE_INPUT_INVALID",
|
|
2223
|
+
summary: 'Expected { type: "file", path }, { type: "directory", path }, { type: "string", content }, { type: "buffer", content }, or { type: "stdin" }.',
|
|
2224
|
+
remediation: "For a file path, use openTraceFile(path).",
|
|
2225
|
+
relatedCodes: ["invalid_input"]
|
|
2226
|
+
},
|
|
2227
|
+
AI_TRACE_FORMAT_UNSUPPORTED: {
|
|
2228
|
+
code: "AI_TRACE_FORMAT_UNSUPPORTED",
|
|
2229
|
+
summary: "No trace reader could detect the input format.",
|
|
2230
|
+
remediation: "Pass an AgentInspect JSONL file via openTraceFile, or set options.format to a registered reader.",
|
|
2231
|
+
relatedCodes: ["unsupported_format"]
|
|
2232
|
+
},
|
|
2233
|
+
AI_TRACE_FORMAT_AMBIGUOUS: {
|
|
2234
|
+
code: "AI_TRACE_FORMAT_AMBIGUOUS",
|
|
2235
|
+
summary: "Multiple trace readers matched the input with equal confidence.",
|
|
2236
|
+
remediation: "Set options.format explicitly to disambiguate the reader.",
|
|
2237
|
+
relatedCodes: ["ambiguous_format"]
|
|
2238
|
+
},
|
|
2239
|
+
AI_TRACE_FACTS_INPUT_NOT_NORMALIZED: {
|
|
2240
|
+
code: "AI_TRACE_FACTS_INPUT_NOT_NORMALIZED",
|
|
2241
|
+
summary: "TraceFacts requires TraceReadResult or PersistedInspectEvent[].",
|
|
2242
|
+
remediation: "Use openTraceFile() to normalize a JSONL trace first."
|
|
2243
|
+
},
|
|
2244
|
+
AI_TRACE_CONTRACT_RUN_SELECTION_REQUIRED: {
|
|
2245
|
+
code: "AI_TRACE_CONTRACT_RUN_SELECTION_REQUIRED",
|
|
2246
|
+
summary: "Multiple runs are available; select a run before executing checks.",
|
|
2247
|
+
remediation: "Pass options.runId or TraceCheckInput.selectedRun.",
|
|
2248
|
+
relatedCodes: ["AI_CHECK_RUN_SELECTION_REQUIRED"]
|
|
2249
|
+
},
|
|
2250
|
+
AI_TRACE_RELATIONSHIP_SELF_PARENT: {
|
|
2251
|
+
code: "AI_TRACE_RELATIONSHIP_SELF_PARENT",
|
|
2252
|
+
summary: "A parentId equals its own event/step id.",
|
|
2253
|
+
remediation: "Reject at capture (AI_LANGGRAPH_SELF_PARENT_REJECTED) or drop via logical projection; do not invent replacement parents.",
|
|
2254
|
+
relatedCodes: [
|
|
2255
|
+
"AI_LANGGRAPH_SELF_PARENT_REJECTED",
|
|
2256
|
+
"AI_LOGICAL_SELF_PARENT_REMOVED"
|
|
2257
|
+
]
|
|
2258
|
+
},
|
|
2259
|
+
AI_TRACE_RELATIONSHIP_CYCLE: {
|
|
2260
|
+
code: "AI_TRACE_RELATIONSHIP_CYCLE",
|
|
2261
|
+
summary: "Trace contains a parentId cycle.",
|
|
2262
|
+
remediation: "Use visibility-first tree linking for legacy fixtures; prefer acyclic capture for new adapter output.",
|
|
2263
|
+
relatedCodes: ["structure.cycle"]
|
|
2264
|
+
}
|
|
2265
|
+
});
|
|
2266
|
+
function formatProgrammaticDiagnostic(code, detail) {
|
|
2267
|
+
const spec = PROGRAMMATIC_DIAGNOSTIC_SPECS[code];
|
|
2268
|
+
const summary = detail?.trim() ? detail.trim() : spec.summary;
|
|
2269
|
+
return `${code}: ${summary} Remediation: ${spec.remediation}`;
|
|
2270
|
+
}
|
|
2271
|
+
|
|
2272
|
+
// packages/core/src/safety/sensitive-key.ts
|
|
2273
|
+
function normalizeSensitiveKey(value) {
|
|
2274
|
+
return value.toLowerCase().replace(/[^a-z0-9_]/g, "");
|
|
2275
|
+
}
|
|
2276
|
+
new Set(
|
|
2277
|
+
[
|
|
2278
|
+
"tokens",
|
|
2279
|
+
"max_tokens",
|
|
2280
|
+
"min_tokens",
|
|
2281
|
+
"ls_max_tokens",
|
|
2282
|
+
"token_count",
|
|
2283
|
+
"token_limit",
|
|
2284
|
+
"token_budget",
|
|
2285
|
+
"input_tokens",
|
|
2286
|
+
"output_tokens",
|
|
2287
|
+
"total_tokens",
|
|
2288
|
+
"cached_tokens",
|
|
2289
|
+
"prompt_tokens",
|
|
2290
|
+
"completion_tokens"
|
|
2291
|
+
].map(normalizeSensitiveKey)
|
|
2292
|
+
);
|
|
2293
|
+
|
|
2219
2294
|
// packages/core/src/checks/logical-events.ts
|
|
2220
2295
|
function isRecord5(value) {
|
|
2221
2296
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -2411,6 +2486,26 @@ function projectLogicalEvents(events) {
|
|
|
2411
2486
|
}
|
|
2412
2487
|
}
|
|
2413
2488
|
if (!remapped) {
|
|
2489
|
+
if (originalParentId === event.eventId) {
|
|
2490
|
+
diagnostics.push({
|
|
2491
|
+
code: "AI_LOGICAL_SELF_PARENT_REMOVED",
|
|
2492
|
+
message: formatProgrammaticDiagnostic(
|
|
2493
|
+
"AI_TRACE_RELATIONSHIP_SELF_PARENT",
|
|
2494
|
+
`Removed self-parent edge on ${event.eventId}.`
|
|
2495
|
+
),
|
|
2496
|
+
eventIds: [event.eventId]
|
|
2497
|
+
});
|
|
2498
|
+
const { parentId: _drop, ...rest } = event;
|
|
2499
|
+
normalized.push({
|
|
2500
|
+
...rest,
|
|
2501
|
+
projection: {
|
|
2502
|
+
...event.projection,
|
|
2503
|
+
parentNormalized: true,
|
|
2504
|
+
originalParentId
|
|
2505
|
+
}
|
|
2506
|
+
});
|
|
2507
|
+
continue;
|
|
2508
|
+
}
|
|
2414
2509
|
if (!logicalById.has(originalParentId) && !logicalByRawId.has(originalParentId)) {
|
|
2415
2510
|
const mapping = event.attributes?.parentMapping;
|
|
2416
2511
|
const unresolved = mapping === "unresolved" || event.attributes?.parentUnresolved === true || event.attributes?.unresolvedParent === true || // LangGraph/framework scaffolding sentinel labels are not event ids.
|
|
@@ -2426,6 +2521,26 @@ function projectLogicalEvents(events) {
|
|
|
2426
2521
|
normalized.push(event);
|
|
2427
2522
|
continue;
|
|
2428
2523
|
}
|
|
2524
|
+
if (nextParent === event.eventId) {
|
|
2525
|
+
diagnostics.push({
|
|
2526
|
+
code: "AI_LOGICAL_SELF_PARENT_REMOVED",
|
|
2527
|
+
message: formatProgrammaticDiagnostic(
|
|
2528
|
+
"AI_TRACE_RELATIONSHIP_SELF_PARENT",
|
|
2529
|
+
`Removed self-parent edge on ${event.eventId} (was ${originalParentId}).`
|
|
2530
|
+
),
|
|
2531
|
+
eventIds: [event.eventId]
|
|
2532
|
+
});
|
|
2533
|
+
const { parentId: _drop, ...rest } = event;
|
|
2534
|
+
normalized.push({
|
|
2535
|
+
...rest,
|
|
2536
|
+
projection: {
|
|
2537
|
+
...event.projection,
|
|
2538
|
+
parentNormalized: true,
|
|
2539
|
+
originalParentId
|
|
2540
|
+
}
|
|
2541
|
+
});
|
|
2542
|
+
continue;
|
|
2543
|
+
}
|
|
2429
2544
|
diagnostics.push({
|
|
2430
2545
|
code: "AI_LOGICAL_PARENT_REMAPPED",
|
|
2431
2546
|
message: `Remapped parent ${originalParentId} \u2192 ${nextParent} for ${event.eventId}.`,
|
|
@@ -2475,6 +2590,11 @@ function pickString(record, keys) {
|
|
|
2475
2590
|
return void 0;
|
|
2476
2591
|
}
|
|
2477
2592
|
|
|
2593
|
+
// packages/core/src/checks/trace-facts.ts
|
|
2594
|
+
formatProgrammaticDiagnostic(
|
|
2595
|
+
"AI_TRACE_FACTS_INPUT_NOT_NORMALIZED"
|
|
2596
|
+
);
|
|
2597
|
+
|
|
2478
2598
|
// packages/core/src/checks/index.ts
|
|
2479
2599
|
var SEVERITY_RANK = {
|
|
2480
2600
|
error: 0,
|
|
@@ -2584,7 +2704,13 @@ function resolveSelectedRun(input, runId) {
|
|
|
2584
2704
|
if (input.read.runs.length === 0) {
|
|
2585
2705
|
return {
|
|
2586
2706
|
diagnostics: [
|
|
2587
|
-
diagnostic3(
|
|
2707
|
+
diagnostic3(
|
|
2708
|
+
"AI_CHECK_RUN_SELECTION_REQUIRED",
|
|
2709
|
+
formatProgrammaticDiagnostic(
|
|
2710
|
+
"AI_TRACE_CONTRACT_RUN_SELECTION_REQUIRED",
|
|
2711
|
+
"No runs are available for checks."
|
|
2712
|
+
)
|
|
2713
|
+
)
|
|
2588
2714
|
]
|
|
2589
2715
|
};
|
|
2590
2716
|
}
|
|
@@ -2592,7 +2718,7 @@ function resolveSelectedRun(input, runId) {
|
|
|
2592
2718
|
diagnostics: [
|
|
2593
2719
|
diagnostic3(
|
|
2594
2720
|
"AI_CHECK_RUN_SELECTION_REQUIRED",
|
|
2595
|
-
"
|
|
2721
|
+
formatProgrammaticDiagnostic("AI_TRACE_CONTRACT_RUN_SELECTION_REQUIRED")
|
|
2596
2722
|
)
|
|
2597
2723
|
]
|
|
2598
2724
|
};
|
|
@@ -2819,7 +2945,7 @@ function createToolUsageRule(options) {
|
|
|
2819
2945
|
}
|
|
2820
2946
|
}
|
|
2821
2947
|
const forbidden = new Set(options.forbidden ?? []);
|
|
2822
|
-
const allowed = options.allowed ? new Set(options.allowed) : void 0;
|
|
2948
|
+
const allowed = options.allowed?.length ? new Set(options.allowed) : void 0;
|
|
2823
2949
|
for (const event of tools) {
|
|
2824
2950
|
const name = toolName(event);
|
|
2825
2951
|
if (forbidden.has(name)) {
|
|
@@ -2855,9 +2981,9 @@ function createLlmUsageRule(options) {
|
|
|
2855
2981
|
evaluate(context) {
|
|
2856
2982
|
const llms = finishedEvents(context, "LLM");
|
|
2857
2983
|
const findings = [];
|
|
2858
|
-
const allowedModels = options.allowedModels ? new Set(options.allowedModels) : void 0;
|
|
2859
|
-
const allowedProviders = options.allowedProviders ? new Set(options.allowedProviders) : void 0;
|
|
2860
|
-
const finishReasons = options.finishReasons ? new Set(options.finishReasons) : void 0;
|
|
2984
|
+
const allowedModels = options.allowedModels?.length ? new Set(options.allowedModels) : void 0;
|
|
2985
|
+
const allowedProviders = options.allowedProviders?.length ? new Set(options.allowedProviders) : void 0;
|
|
2986
|
+
const finishReasons = options.finishReasons?.length ? new Set(options.finishReasons) : void 0;
|
|
2861
2987
|
if (options.maxCalls !== void 0 && llms.length > options.maxCalls) {
|
|
2862
2988
|
findings.push(
|
|
2863
2989
|
failFinding(
|
|
@@ -3272,6 +3398,20 @@ function traceEventsToPersistedInspectEvents(events, options) {
|
|
|
3272
3398
|
function inc(map, key) {
|
|
3273
3399
|
map[key] = (map[key] ?? 0) + 1;
|
|
3274
3400
|
}
|
|
3401
|
+
function confidenceRank(confidence) {
|
|
3402
|
+
switch (confidence) {
|
|
3403
|
+
case "unknown":
|
|
3404
|
+
return 0;
|
|
3405
|
+
case "heuristic":
|
|
3406
|
+
return 1;
|
|
3407
|
+
case "correlated":
|
|
3408
|
+
return 2;
|
|
3409
|
+
case "explicit":
|
|
3410
|
+
return 3;
|
|
3411
|
+
default:
|
|
3412
|
+
return 0;
|
|
3413
|
+
}
|
|
3414
|
+
}
|
|
3275
3415
|
function computeRunStatus(events) {
|
|
3276
3416
|
let runTerminal;
|
|
3277
3417
|
let sawRunEvent = false;
|
|
@@ -3292,6 +3432,84 @@ function computeRunStatus(events) {
|
|
|
3292
3432
|
}
|
|
3293
3433
|
return hasRunning ? "running" : "ok";
|
|
3294
3434
|
}
|
|
3435
|
+
function linkNodesVisibilityFirst(nodes) {
|
|
3436
|
+
let selfParentCount = 0;
|
|
3437
|
+
let unresolvedParentCount = 0;
|
|
3438
|
+
let normalizedEdgeCount = 0;
|
|
3439
|
+
let cycleCount = 0;
|
|
3440
|
+
const pending = [];
|
|
3441
|
+
for (const node of nodes.values()) {
|
|
3442
|
+
const parentId = node.event.parentId;
|
|
3443
|
+
if (!parentId) continue;
|
|
3444
|
+
if (parentId === node.event.eventId) {
|
|
3445
|
+
selfParentCount += 1;
|
|
3446
|
+
normalizedEdgeCount += 1;
|
|
3447
|
+
continue;
|
|
3448
|
+
}
|
|
3449
|
+
if (!nodes.has(parentId)) {
|
|
3450
|
+
unresolvedParentCount += 1;
|
|
3451
|
+
continue;
|
|
3452
|
+
}
|
|
3453
|
+
pending.push({
|
|
3454
|
+
childId: node.event.eventId,
|
|
3455
|
+
parentId,
|
|
3456
|
+
childTimestamp: node.event.timestamp,
|
|
3457
|
+
childConfidence: node.event.confidence
|
|
3458
|
+
});
|
|
3459
|
+
}
|
|
3460
|
+
pending.sort((a, b) => {
|
|
3461
|
+
const conf = confidenceRank(b.childConfidence) - confidenceRank(a.childConfidence);
|
|
3462
|
+
if (conf !== 0) return conf;
|
|
3463
|
+
return a.childTimestamp - b.childTimestamp;
|
|
3464
|
+
});
|
|
3465
|
+
const parentOf = /* @__PURE__ */ new Map();
|
|
3466
|
+
for (const edge of pending) {
|
|
3467
|
+
parentOf.set(edge.childId, edge.parentId);
|
|
3468
|
+
let cursor = edge.parentId;
|
|
3469
|
+
const seen = /* @__PURE__ */ new Set([edge.childId]);
|
|
3470
|
+
let cyclic = false;
|
|
3471
|
+
while (cursor) {
|
|
3472
|
+
if (seen.has(cursor)) {
|
|
3473
|
+
cyclic = true;
|
|
3474
|
+
break;
|
|
3475
|
+
}
|
|
3476
|
+
seen.add(cursor);
|
|
3477
|
+
cursor = parentOf.get(cursor);
|
|
3478
|
+
}
|
|
3479
|
+
if (cyclic) {
|
|
3480
|
+
parentOf.delete(edge.childId);
|
|
3481
|
+
cycleCount += 1;
|
|
3482
|
+
normalizedEdgeCount += 1;
|
|
3483
|
+
}
|
|
3484
|
+
}
|
|
3485
|
+
for (const [childId, parentId] of parentOf) {
|
|
3486
|
+
nodes.get(parentId).children.push(nodes.get(childId));
|
|
3487
|
+
}
|
|
3488
|
+
const roots = [];
|
|
3489
|
+
for (const node of nodes.values()) {
|
|
3490
|
+
if (!parentOf.has(node.event.eventId)) {
|
|
3491
|
+
roots.push(node);
|
|
3492
|
+
}
|
|
3493
|
+
}
|
|
3494
|
+
const assignDepth = (n, depth, stack) => {
|
|
3495
|
+
if (stack.has(n.event.eventId)) return;
|
|
3496
|
+
n.depth = depth;
|
|
3497
|
+
stack.add(n.event.eventId);
|
|
3498
|
+
for (const c of n.children) assignDepth(c, depth + 1, stack);
|
|
3499
|
+
stack.delete(n.event.eventId);
|
|
3500
|
+
};
|
|
3501
|
+
for (const r of roots) assignDepth(r, 0, /* @__PURE__ */ new Set());
|
|
3502
|
+
return {
|
|
3503
|
+
roots,
|
|
3504
|
+
summary: {
|
|
3505
|
+
rootCount: roots.length,
|
|
3506
|
+
selfParentCount,
|
|
3507
|
+
cycleCount,
|
|
3508
|
+
unresolvedParentCount,
|
|
3509
|
+
normalizedEdgeCount
|
|
3510
|
+
}
|
|
3511
|
+
};
|
|
3512
|
+
}
|
|
3295
3513
|
var TreeBuilder = class {
|
|
3296
3514
|
constructor(options) {
|
|
3297
3515
|
void options?.config;
|
|
@@ -3309,20 +3527,7 @@ var TreeBuilder = class {
|
|
|
3309
3527
|
for (const e of sorted) {
|
|
3310
3528
|
nodes.set(e.eventId, { event: e, children: [], depth: 0 });
|
|
3311
3529
|
}
|
|
3312
|
-
const roots =
|
|
3313
|
-
for (const node of nodes.values()) {
|
|
3314
|
-
const parentId = node.event.parentId;
|
|
3315
|
-
if (parentId && nodes.has(parentId)) {
|
|
3316
|
-
nodes.get(parentId).children.push(node);
|
|
3317
|
-
} else {
|
|
3318
|
-
roots.push(node);
|
|
3319
|
-
}
|
|
3320
|
-
}
|
|
3321
|
-
const assignDepth = (n, depth) => {
|
|
3322
|
-
n.depth = depth;
|
|
3323
|
-
for (const c of n.children) assignDepth(c, depth + 1);
|
|
3324
|
-
};
|
|
3325
|
-
for (const r of roots) assignDepth(r, 0);
|
|
3530
|
+
const { roots, summary } = linkNodesVisibilityFirst(nodes);
|
|
3326
3531
|
const confidenceBreakdown = {
|
|
3327
3532
|
explicit: 0,
|
|
3328
3533
|
correlated: 0,
|
|
@@ -3350,7 +3555,8 @@ var TreeBuilder = class {
|
|
|
3350
3555
|
metadata: {
|
|
3351
3556
|
totalEvents: sorted.length,
|
|
3352
3557
|
confidenceBreakdown,
|
|
3353
|
-
kinds
|
|
3558
|
+
kinds,
|
|
3559
|
+
relationshipSummary: summary
|
|
3354
3560
|
}
|
|
3355
3561
|
});
|
|
3356
3562
|
}
|
|
@@ -3579,6 +3785,38 @@ var TraceReadError = class extends Error {
|
|
|
3579
3785
|
this.warnings = warnings;
|
|
3580
3786
|
}
|
|
3581
3787
|
};
|
|
3788
|
+
var TRACE_INPUT_INVALID_MESSAGE = formatProgrammaticDiagnostic(
|
|
3789
|
+
"AI_TRACE_INPUT_INVALID"
|
|
3790
|
+
);
|
|
3791
|
+
function isTraceInput(input) {
|
|
3792
|
+
if (typeof input !== "object" || input === null || Array.isArray(input)) {
|
|
3793
|
+
return false;
|
|
3794
|
+
}
|
|
3795
|
+
const record = input;
|
|
3796
|
+
switch (record.type) {
|
|
3797
|
+
case "file":
|
|
3798
|
+
case "directory":
|
|
3799
|
+
return typeof record.path === "string";
|
|
3800
|
+
case "string":
|
|
3801
|
+
return typeof record.content === "string";
|
|
3802
|
+
case "buffer":
|
|
3803
|
+
return Buffer.isBuffer(record.content);
|
|
3804
|
+
case "stdin":
|
|
3805
|
+
return true;
|
|
3806
|
+
default:
|
|
3807
|
+
return false;
|
|
3808
|
+
}
|
|
3809
|
+
}
|
|
3810
|
+
function assertTraceInput(input) {
|
|
3811
|
+
if (isTraceInput(input)) return;
|
|
3812
|
+
throw new TraceReadError("invalid_input", TRACE_INPUT_INVALID_MESSAGE, [
|
|
3813
|
+
{
|
|
3814
|
+
code: "AI_TRACE_INPUT_INVALID",
|
|
3815
|
+
message: TRACE_INPUT_INVALID_MESSAGE,
|
|
3816
|
+
severity: "error"
|
|
3817
|
+
}
|
|
3818
|
+
]);
|
|
3819
|
+
}
|
|
3582
3820
|
function normalizeCandidate(reader, candidate) {
|
|
3583
3821
|
const confidence = Number.isFinite(candidate.confidence) ? Math.max(0, Math.min(1, candidate.confidence)) : 0;
|
|
3584
3822
|
return {
|
|
@@ -4933,6 +5171,7 @@ var DEFAULT_TRACE_READERS = [
|
|
|
4933
5171
|
otlpJsonReader
|
|
4934
5172
|
];
|
|
4935
5173
|
async function detectTraceFormat(input, options = {}) {
|
|
5174
|
+
assertTraceInput(input);
|
|
4936
5175
|
const readers = options.readers ?? DEFAULT_TRACE_READERS;
|
|
4937
5176
|
if (options.format !== void 0) {
|
|
4938
5177
|
const reader = findReaderByFormat(options.format, readers);
|
|
@@ -5029,19 +5268,20 @@ async function detectTraceFormat(input, options = {}) {
|
|
|
5029
5268
|
};
|
|
5030
5269
|
}
|
|
5031
5270
|
async function readTrace(input, options = {}) {
|
|
5271
|
+
assertTraceInput(input);
|
|
5032
5272
|
const readers = options.readers ?? DEFAULT_TRACE_READERS;
|
|
5033
5273
|
const detection = await detectTraceFormat(input, options);
|
|
5034
5274
|
if (detection.status === "unsupported" || detection.format === void 0) {
|
|
5035
5275
|
throw new TraceReadError(
|
|
5036
5276
|
"unsupported_format",
|
|
5037
|
-
"
|
|
5277
|
+
formatProgrammaticDiagnostic("AI_TRACE_FORMAT_UNSUPPORTED"),
|
|
5038
5278
|
detection.warnings
|
|
5039
5279
|
);
|
|
5040
5280
|
}
|
|
5041
5281
|
if (detection.status === "ambiguous") {
|
|
5042
5282
|
throw new TraceReadError(
|
|
5043
5283
|
"ambiguous_format",
|
|
5044
|
-
"
|
|
5284
|
+
formatProgrammaticDiagnostic("AI_TRACE_FORMAT_AMBIGUOUS"),
|
|
5045
5285
|
detection.warnings
|
|
5046
5286
|
);
|
|
5047
5287
|
}
|
|
@@ -5049,7 +5289,10 @@ async function readTrace(input, options = {}) {
|
|
|
5049
5289
|
if (!reader) {
|
|
5050
5290
|
throw new TraceReadError(
|
|
5051
5291
|
"unsupported_format",
|
|
5052
|
-
|
|
5292
|
+
formatProgrammaticDiagnostic(
|
|
5293
|
+
"AI_TRACE_FORMAT_UNSUPPORTED",
|
|
5294
|
+
`No trace reader is registered for format "${detection.format}".`
|
|
5295
|
+
),
|
|
5053
5296
|
detection.warnings
|
|
5054
5297
|
);
|
|
5055
5298
|
}
|