@agent-inspect/mcp-server 6.18.0 → 6.19.1

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/cli.cjs CHANGED
@@ -1160,9 +1160,63 @@ async function extractMetadata(filePath, _quickScan) {
1160
1160
  createdAt: stats.birthtime
1161
1161
  };
1162
1162
  }
1163
+ var ROOT_STEP_DEPTH = 0;
1164
+ var MAX_RUN_SUMMARY_DEPTH = 1e3;
1163
1165
  function isNonNegativeFiniteNumber(value) {
1164
1166
  return typeof value === "number" && Number.isFinite(value) && value >= 0;
1165
1167
  }
1168
+ function resolveParentStepId(step, steps) {
1169
+ const parentId = step.parentId;
1170
+ if (typeof parentId !== "string" || parentId.trim() === "") {
1171
+ return void 0;
1172
+ }
1173
+ return steps.has(parentId) ? parentId : void 0;
1174
+ }
1175
+ function computeStepDepth(stepId, steps, depthCache) {
1176
+ const cached = depthCache.get(stepId);
1177
+ if (cached !== void 0) return cached;
1178
+ const ancestry = [];
1179
+ const ancestryIndexes = /* @__PURE__ */ new Map();
1180
+ let currentStepId = stepId;
1181
+ let resolvedDepth;
1182
+ while (resolvedDepth === void 0) {
1183
+ const cachedDepth = depthCache.get(currentStepId);
1184
+ if (cachedDepth !== void 0) {
1185
+ resolvedDepth = cachedDepth;
1186
+ continue;
1187
+ }
1188
+ const cycleStart = ancestryIndexes.get(currentStepId);
1189
+ if (cycleStart !== void 0) {
1190
+ const cycleStepIds = ancestry.splice(cycleStart);
1191
+ for (const cycleStepId of cycleStepIds) {
1192
+ depthCache.set(cycleStepId, ROOT_STEP_DEPTH);
1193
+ }
1194
+ resolvedDepth = ROOT_STEP_DEPTH;
1195
+ continue;
1196
+ }
1197
+ const currentStep = steps.get(currentStepId);
1198
+ if (!currentStep) {
1199
+ resolvedDepth = ROOT_STEP_DEPTH;
1200
+ continue;
1201
+ }
1202
+ ancestryIndexes.set(currentStepId, ancestry.length);
1203
+ ancestry.push(currentStepId);
1204
+ const parentStepId = resolveParentStepId(currentStep, steps);
1205
+ if (parentStepId === void 0) {
1206
+ ancestry.pop();
1207
+ depthCache.set(currentStepId, ROOT_STEP_DEPTH);
1208
+ resolvedDepth = ROOT_STEP_DEPTH;
1209
+ continue;
1210
+ }
1211
+ currentStepId = parentStepId;
1212
+ }
1213
+ ancestry.reverse();
1214
+ for (const ancestorStepId of ancestry) {
1215
+ resolvedDepth = Math.min(MAX_RUN_SUMMARY_DEPTH, resolvedDepth + 1);
1216
+ depthCache.set(ancestorStepId, resolvedDepth);
1217
+ }
1218
+ return depthCache.get(stepId) ?? ROOT_STEP_DEPTH;
1219
+ }
1166
1220
  function buildRunSummary(events) {
1167
1221
  const started = events.find(
1168
1222
  (e) => e.event === "run_started"
@@ -1216,27 +1270,13 @@ function buildRunSummary(events) {
1216
1270
  let stepsWithKnownTotal = 0;
1217
1271
  let hasCachedTokens = false;
1218
1272
  const depthCache = /* @__PURE__ */ new Map();
1219
- const computeDepth = (stepId) => {
1220
- const cached = depthCache.get(stepId);
1221
- if (cached !== void 0) return cached;
1222
- const node = steps.get(stepId);
1223
- if (!node) return 0;
1224
- const parent = node.parentId;
1225
- if (typeof parent !== "string" || parent.trim() === "" || !steps.has(parent)) {
1226
- depthCache.set(stepId, 0);
1227
- return 0;
1228
- }
1229
- const d = Math.min(1e3, computeDepth(parent) + 1);
1230
- depthCache.set(stepId, d);
1231
- return d;
1232
- };
1233
1273
  for (const [id, s] of steps.entries()) {
1234
1274
  totalSteps += 1;
1235
1275
  if (s.type === "llm") llmSteps += 1;
1236
1276
  else if (s.type === "tool") toolSteps += 1;
1237
1277
  else logicSteps += 1;
1238
1278
  if (s.status === "error") errorSteps += 1;
1239
- const depth = computeDepth(id);
1279
+ const depth = computeStepDepth(id, steps, depthCache);
1240
1280
  if (depth > maxDepth) maxDepth = depth;
1241
1281
  if (typeof s.durationMs === "number" && Number.isFinite(s.durationMs)) {
1242
1282
  if (!longestStep || s.durationMs > longestStep.durationMs) {
@@ -3003,6 +3043,325 @@ function pickString(record, keys) {
3003
3043
  return void 0;
3004
3044
  }
3005
3045
 
3046
+ // packages/core/src/checks/derived-failure.ts
3047
+ function isRecord7(value) {
3048
+ return typeof value === "object" && value !== null && !Array.isArray(value);
3049
+ }
3050
+ function pickString2(record, keys) {
3051
+ if (!record) return void 0;
3052
+ for (const key of keys) {
3053
+ const value = record[key];
3054
+ if (typeof value === "string" && value.trim() !== "") return value;
3055
+ }
3056
+ return void 0;
3057
+ }
3058
+ function pickNumber(record, keys) {
3059
+ if (!record) return void 0;
3060
+ for (const key of keys) {
3061
+ const value = record[key];
3062
+ if (typeof value === "number" && Number.isFinite(value) && value > 0) {
3063
+ return value;
3064
+ }
3065
+ }
3066
+ return void 0;
3067
+ }
3068
+ function eventMetadata(event) {
3069
+ const attrs = isRecord7(event.attributes) ? event.attributes : void 0;
3070
+ const nested = attrs !== void 0 && isRecord7(attrs.metadata) ? attrs.metadata : void 0;
3071
+ return {
3072
+ ...attrs ?? {},
3073
+ ...nested ?? {}
3074
+ };
3075
+ }
3076
+ function canonicalName(event) {
3077
+ if (event.kind === "TOOL") return resolveCanonicalToolName(event);
3078
+ return event.name;
3079
+ }
3080
+ function linkKeys(event) {
3081
+ const meta = eventMetadata(event);
3082
+ const keys = [];
3083
+ for (const key of ["linkedStepId", "toolCallId", "mcpToolCallId"]) {
3084
+ const value = pickString2(meta, [key]);
3085
+ if (value !== void 0) keys.push(`${key}:${value}`);
3086
+ }
3087
+ const stepId = pickString2(meta, ["stepId"]);
3088
+ if (stepId !== void 0) keys.push(`stepId:${stepId}`);
3089
+ return keys;
3090
+ }
3091
+ function buildRunContexts(logicalEvents) {
3092
+ const byRun = /* @__PURE__ */ new Map();
3093
+ for (const event of logicalEvents) {
3094
+ const existing = byRun.get(event.runId) ?? {
3095
+ runId: event.runId,
3096
+ name: event.name
3097
+ };
3098
+ const meta = eventMetadata(event);
3099
+ if (event.kind === "RUN" || existing.name === event.runId) {
3100
+ existing.name = event.name || existing.name;
3101
+ }
3102
+ if (event.kind === "RUN" && event.status !== void 0 && event.status !== "running") {
3103
+ existing.status = event.status;
3104
+ }
3105
+ existing.retryOf ??= pickString2(meta, ["retryOf"]);
3106
+ existing.attempt ??= pickNumber(meta, ["attempt", "retryAttempt", "retryCount"]);
3107
+ existing.sessionId ??= pickString2(meta, ["sessionId", "conversationId"]);
3108
+ existing.groupId ??= pickString2(meta, ["groupId"]);
3109
+ existing.parentGroupId ??= pickString2(meta, ["parentGroupId"]);
3110
+ existing.fallbackOf ??= pickString2(meta, ["fallbackOf", "fallbackFrom"]);
3111
+ byRun.set(event.runId, existing);
3112
+ }
3113
+ return byRun;
3114
+ }
3115
+ function sameCorrelationScope(a, b) {
3116
+ if (a.sessionId && b.sessionId && a.sessionId === b.sessionId) return true;
3117
+ if (a.groupId && b.groupId && a.groupId === b.groupId) return true;
3118
+ if (a.parentGroupId && b.parentGroupId && a.parentGroupId === b.parentGroupId) {
3119
+ return true;
3120
+ }
3121
+ return false;
3122
+ }
3123
+ function isSuccessful(event) {
3124
+ return event.status === "ok";
3125
+ }
3126
+ function isFailure(event) {
3127
+ return event.status === "error";
3128
+ }
3129
+ function compareEventOrder(a, b) {
3130
+ const byTime = a.timestamp.localeCompare(b.timestamp);
3131
+ if (byTime !== 0) return byTime;
3132
+ return a.eventId.localeCompare(b.eventId);
3133
+ }
3134
+ function collectCandidates(failure, logicalEvents, runs) {
3135
+ const failureRun = runs.get(failure.runId);
3136
+ const failureLinks = new Set(linkKeys(failure));
3137
+ const failureName = canonicalName(failure);
3138
+ const failureAttempt = pickNumber(eventMetadata(failure), ["attempt", "retryAttempt", "retryCount"]) ?? failureRun?.attempt;
3139
+ const candidates = [];
3140
+ for (const event of logicalEvents) {
3141
+ if (event.eventId === failure.eventId) continue;
3142
+ if (event.status === "running") continue;
3143
+ const eventRun = runs.get(event.runId);
3144
+ const eventMeta = eventMetadata(event);
3145
+ const sameRun = event.runId === failure.runId;
3146
+ if (eventRun?.retryOf === failure.runId) {
3147
+ candidates.push({
3148
+ event,
3149
+ basis: "retryOf",
3150
+ confidence: "explicit",
3151
+ viaRunId: event.runId
3152
+ });
3153
+ continue;
3154
+ }
3155
+ if (eventRun?.fallbackOf === failure.runId || pickString2(eventMeta, ["fallbackOf", "fallbackFrom"]) === failure.runId) {
3156
+ candidates.push({
3157
+ event,
3158
+ basis: "fallbackOf",
3159
+ confidence: "explicit",
3160
+ viaRunId: event.runId
3161
+ });
3162
+ continue;
3163
+ }
3164
+ if (sameRun && compareEventOrder(failure, event) >= 0) continue;
3165
+ const eventLinks = linkKeys(event);
3166
+ const sharedLink = eventLinks.find((key) => failureLinks.has(key));
3167
+ if (sharedLink !== void 0) {
3168
+ candidates.push({
3169
+ event,
3170
+ basis: sharedLink.split(":")[0] ?? "linkedId",
3171
+ confidence: "explicit"
3172
+ });
3173
+ continue;
3174
+ }
3175
+ const eventAttempt = pickNumber(eventMeta, ["attempt", "retryAttempt", "retryCount"]) ?? eventRun?.attempt;
3176
+ const sameParent = failure.parentId !== void 0 && event.parentId !== void 0 && failure.parentId === event.parentId;
3177
+ const differentParent = failure.parentId !== void 0 && event.parentId !== void 0 && failure.parentId !== event.parentId;
3178
+ const sessionScoped = failureRun !== void 0 && eventRun !== void 0 && sameCorrelationScope(failureRun, eventRun);
3179
+ if (canonicalName(event) === failureName && failureAttempt !== void 0 && eventAttempt !== void 0 && eventAttempt > failureAttempt && !differentParent && (sameParent || sessionScoped || sameRun)) {
3180
+ candidates.push({
3181
+ event,
3182
+ basis: "attempt-progression",
3183
+ confidence: "correlated",
3184
+ ...event.runId !== failure.runId ? { viaRunId: event.runId } : {}
3185
+ });
3186
+ }
3187
+ }
3188
+ const byId = /* @__PURE__ */ new Map();
3189
+ for (const candidate of candidates) {
3190
+ const prev = byId.get(candidate.event.eventId);
3191
+ if (!prev || prev.confidence !== "explicit" && candidate.confidence === "explicit") {
3192
+ byId.set(candidate.event.eventId, candidate);
3193
+ }
3194
+ }
3195
+ return [...byId.values()].sort((a, b) => compareEventOrder(a.event, b.event));
3196
+ }
3197
+ function classifyFailure(failure, candidates, runs, logicalEvents) {
3198
+ const successful = candidates.filter((c) => isSuccessful(c.event));
3199
+ const unsuccessful = candidates.filter((c) => !isSuccessful(c.event));
3200
+ const retryRunIds = Object.freeze(
3201
+ [...new Set(candidates.map((c) => c.viaRunId).filter((id) => id !== void 0))].sort(
3202
+ (a, b) => a.localeCompare(b)
3203
+ )
3204
+ );
3205
+ if (successful.length > 1) {
3206
+ const distinctRuns = new Set(successful.map((c) => c.event.runId));
3207
+ const distinctParents = new Set(
3208
+ successful.map((c) => c.event.parentId ?? "").filter((id) => id !== "")
3209
+ );
3210
+ if (distinctRuns.size > 1 || distinctParents.size > 1) {
3211
+ return {
3212
+ eventId: failure.eventId,
3213
+ runId: failure.runId,
3214
+ name: failure.name,
3215
+ kind: failure.kind,
3216
+ role: "unknown",
3217
+ confidence: "unknown",
3218
+ basis: Object.freeze(["ambiguous-recovery-candidates"]),
3219
+ recoveryEventIds: Object.freeze(
3220
+ successful.map((c) => c.event.eventId).sort((a, b) => a.localeCompare(b))
3221
+ ),
3222
+ retryRunIds
3223
+ };
3224
+ }
3225
+ }
3226
+ if (successful.length >= 1) {
3227
+ const best = successful[0];
3228
+ return {
3229
+ eventId: failure.eventId,
3230
+ runId: failure.runId,
3231
+ name: failure.name,
3232
+ kind: failure.kind,
3233
+ role: "recovered",
3234
+ confidence: best.confidence,
3235
+ basis: Object.freeze([best.basis]),
3236
+ recoveryEventIds: Object.freeze(
3237
+ successful.map((c) => c.event.eventId).sort((a, b) => a.localeCompare(b))
3238
+ ),
3239
+ retryRunIds
3240
+ };
3241
+ }
3242
+ if (candidates.length > 0) {
3243
+ const best = candidates[0];
3244
+ return {
3245
+ eventId: failure.eventId,
3246
+ runId: failure.runId,
3247
+ name: failure.name,
3248
+ kind: failure.kind,
3249
+ role: "transient",
3250
+ confidence: best.confidence,
3251
+ basis: Object.freeze([
3252
+ best.basis,
3253
+ unsuccessful.some((c) => c.event.status === void 0) ? "retry-incomplete" : "retry-without-success"
3254
+ ]),
3255
+ recoveryEventIds: Object.freeze([]),
3256
+ retryRunIds
3257
+ };
3258
+ }
3259
+ const failureMeta = eventMetadata(failure);
3260
+ const declaredSuccessor = pickString2(failureMeta, [
3261
+ "retriedBy",
3262
+ "nextRetryRunId",
3263
+ "retryRunId"
3264
+ ]);
3265
+ if (declaredSuccessor !== void 0 && !runs.has(declaredSuccessor)) {
3266
+ return {
3267
+ eventId: failure.eventId,
3268
+ runId: failure.runId,
3269
+ name: failure.name,
3270
+ kind: failure.kind,
3271
+ role: "transient",
3272
+ confidence: "explicit",
3273
+ basis: Object.freeze(["retry-declared", "retry-run-missing"]),
3274
+ recoveryEventIds: Object.freeze([]),
3275
+ retryRunIds: Object.freeze([declaredSuccessor])
3276
+ };
3277
+ }
3278
+ for (const run of runs.values()) {
3279
+ if (run.retryOf === failure.runId) {
3280
+ return {
3281
+ eventId: failure.eventId,
3282
+ runId: failure.runId,
3283
+ name: failure.name,
3284
+ kind: failure.kind,
3285
+ role: "transient",
3286
+ confidence: "explicit",
3287
+ basis: Object.freeze(["retryOf", "retry-run-missing-or-empty"]),
3288
+ recoveryEventIds: Object.freeze([]),
3289
+ retryRunIds: Object.freeze([run.runId])
3290
+ };
3291
+ }
3292
+ }
3293
+ const failureRun = runs.get(failure.runId);
3294
+ const hasSuccessorDeclared = [...runs.values()].some((run) => run.retryOf === failure.runId);
3295
+ const isFinalInChain = failureRun !== void 0 && !hasSuccessorDeclared && (failureRun.retryOf !== void 0 || failureRun.attempt !== void 0 && failureRun.attempt > 1 || pickNumber(eventMetadata(failure), ["attempt"]) !== void 0);
3296
+ if (isFinalInChain && failureRun?.status === "error" && !logicalEvents.some(
3297
+ (event) => event.runId === failure.runId && event.eventId !== failure.eventId && isSuccessful(event) && canonicalName(event) === canonicalName(failure)
3298
+ )) {
3299
+ return {
3300
+ eventId: failure.eventId,
3301
+ runId: failure.runId,
3302
+ name: failure.name,
3303
+ kind: failure.kind,
3304
+ role: "terminal",
3305
+ confidence: failureRun.retryOf !== void 0 ? "explicit" : "correlated",
3306
+ basis: Object.freeze(["final-retry-chain-member", "enclosing-run-error"]),
3307
+ recoveryEventIds: Object.freeze([]),
3308
+ retryRunIds: Object.freeze(
3309
+ failureRun.retryOf !== void 0 ? [failureRun.retryOf] : []
3310
+ )
3311
+ };
3312
+ }
3313
+ return {
3314
+ eventId: failure.eventId,
3315
+ runId: failure.runId,
3316
+ name: failure.name,
3317
+ kind: failure.kind,
3318
+ role: "unknown",
3319
+ confidence: "unknown",
3320
+ basis: Object.freeze(["no-explicit-or-correlated-recovery"]),
3321
+ recoveryEventIds: Object.freeze([]),
3322
+ retryRunIds: Object.freeze([])
3323
+ };
3324
+ }
3325
+ function deriveFailureFacts(logicalEvents) {
3326
+ const runs = buildRunContexts(logicalEvents);
3327
+ const failures = logicalEvents.filter((event) => isFailure(event)).sort(compareEventOrder);
3328
+ const failureFacts = failures.map(
3329
+ (failure) => classifyFailure(failure, collectCandidates(failure, logicalEvents, runs), runs, logicalEvents)
3330
+ );
3331
+ const byRole = /* @__PURE__ */ new Map([
3332
+ ["transient", []],
3333
+ ["recovered", []],
3334
+ ["terminal", []],
3335
+ ["unknown", []]
3336
+ ]);
3337
+ for (const fact of failureFacts) {
3338
+ byRole.get(fact.role).push(fact);
3339
+ }
3340
+ for (const [role, list] of byRole) {
3341
+ byRole.set(
3342
+ role,
3343
+ Object.freeze(
3344
+ [...list].sort((a, b) => {
3345
+ const byRun = a.runId.localeCompare(b.runId);
3346
+ if (byRun !== 0) return byRun;
3347
+ return a.eventId.localeCompare(b.eventId);
3348
+ })
3349
+ )
3350
+ );
3351
+ }
3352
+ const failureRoleCounts = {
3353
+ transient: byRole.get("transient").length,
3354
+ recovered: byRole.get("recovered").length,
3355
+ terminal: byRole.get("terminal").length,
3356
+ unknown: byRole.get("unknown").length
3357
+ };
3358
+ return {
3359
+ failureFacts: Object.freeze(failureFacts),
3360
+ failuresByRole: byRole,
3361
+ failureRoleCounts
3362
+ };
3363
+ }
3364
+
3006
3365
  // packages/core/src/checks/trace-facts.ts
3007
3366
  function summarizeSemanticParity(events) {
3008
3367
  const projection = projectLogicalEvents(events);
@@ -3013,6 +3372,7 @@ function summarizeSemanticParity(events) {
3013
3372
  const finishedToolNames = Object.freeze(
3014
3373
  finishedTools.map((event) => resolveCanonicalToolName(event)).sort((a, b) => a.localeCompare(b))
3015
3374
  );
3375
+ const derived = deriveFailureFacts(logical);
3016
3376
  return {
3017
3377
  rawEventCount: events.length,
3018
3378
  logicalEventCount: logical.length,
@@ -3023,7 +3383,8 @@ function summarizeSemanticParity(events) {
3023
3383
  parentRemapCount: projection.diagnostics.filter(
3024
3384
  (item) => item.code === "AI_LOGICAL_PARENT_REMAPPED"
3025
3385
  ).length,
3026
- diagnostics: projection.diagnostics
3386
+ diagnostics: projection.diagnostics,
3387
+ failureRoleCounts: derived.failureRoleCounts
3027
3388
  };
3028
3389
  }
3029
3390
  var TRACE_FACTS_INPUT_NOT_NORMALIZED = formatProgrammaticDiagnostic(
@@ -3086,6 +3447,8 @@ function buildTraceFacts(input) {
3086
3447
  for (const [name, list] of [...toolsByName.entries()]) {
3087
3448
  toolsByName.set(name, Object.freeze([...list]));
3088
3449
  }
3450
+ const derived = deriveFailureFacts(projection.logicalEvents);
3451
+ const summary = summarizeSemanticParity(events);
3089
3452
  return {
3090
3453
  rawEvents: Object.freeze([...events]),
3091
3454
  logicalEvents: projection.logicalEvents,
@@ -3093,7 +3456,12 @@ function buildTraceFacts(input) {
3093
3456
  toolsByName,
3094
3457
  llmEvents: Object.freeze(llmEvents),
3095
3458
  outcomeEvents: Object.freeze(outcomeEvents),
3096
- summary: summarizeSemanticParity(events)
3459
+ summary: {
3460
+ ...summary,
3461
+ failureRoleCounts: derived.failureRoleCounts
3462
+ },
3463
+ failureFacts: derived.failureFacts,
3464
+ failuresByRole: derived.failuresByRole
3097
3465
  };
3098
3466
  }
3099
3467
 
@@ -3419,7 +3787,7 @@ function failFinding(ruleId, message, evidence, expected, actual, meta) {
3419
3787
  function semanticEvents(context) {
3420
3788
  return context.logicalEvents ?? context.events;
3421
3789
  }
3422
- function isRecord7(value) {
3790
+ function isRecord8(value) {
3423
3791
  return typeof value === "object" && value !== null && !Array.isArray(value);
3424
3792
  }
3425
3793
  function normalizedKey(value) {
@@ -3450,7 +3818,7 @@ function pushValueEntries(entries, event, value, path17, key, depth = 0) {
3450
3818
  }
3451
3819
  return;
3452
3820
  }
3453
- if (!isRecord7(value)) return;
3821
+ if (!isRecord8(value)) return;
3454
3822
  for (const nestedKey of Object.keys(value).sort((a, b) => a.localeCompare(b))) {
3455
3823
  pushValueEntries(
3456
3824
  entries,
@@ -3698,7 +4066,7 @@ function createSafetyOversizedAttributeRule(options) {
3698
4066
  )
3699
4067
  );
3700
4068
  }
3701
- if (isRecord7(entry.value) && options.maxObjectKeys !== void 0 && Object.keys(entry.value).length > options.maxObjectKeys) {
4069
+ if (isRecord8(entry.value) && options.maxObjectKeys !== void 0 && Object.keys(entry.value).length > options.maxObjectKeys) {
3702
4070
  findings.push(
3703
4071
  failFinding(
3704
4072
  "safety.oversizedAttribute",
@@ -3816,14 +4184,14 @@ function runTraceChecks(input, options = {}) {
3816
4184
  }
3817
4185
 
3818
4186
  // packages/core/src/persisted/token-usage.ts
3819
- function isRecord8(value) {
4187
+ function isRecord9(value) {
3820
4188
  return typeof value === "object" && value !== null && !Array.isArray(value);
3821
4189
  }
3822
4190
  function nonNegativeFinite(value) {
3823
4191
  return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : void 0;
3824
4192
  }
3825
4193
  function normalizeTokenUsage(value) {
3826
- if (!isRecord8(value)) return void 0;
4194
+ if (!isRecord9(value)) return void 0;
3827
4195
  const input = nonNegativeFinite(value.input);
3828
4196
  const output = nonNegativeFinite(value.output);
3829
4197
  const suppliedTotal = nonNegativeFinite(value.total);
@@ -4704,7 +5072,7 @@ function persistedEventsForParsedTrace(parsed) {
4704
5072
  sourceName: "agent-inspect-jsonl-reader"
4705
5073
  });
4706
5074
  }
4707
- function isRecord9(value) {
5075
+ function isRecord10(value) {
4708
5076
  return typeof value === "object" && value !== null && !Array.isArray(value);
4709
5077
  }
4710
5078
  function isNonEmptyString3(value) {
@@ -4719,13 +5087,13 @@ function readStringField(record, keys) {
4719
5087
  }
4720
5088
  function readRecordField(record, key) {
4721
5089
  const value = record[key];
4722
- return isRecord9(value) ? value : void 0;
5090
+ return isRecord10(value) ? value : void 0;
4723
5091
  }
4724
5092
  function parseJsonDocument(content) {
4725
5093
  return JSON.parse(content);
4726
5094
  }
4727
5095
  function looksLikeOpenInferenceSpan(value) {
4728
- if (!isRecord9(value)) return false;
5096
+ if (!isRecord10(value)) return false;
4729
5097
  const attributes = readRecordField(value, "attributes");
4730
5098
  return readStringField(value, ["trace_id", "traceId"]) !== void 0 && readStringField(value, ["span_id", "spanId"]) !== void 0 && (readStringField(value, ["name"]) !== void 0 || attributes?.["openinference.span.kind"] !== void 0);
4731
5099
  }
@@ -4750,7 +5118,7 @@ function extractOpenInferenceDocument(root) {
4750
5118
  unsupportedFields
4751
5119
  };
4752
5120
  }
4753
- if (!isRecord9(root)) return void 0;
5121
+ if (!isRecord10(root)) return void 0;
4754
5122
  const rootFormat = root.format;
4755
5123
  const rootCompatibility = root.compatibility;
4756
5124
  const version = typeof root.version === "string" && root.version.trim() !== "" ? root.version : void 0;
@@ -4890,7 +5258,7 @@ function summarizeAttributeValue(value) {
4890
5258
  if (Array.isArray(value)) {
4891
5259
  return { type: "array", length: value.length };
4892
5260
  }
4893
- if (isRecord9(value)) {
5261
+ if (isRecord10(value)) {
4894
5262
  return { type: "object", keyCount: Object.keys(value).length };
4895
5263
  }
4896
5264
  if (value === null) {
@@ -4977,7 +5345,7 @@ function mapOpenInferenceKind(span, attributes, pathPrefix) {
4977
5345
  }
4978
5346
  }
4979
5347
  function mapOpenInferenceStatus(status) {
4980
- if (!isRecord9(status)) return void 0;
5348
+ if (!isRecord10(status)) return void 0;
4981
5349
  const rawCode = status.code;
4982
5350
  if (typeof rawCode !== "string") return void 0;
4983
5351
  switch (rawCode.toUpperCase()) {
@@ -5077,7 +5445,7 @@ function mapOpenInferenceSpan(span, index, version) {
5077
5445
  warnings.push(...kindWarnings);
5078
5446
  const status = mapOpenInferenceStatus(span.status);
5079
5447
  const tokenUsage = readOpenInferenceTokenUsage(rawAttributes);
5080
- const errorMessage = isRecord9(span.status) && typeof span.status.message === "string" ? span.status.message : void 0;
5448
+ const errorMessage = isRecord10(span.status) && typeof span.status.message === "string" ? span.status.message : void 0;
5081
5449
  const event = {
5082
5450
  schemaVersion: "0.2",
5083
5451
  eventId: typeof rawAttributes["agent_inspect.event_id"] === "string" ? rawAttributes["agent_inspect.event_id"] : spanId,
@@ -5223,7 +5591,7 @@ var openInferenceJsonReader = {
5223
5591
  }
5224
5592
  };
5225
5593
  function parseOtlpAnyValue(value, field, warnings, unsupportedFields) {
5226
- if (!isRecord9(value)) {
5594
+ if (!isRecord10(value)) {
5227
5595
  unsupportedFields.push(field);
5228
5596
  warnings.push({
5229
5597
  code: "otlp_attribute_value_invalid",
@@ -5245,15 +5613,15 @@ function parseOtlpAnyValue(value, field, warnings, unsupportedFields) {
5245
5613
  if (typeof value.doubleValue === "number" && Number.isFinite(value.doubleValue)) {
5246
5614
  return value.doubleValue;
5247
5615
  }
5248
- if (isRecord9(value.arrayValue) && Array.isArray(value.arrayValue.values)) {
5616
+ if (isRecord10(value.arrayValue) && Array.isArray(value.arrayValue.values)) {
5249
5617
  return value.arrayValue.values.map(
5250
5618
  (item, index) => parseOtlpAnyValue(item, `${field}.arrayValue.values[${index}]`, warnings, unsupportedFields)
5251
5619
  );
5252
5620
  }
5253
- if (isRecord9(value.kvlistValue) && Array.isArray(value.kvlistValue.values)) {
5621
+ if (isRecord10(value.kvlistValue) && Array.isArray(value.kvlistValue.values)) {
5254
5622
  const out = {};
5255
5623
  for (const [index, item] of value.kvlistValue.values.entries()) {
5256
- if (!isRecord9(item) || typeof item.key !== "string") {
5624
+ if (!isRecord10(item) || typeof item.key !== "string") {
5257
5625
  unsupportedFields.push(`${field}.kvlistValue.values[${index}]`);
5258
5626
  continue;
5259
5627
  }
@@ -5304,7 +5672,7 @@ function parseOtlpAttributes(value, pathPrefix) {
5304
5672
  }
5305
5673
  for (const [index, item] of value.entries()) {
5306
5674
  const field = `${pathPrefix}[${index}]`;
5307
- if (!isRecord9(item) || typeof item.key !== "string") {
5675
+ if (!isRecord10(item) || typeof item.key !== "string") {
5308
5676
  unsupportedFields.push(field);
5309
5677
  warnings.push({
5310
5678
  code: "otlp_attribute_invalid",
@@ -5327,16 +5695,16 @@ function parseOtlpAttributes(value, pathPrefix) {
5327
5695
  return { attributes, warnings, unsupportedFields };
5328
5696
  }
5329
5697
  function looksLikeOtlpSpan(value) {
5330
- return isRecord9(value) && readStringField(value, ["traceId"]) !== void 0 && readStringField(value, ["spanId"]) !== void 0 && readStringField(value, ["name"]) !== void 0;
5698
+ return isRecord10(value) && readStringField(value, ["traceId"]) !== void 0 && readStringField(value, ["spanId"]) !== void 0 && readStringField(value, ["name"]) !== void 0;
5331
5699
  }
5332
5700
  function extractOtlpDocument(root) {
5333
- if (!isRecord9(root) || !Array.isArray(root.resourceSpans)) return void 0;
5701
+ if (!isRecord10(root) || !Array.isArray(root.resourceSpans)) return void 0;
5334
5702
  const spans = [];
5335
5703
  const warnings = [];
5336
5704
  const unsupportedFields = [];
5337
5705
  for (const [resourceIndex, resourceSpan] of root.resourceSpans.entries()) {
5338
5706
  const resourcePath = `resourceSpans[${resourceIndex}]`;
5339
- if (!isRecord9(resourceSpan)) {
5707
+ if (!isRecord10(resourceSpan)) {
5340
5708
  unsupportedFields.push(resourcePath);
5341
5709
  continue;
5342
5710
  }
@@ -5359,7 +5727,7 @@ function extractOtlpDocument(root) {
5359
5727
  }
5360
5728
  for (const [scopeIndex, scopeSpan] of resourceSpan.scopeSpans.entries()) {
5361
5729
  const scopePath = `${resourcePath}.scopeSpans[${scopeIndex}]`;
5362
- if (!isRecord9(scopeSpan)) {
5730
+ if (!isRecord10(scopeSpan)) {
5363
5731
  unsupportedFields.push(scopePath);
5364
5732
  continue;
5365
5733
  }
@@ -5426,7 +5794,7 @@ function extractOtlpDocument(root) {
5426
5794
  };
5427
5795
  }
5428
5796
  function mapOtlpStatus(status) {
5429
- if (!isRecord9(status)) return void 0;
5797
+ if (!isRecord10(status)) return void 0;
5430
5798
  const rawCode = status.code;
5431
5799
  if (typeof rawCode !== "string") return void 0;
5432
5800
  switch (rawCode.toUpperCase()) {
@@ -5526,7 +5894,7 @@ function mapOtlpEvents(value, pathPrefix) {
5526
5894
  const events = [];
5527
5895
  for (const [index, event] of value.entries()) {
5528
5896
  const eventPath = `${pathPrefix}[${index}]`;
5529
- if (!isRecord9(event)) {
5897
+ if (!isRecord10(event)) {
5530
5898
  unsupportedFields.push(eventPath);
5531
5899
  continue;
5532
5900
  }
@@ -5664,7 +6032,7 @@ function mapOtlpSpan(context) {
5664
6032
  warnings.push(...kindWarnings);
5665
6033
  const status = mapOtlpStatus(span.status);
5666
6034
  const tokenUsage = readOtlpTokenUsage(parsedSpanAttributes.attributes);
5667
- const errorMessage = isRecord9(span.status) && typeof span.status.message === "string" ? span.status.message : void 0;
6035
+ const errorMessage = isRecord10(span.status) && typeof span.status.message === "string" ? span.status.message : void 0;
5668
6036
  const event = {
5669
6037
  schemaVersion: "0.2",
5670
6038
  eventId: typeof parsedSpanAttributes.attributes["agent_inspect.event_id"] === "string" ? parsedSpanAttributes.attributes["agent_inspect.event_id"] : spanId,
@@ -6015,7 +6383,7 @@ function openTrace(input, options = {}) {
6015
6383
  var EXPORT_PAYLOAD_VERSION = "0.1.2";
6016
6384
 
6017
6385
  // packages/core/src/exporters/redact-export.ts
6018
- function isRecord10(value) {
6386
+ function isRecord11(value) {
6019
6387
  return typeof value === "object" && value !== null && !Array.isArray(value);
6020
6388
  }
6021
6389
  function deepClone(value) {
@@ -6089,7 +6457,7 @@ function redactEventAttributes(attrs, redactor, maxMetadataValueLength, maxPrevi
6089
6457
  0
6090
6458
  );
6091
6459
  const err = bounded.error;
6092
- if (isRecord10(err) && typeof err.message === "string") {
6460
+ if (isRecord11(err) && typeof err.message === "string") {
6093
6461
  bounded.error = {
6094
6462
  ...err,
6095
6463
  message: truncateStringForProfile(
@@ -6814,7 +7182,7 @@ var STRICT_PROFILE_EXTRA_KEYS2 = [
6814
7182
  "retrieval",
6815
7183
  "query"
6816
7184
  ];
6817
- function isRecord11(value) {
7185
+ function isRecord12(value) {
6818
7186
  return typeof value === "object" && value !== null && !Array.isArray(value);
6819
7187
  }
6820
7188
  function toKey2(key) {
@@ -7194,7 +7562,7 @@ var Redactor2 = class {
7194
7562
  });
7195
7563
  return out;
7196
7564
  }
7197
- if (isRecord11(value)) {
7565
+ if (isRecord12(value)) {
7198
7566
  if (state.seen.has(value)) return state.seen.get(value);
7199
7567
  const out = {};
7200
7568
  state.seen.set(value, out);
@@ -7613,7 +7981,18 @@ async function callReadOnlyTool(context, name, args = {}) {
7613
7981
  toolNames: [...facts.toolsByName.keys()].sort((a, b) => a.localeCompare(b)),
7614
7982
  llmCount: facts.llmEvents.length,
7615
7983
  outcomeCount: facts.outcomeEvents.length,
7616
- note: "Bounded TraceFacts summary only; raw events and prompts are not included."
7984
+ failureRoleCounts: facts.summary.failureRoleCounts ?? {
7985
+ transient: 0,
7986
+ recovered: 0,
7987
+ terminal: 0,
7988
+ unknown: 0
7989
+ },
7990
+ failureFactIds: facts.failureFacts.map((fact) => ({
7991
+ eventId: fact.eventId,
7992
+ role: fact.role,
7993
+ confidence: fact.confidence
7994
+ })),
7995
+ note: "Bounded TraceFacts summary only; raw events, prompts, and error bodies are not included. Failure roles are derived classifications over recorded evidence."
7617
7996
  },
7618
7997
  context
7619
7998
  );