@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.
@@ -1150,9 +1150,63 @@ async function extractMetadata(filePath, _quickScan) {
1150
1150
  createdAt: stats.birthtime
1151
1151
  };
1152
1152
  }
1153
+ var ROOT_STEP_DEPTH = 0;
1154
+ var MAX_RUN_SUMMARY_DEPTH = 1e3;
1153
1155
  function isNonNegativeFiniteNumber(value) {
1154
1156
  return typeof value === "number" && Number.isFinite(value) && value >= 0;
1155
1157
  }
1158
+ function resolveParentStepId(step, steps) {
1159
+ const parentId = step.parentId;
1160
+ if (typeof parentId !== "string" || parentId.trim() === "") {
1161
+ return void 0;
1162
+ }
1163
+ return steps.has(parentId) ? parentId : void 0;
1164
+ }
1165
+ function computeStepDepth(stepId, steps, depthCache) {
1166
+ const cached = depthCache.get(stepId);
1167
+ if (cached !== void 0) return cached;
1168
+ const ancestry = [];
1169
+ const ancestryIndexes = /* @__PURE__ */ new Map();
1170
+ let currentStepId = stepId;
1171
+ let resolvedDepth;
1172
+ while (resolvedDepth === void 0) {
1173
+ const cachedDepth = depthCache.get(currentStepId);
1174
+ if (cachedDepth !== void 0) {
1175
+ resolvedDepth = cachedDepth;
1176
+ continue;
1177
+ }
1178
+ const cycleStart = ancestryIndexes.get(currentStepId);
1179
+ if (cycleStart !== void 0) {
1180
+ const cycleStepIds = ancestry.splice(cycleStart);
1181
+ for (const cycleStepId of cycleStepIds) {
1182
+ depthCache.set(cycleStepId, ROOT_STEP_DEPTH);
1183
+ }
1184
+ resolvedDepth = ROOT_STEP_DEPTH;
1185
+ continue;
1186
+ }
1187
+ const currentStep = steps.get(currentStepId);
1188
+ if (!currentStep) {
1189
+ resolvedDepth = ROOT_STEP_DEPTH;
1190
+ continue;
1191
+ }
1192
+ ancestryIndexes.set(currentStepId, ancestry.length);
1193
+ ancestry.push(currentStepId);
1194
+ const parentStepId = resolveParentStepId(currentStep, steps);
1195
+ if (parentStepId === void 0) {
1196
+ ancestry.pop();
1197
+ depthCache.set(currentStepId, ROOT_STEP_DEPTH);
1198
+ resolvedDepth = ROOT_STEP_DEPTH;
1199
+ continue;
1200
+ }
1201
+ currentStepId = parentStepId;
1202
+ }
1203
+ ancestry.reverse();
1204
+ for (const ancestorStepId of ancestry) {
1205
+ resolvedDepth = Math.min(MAX_RUN_SUMMARY_DEPTH, resolvedDepth + 1);
1206
+ depthCache.set(ancestorStepId, resolvedDepth);
1207
+ }
1208
+ return depthCache.get(stepId) ?? ROOT_STEP_DEPTH;
1209
+ }
1156
1210
  function buildRunSummary(events) {
1157
1211
  const started = events.find(
1158
1212
  (e) => e.event === "run_started"
@@ -1206,27 +1260,13 @@ function buildRunSummary(events) {
1206
1260
  let stepsWithKnownTotal = 0;
1207
1261
  let hasCachedTokens = false;
1208
1262
  const depthCache = /* @__PURE__ */ new Map();
1209
- const computeDepth = (stepId) => {
1210
- const cached = depthCache.get(stepId);
1211
- if (cached !== void 0) return cached;
1212
- const node = steps.get(stepId);
1213
- if (!node) return 0;
1214
- const parent = node.parentId;
1215
- if (typeof parent !== "string" || parent.trim() === "" || !steps.has(parent)) {
1216
- depthCache.set(stepId, 0);
1217
- return 0;
1218
- }
1219
- const d = Math.min(1e3, computeDepth(parent) + 1);
1220
- depthCache.set(stepId, d);
1221
- return d;
1222
- };
1223
1263
  for (const [id, s] of steps.entries()) {
1224
1264
  totalSteps += 1;
1225
1265
  if (s.type === "llm") llmSteps += 1;
1226
1266
  else if (s.type === "tool") toolSteps += 1;
1227
1267
  else logicSteps += 1;
1228
1268
  if (s.status === "error") errorSteps += 1;
1229
- const depth = computeDepth(id);
1269
+ const depth = computeStepDepth(id, steps, depthCache);
1230
1270
  if (depth > maxDepth) maxDepth = depth;
1231
1271
  if (typeof s.durationMs === "number" && Number.isFinite(s.durationMs)) {
1232
1272
  if (!longestStep || s.durationMs > longestStep.durationMs) {
@@ -2993,6 +3033,325 @@ function pickString(record, keys) {
2993
3033
  return void 0;
2994
3034
  }
2995
3035
 
3036
+ // packages/core/src/checks/derived-failure.ts
3037
+ function isRecord7(value) {
3038
+ return typeof value === "object" && value !== null && !Array.isArray(value);
3039
+ }
3040
+ function pickString2(record, keys) {
3041
+ if (!record) return void 0;
3042
+ for (const key of keys) {
3043
+ const value = record[key];
3044
+ if (typeof value === "string" && value.trim() !== "") return value;
3045
+ }
3046
+ return void 0;
3047
+ }
3048
+ function pickNumber(record, keys) {
3049
+ if (!record) return void 0;
3050
+ for (const key of keys) {
3051
+ const value = record[key];
3052
+ if (typeof value === "number" && Number.isFinite(value) && value > 0) {
3053
+ return value;
3054
+ }
3055
+ }
3056
+ return void 0;
3057
+ }
3058
+ function eventMetadata(event) {
3059
+ const attrs = isRecord7(event.attributes) ? event.attributes : void 0;
3060
+ const nested = attrs !== void 0 && isRecord7(attrs.metadata) ? attrs.metadata : void 0;
3061
+ return {
3062
+ ...attrs ?? {},
3063
+ ...nested ?? {}
3064
+ };
3065
+ }
3066
+ function canonicalName(event) {
3067
+ if (event.kind === "TOOL") return resolveCanonicalToolName(event);
3068
+ return event.name;
3069
+ }
3070
+ function linkKeys(event) {
3071
+ const meta = eventMetadata(event);
3072
+ const keys = [];
3073
+ for (const key of ["linkedStepId", "toolCallId", "mcpToolCallId"]) {
3074
+ const value = pickString2(meta, [key]);
3075
+ if (value !== void 0) keys.push(`${key}:${value}`);
3076
+ }
3077
+ const stepId = pickString2(meta, ["stepId"]);
3078
+ if (stepId !== void 0) keys.push(`stepId:${stepId}`);
3079
+ return keys;
3080
+ }
3081
+ function buildRunContexts(logicalEvents) {
3082
+ const byRun = /* @__PURE__ */ new Map();
3083
+ for (const event of logicalEvents) {
3084
+ const existing = byRun.get(event.runId) ?? {
3085
+ runId: event.runId,
3086
+ name: event.name
3087
+ };
3088
+ const meta = eventMetadata(event);
3089
+ if (event.kind === "RUN" || existing.name === event.runId) {
3090
+ existing.name = event.name || existing.name;
3091
+ }
3092
+ if (event.kind === "RUN" && event.status !== void 0 && event.status !== "running") {
3093
+ existing.status = event.status;
3094
+ }
3095
+ existing.retryOf ??= pickString2(meta, ["retryOf"]);
3096
+ existing.attempt ??= pickNumber(meta, ["attempt", "retryAttempt", "retryCount"]);
3097
+ existing.sessionId ??= pickString2(meta, ["sessionId", "conversationId"]);
3098
+ existing.groupId ??= pickString2(meta, ["groupId"]);
3099
+ existing.parentGroupId ??= pickString2(meta, ["parentGroupId"]);
3100
+ existing.fallbackOf ??= pickString2(meta, ["fallbackOf", "fallbackFrom"]);
3101
+ byRun.set(event.runId, existing);
3102
+ }
3103
+ return byRun;
3104
+ }
3105
+ function sameCorrelationScope(a, b) {
3106
+ if (a.sessionId && b.sessionId && a.sessionId === b.sessionId) return true;
3107
+ if (a.groupId && b.groupId && a.groupId === b.groupId) return true;
3108
+ if (a.parentGroupId && b.parentGroupId && a.parentGroupId === b.parentGroupId) {
3109
+ return true;
3110
+ }
3111
+ return false;
3112
+ }
3113
+ function isSuccessful(event) {
3114
+ return event.status === "ok";
3115
+ }
3116
+ function isFailure(event) {
3117
+ return event.status === "error";
3118
+ }
3119
+ function compareEventOrder(a, b) {
3120
+ const byTime = a.timestamp.localeCompare(b.timestamp);
3121
+ if (byTime !== 0) return byTime;
3122
+ return a.eventId.localeCompare(b.eventId);
3123
+ }
3124
+ function collectCandidates(failure, logicalEvents, runs) {
3125
+ const failureRun = runs.get(failure.runId);
3126
+ const failureLinks = new Set(linkKeys(failure));
3127
+ const failureName = canonicalName(failure);
3128
+ const failureAttempt = pickNumber(eventMetadata(failure), ["attempt", "retryAttempt", "retryCount"]) ?? failureRun?.attempt;
3129
+ const candidates = [];
3130
+ for (const event of logicalEvents) {
3131
+ if (event.eventId === failure.eventId) continue;
3132
+ if (event.status === "running") continue;
3133
+ const eventRun = runs.get(event.runId);
3134
+ const eventMeta = eventMetadata(event);
3135
+ const sameRun = event.runId === failure.runId;
3136
+ if (eventRun?.retryOf === failure.runId) {
3137
+ candidates.push({
3138
+ event,
3139
+ basis: "retryOf",
3140
+ confidence: "explicit",
3141
+ viaRunId: event.runId
3142
+ });
3143
+ continue;
3144
+ }
3145
+ if (eventRun?.fallbackOf === failure.runId || pickString2(eventMeta, ["fallbackOf", "fallbackFrom"]) === failure.runId) {
3146
+ candidates.push({
3147
+ event,
3148
+ basis: "fallbackOf",
3149
+ confidence: "explicit",
3150
+ viaRunId: event.runId
3151
+ });
3152
+ continue;
3153
+ }
3154
+ if (sameRun && compareEventOrder(failure, event) >= 0) continue;
3155
+ const eventLinks = linkKeys(event);
3156
+ const sharedLink = eventLinks.find((key) => failureLinks.has(key));
3157
+ if (sharedLink !== void 0) {
3158
+ candidates.push({
3159
+ event,
3160
+ basis: sharedLink.split(":")[0] ?? "linkedId",
3161
+ confidence: "explicit"
3162
+ });
3163
+ continue;
3164
+ }
3165
+ const eventAttempt = pickNumber(eventMeta, ["attempt", "retryAttempt", "retryCount"]) ?? eventRun?.attempt;
3166
+ const sameParent = failure.parentId !== void 0 && event.parentId !== void 0 && failure.parentId === event.parentId;
3167
+ const differentParent = failure.parentId !== void 0 && event.parentId !== void 0 && failure.parentId !== event.parentId;
3168
+ const sessionScoped = failureRun !== void 0 && eventRun !== void 0 && sameCorrelationScope(failureRun, eventRun);
3169
+ if (canonicalName(event) === failureName && failureAttempt !== void 0 && eventAttempt !== void 0 && eventAttempt > failureAttempt && !differentParent && (sameParent || sessionScoped || sameRun)) {
3170
+ candidates.push({
3171
+ event,
3172
+ basis: "attempt-progression",
3173
+ confidence: "correlated",
3174
+ ...event.runId !== failure.runId ? { viaRunId: event.runId } : {}
3175
+ });
3176
+ }
3177
+ }
3178
+ const byId = /* @__PURE__ */ new Map();
3179
+ for (const candidate of candidates) {
3180
+ const prev = byId.get(candidate.event.eventId);
3181
+ if (!prev || prev.confidence !== "explicit" && candidate.confidence === "explicit") {
3182
+ byId.set(candidate.event.eventId, candidate);
3183
+ }
3184
+ }
3185
+ return [...byId.values()].sort((a, b) => compareEventOrder(a.event, b.event));
3186
+ }
3187
+ function classifyFailure(failure, candidates, runs, logicalEvents) {
3188
+ const successful = candidates.filter((c) => isSuccessful(c.event));
3189
+ const unsuccessful = candidates.filter((c) => !isSuccessful(c.event));
3190
+ const retryRunIds = Object.freeze(
3191
+ [...new Set(candidates.map((c) => c.viaRunId).filter((id) => id !== void 0))].sort(
3192
+ (a, b) => a.localeCompare(b)
3193
+ )
3194
+ );
3195
+ if (successful.length > 1) {
3196
+ const distinctRuns = new Set(successful.map((c) => c.event.runId));
3197
+ const distinctParents = new Set(
3198
+ successful.map((c) => c.event.parentId ?? "").filter((id) => id !== "")
3199
+ );
3200
+ if (distinctRuns.size > 1 || distinctParents.size > 1) {
3201
+ return {
3202
+ eventId: failure.eventId,
3203
+ runId: failure.runId,
3204
+ name: failure.name,
3205
+ kind: failure.kind,
3206
+ role: "unknown",
3207
+ confidence: "unknown",
3208
+ basis: Object.freeze(["ambiguous-recovery-candidates"]),
3209
+ recoveryEventIds: Object.freeze(
3210
+ successful.map((c) => c.event.eventId).sort((a, b) => a.localeCompare(b))
3211
+ ),
3212
+ retryRunIds
3213
+ };
3214
+ }
3215
+ }
3216
+ if (successful.length >= 1) {
3217
+ const best = successful[0];
3218
+ return {
3219
+ eventId: failure.eventId,
3220
+ runId: failure.runId,
3221
+ name: failure.name,
3222
+ kind: failure.kind,
3223
+ role: "recovered",
3224
+ confidence: best.confidence,
3225
+ basis: Object.freeze([best.basis]),
3226
+ recoveryEventIds: Object.freeze(
3227
+ successful.map((c) => c.event.eventId).sort((a, b) => a.localeCompare(b))
3228
+ ),
3229
+ retryRunIds
3230
+ };
3231
+ }
3232
+ if (candidates.length > 0) {
3233
+ const best = candidates[0];
3234
+ return {
3235
+ eventId: failure.eventId,
3236
+ runId: failure.runId,
3237
+ name: failure.name,
3238
+ kind: failure.kind,
3239
+ role: "transient",
3240
+ confidence: best.confidence,
3241
+ basis: Object.freeze([
3242
+ best.basis,
3243
+ unsuccessful.some((c) => c.event.status === void 0) ? "retry-incomplete" : "retry-without-success"
3244
+ ]),
3245
+ recoveryEventIds: Object.freeze([]),
3246
+ retryRunIds
3247
+ };
3248
+ }
3249
+ const failureMeta = eventMetadata(failure);
3250
+ const declaredSuccessor = pickString2(failureMeta, [
3251
+ "retriedBy",
3252
+ "nextRetryRunId",
3253
+ "retryRunId"
3254
+ ]);
3255
+ if (declaredSuccessor !== void 0 && !runs.has(declaredSuccessor)) {
3256
+ return {
3257
+ eventId: failure.eventId,
3258
+ runId: failure.runId,
3259
+ name: failure.name,
3260
+ kind: failure.kind,
3261
+ role: "transient",
3262
+ confidence: "explicit",
3263
+ basis: Object.freeze(["retry-declared", "retry-run-missing"]),
3264
+ recoveryEventIds: Object.freeze([]),
3265
+ retryRunIds: Object.freeze([declaredSuccessor])
3266
+ };
3267
+ }
3268
+ for (const run of runs.values()) {
3269
+ if (run.retryOf === failure.runId) {
3270
+ return {
3271
+ eventId: failure.eventId,
3272
+ runId: failure.runId,
3273
+ name: failure.name,
3274
+ kind: failure.kind,
3275
+ role: "transient",
3276
+ confidence: "explicit",
3277
+ basis: Object.freeze(["retryOf", "retry-run-missing-or-empty"]),
3278
+ recoveryEventIds: Object.freeze([]),
3279
+ retryRunIds: Object.freeze([run.runId])
3280
+ };
3281
+ }
3282
+ }
3283
+ const failureRun = runs.get(failure.runId);
3284
+ const hasSuccessorDeclared = [...runs.values()].some((run) => run.retryOf === failure.runId);
3285
+ const isFinalInChain = failureRun !== void 0 && !hasSuccessorDeclared && (failureRun.retryOf !== void 0 || failureRun.attempt !== void 0 && failureRun.attempt > 1 || pickNumber(eventMetadata(failure), ["attempt"]) !== void 0);
3286
+ if (isFinalInChain && failureRun?.status === "error" && !logicalEvents.some(
3287
+ (event) => event.runId === failure.runId && event.eventId !== failure.eventId && isSuccessful(event) && canonicalName(event) === canonicalName(failure)
3288
+ )) {
3289
+ return {
3290
+ eventId: failure.eventId,
3291
+ runId: failure.runId,
3292
+ name: failure.name,
3293
+ kind: failure.kind,
3294
+ role: "terminal",
3295
+ confidence: failureRun.retryOf !== void 0 ? "explicit" : "correlated",
3296
+ basis: Object.freeze(["final-retry-chain-member", "enclosing-run-error"]),
3297
+ recoveryEventIds: Object.freeze([]),
3298
+ retryRunIds: Object.freeze(
3299
+ failureRun.retryOf !== void 0 ? [failureRun.retryOf] : []
3300
+ )
3301
+ };
3302
+ }
3303
+ return {
3304
+ eventId: failure.eventId,
3305
+ runId: failure.runId,
3306
+ name: failure.name,
3307
+ kind: failure.kind,
3308
+ role: "unknown",
3309
+ confidence: "unknown",
3310
+ basis: Object.freeze(["no-explicit-or-correlated-recovery"]),
3311
+ recoveryEventIds: Object.freeze([]),
3312
+ retryRunIds: Object.freeze([])
3313
+ };
3314
+ }
3315
+ function deriveFailureFacts(logicalEvents) {
3316
+ const runs = buildRunContexts(logicalEvents);
3317
+ const failures = logicalEvents.filter((event) => isFailure(event)).sort(compareEventOrder);
3318
+ const failureFacts = failures.map(
3319
+ (failure) => classifyFailure(failure, collectCandidates(failure, logicalEvents, runs), runs, logicalEvents)
3320
+ );
3321
+ const byRole = /* @__PURE__ */ new Map([
3322
+ ["transient", []],
3323
+ ["recovered", []],
3324
+ ["terminal", []],
3325
+ ["unknown", []]
3326
+ ]);
3327
+ for (const fact of failureFacts) {
3328
+ byRole.get(fact.role).push(fact);
3329
+ }
3330
+ for (const [role, list] of byRole) {
3331
+ byRole.set(
3332
+ role,
3333
+ Object.freeze(
3334
+ [...list].sort((a, b) => {
3335
+ const byRun = a.runId.localeCompare(b.runId);
3336
+ if (byRun !== 0) return byRun;
3337
+ return a.eventId.localeCompare(b.eventId);
3338
+ })
3339
+ )
3340
+ );
3341
+ }
3342
+ const failureRoleCounts = {
3343
+ transient: byRole.get("transient").length,
3344
+ recovered: byRole.get("recovered").length,
3345
+ terminal: byRole.get("terminal").length,
3346
+ unknown: byRole.get("unknown").length
3347
+ };
3348
+ return {
3349
+ failureFacts: Object.freeze(failureFacts),
3350
+ failuresByRole: byRole,
3351
+ failureRoleCounts
3352
+ };
3353
+ }
3354
+
2996
3355
  // packages/core/src/checks/trace-facts.ts
2997
3356
  function summarizeSemanticParity(events) {
2998
3357
  const projection = projectLogicalEvents(events);
@@ -3003,6 +3362,7 @@ function summarizeSemanticParity(events) {
3003
3362
  const finishedToolNames = Object.freeze(
3004
3363
  finishedTools.map((event) => resolveCanonicalToolName(event)).sort((a, b) => a.localeCompare(b))
3005
3364
  );
3365
+ const derived = deriveFailureFacts(logical);
3006
3366
  return {
3007
3367
  rawEventCount: events.length,
3008
3368
  logicalEventCount: logical.length,
@@ -3013,7 +3373,8 @@ function summarizeSemanticParity(events) {
3013
3373
  parentRemapCount: projection.diagnostics.filter(
3014
3374
  (item) => item.code === "AI_LOGICAL_PARENT_REMAPPED"
3015
3375
  ).length,
3016
- diagnostics: projection.diagnostics
3376
+ diagnostics: projection.diagnostics,
3377
+ failureRoleCounts: derived.failureRoleCounts
3017
3378
  };
3018
3379
  }
3019
3380
  var TRACE_FACTS_INPUT_NOT_NORMALIZED = formatProgrammaticDiagnostic(
@@ -3076,6 +3437,8 @@ function buildTraceFacts(input) {
3076
3437
  for (const [name, list] of [...toolsByName.entries()]) {
3077
3438
  toolsByName.set(name, Object.freeze([...list]));
3078
3439
  }
3440
+ const derived = deriveFailureFacts(projection.logicalEvents);
3441
+ const summary = summarizeSemanticParity(events);
3079
3442
  return {
3080
3443
  rawEvents: Object.freeze([...events]),
3081
3444
  logicalEvents: projection.logicalEvents,
@@ -3083,7 +3446,12 @@ function buildTraceFacts(input) {
3083
3446
  toolsByName,
3084
3447
  llmEvents: Object.freeze(llmEvents),
3085
3448
  outcomeEvents: Object.freeze(outcomeEvents),
3086
- summary: summarizeSemanticParity(events)
3449
+ summary: {
3450
+ ...summary,
3451
+ failureRoleCounts: derived.failureRoleCounts
3452
+ },
3453
+ failureFacts: derived.failureFacts,
3454
+ failuresByRole: derived.failuresByRole
3087
3455
  };
3088
3456
  }
3089
3457
 
@@ -3409,7 +3777,7 @@ function failFinding(ruleId, message, evidence, expected, actual, meta) {
3409
3777
  function semanticEvents(context) {
3410
3778
  return context.logicalEvents ?? context.events;
3411
3779
  }
3412
- function isRecord7(value) {
3780
+ function isRecord8(value) {
3413
3781
  return typeof value === "object" && value !== null && !Array.isArray(value);
3414
3782
  }
3415
3783
  function normalizedKey(value) {
@@ -3440,7 +3808,7 @@ function pushValueEntries(entries, event, value, path16, key, depth = 0) {
3440
3808
  }
3441
3809
  return;
3442
3810
  }
3443
- if (!isRecord7(value)) return;
3811
+ if (!isRecord8(value)) return;
3444
3812
  for (const nestedKey of Object.keys(value).sort((a, b) => a.localeCompare(b))) {
3445
3813
  pushValueEntries(
3446
3814
  entries,
@@ -3688,7 +4056,7 @@ function createSafetyOversizedAttributeRule(options) {
3688
4056
  )
3689
4057
  );
3690
4058
  }
3691
- if (isRecord7(entry.value) && options.maxObjectKeys !== void 0 && Object.keys(entry.value).length > options.maxObjectKeys) {
4059
+ if (isRecord8(entry.value) && options.maxObjectKeys !== void 0 && Object.keys(entry.value).length > options.maxObjectKeys) {
3692
4060
  findings.push(
3693
4061
  failFinding(
3694
4062
  "safety.oversizedAttribute",
@@ -3806,14 +4174,14 @@ function runTraceChecks(input, options = {}) {
3806
4174
  }
3807
4175
 
3808
4176
  // packages/core/src/persisted/token-usage.ts
3809
- function isRecord8(value) {
4177
+ function isRecord9(value) {
3810
4178
  return typeof value === "object" && value !== null && !Array.isArray(value);
3811
4179
  }
3812
4180
  function nonNegativeFinite(value) {
3813
4181
  return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : void 0;
3814
4182
  }
3815
4183
  function normalizeTokenUsage(value) {
3816
- if (!isRecord8(value)) return void 0;
4184
+ if (!isRecord9(value)) return void 0;
3817
4185
  const input = nonNegativeFinite(value.input);
3818
4186
  const output = nonNegativeFinite(value.output);
3819
4187
  const suppliedTotal = nonNegativeFinite(value.total);
@@ -4694,7 +5062,7 @@ function persistedEventsForParsedTrace(parsed) {
4694
5062
  sourceName: "agent-inspect-jsonl-reader"
4695
5063
  });
4696
5064
  }
4697
- function isRecord9(value) {
5065
+ function isRecord10(value) {
4698
5066
  return typeof value === "object" && value !== null && !Array.isArray(value);
4699
5067
  }
4700
5068
  function isNonEmptyString3(value) {
@@ -4709,13 +5077,13 @@ function readStringField(record, keys) {
4709
5077
  }
4710
5078
  function readRecordField(record, key) {
4711
5079
  const value = record[key];
4712
- return isRecord9(value) ? value : void 0;
5080
+ return isRecord10(value) ? value : void 0;
4713
5081
  }
4714
5082
  function parseJsonDocument(content) {
4715
5083
  return JSON.parse(content);
4716
5084
  }
4717
5085
  function looksLikeOpenInferenceSpan(value) {
4718
- if (!isRecord9(value)) return false;
5086
+ if (!isRecord10(value)) return false;
4719
5087
  const attributes = readRecordField(value, "attributes");
4720
5088
  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);
4721
5089
  }
@@ -4740,7 +5108,7 @@ function extractOpenInferenceDocument(root) {
4740
5108
  unsupportedFields
4741
5109
  };
4742
5110
  }
4743
- if (!isRecord9(root)) return void 0;
5111
+ if (!isRecord10(root)) return void 0;
4744
5112
  const rootFormat = root.format;
4745
5113
  const rootCompatibility = root.compatibility;
4746
5114
  const version = typeof root.version === "string" && root.version.trim() !== "" ? root.version : void 0;
@@ -4880,7 +5248,7 @@ function summarizeAttributeValue(value) {
4880
5248
  if (Array.isArray(value)) {
4881
5249
  return { type: "array", length: value.length };
4882
5250
  }
4883
- if (isRecord9(value)) {
5251
+ if (isRecord10(value)) {
4884
5252
  return { type: "object", keyCount: Object.keys(value).length };
4885
5253
  }
4886
5254
  if (value === null) {
@@ -4967,7 +5335,7 @@ function mapOpenInferenceKind(span, attributes, pathPrefix) {
4967
5335
  }
4968
5336
  }
4969
5337
  function mapOpenInferenceStatus(status) {
4970
- if (!isRecord9(status)) return void 0;
5338
+ if (!isRecord10(status)) return void 0;
4971
5339
  const rawCode = status.code;
4972
5340
  if (typeof rawCode !== "string") return void 0;
4973
5341
  switch (rawCode.toUpperCase()) {
@@ -5067,7 +5435,7 @@ function mapOpenInferenceSpan(span, index, version) {
5067
5435
  warnings.push(...kindWarnings);
5068
5436
  const status = mapOpenInferenceStatus(span.status);
5069
5437
  const tokenUsage = readOpenInferenceTokenUsage(rawAttributes);
5070
- const errorMessage = isRecord9(span.status) && typeof span.status.message === "string" ? span.status.message : void 0;
5438
+ const errorMessage = isRecord10(span.status) && typeof span.status.message === "string" ? span.status.message : void 0;
5071
5439
  const event = {
5072
5440
  schemaVersion: "0.2",
5073
5441
  eventId: typeof rawAttributes["agent_inspect.event_id"] === "string" ? rawAttributes["agent_inspect.event_id"] : spanId,
@@ -5213,7 +5581,7 @@ var openInferenceJsonReader = {
5213
5581
  }
5214
5582
  };
5215
5583
  function parseOtlpAnyValue(value, field, warnings, unsupportedFields) {
5216
- if (!isRecord9(value)) {
5584
+ if (!isRecord10(value)) {
5217
5585
  unsupportedFields.push(field);
5218
5586
  warnings.push({
5219
5587
  code: "otlp_attribute_value_invalid",
@@ -5235,15 +5603,15 @@ function parseOtlpAnyValue(value, field, warnings, unsupportedFields) {
5235
5603
  if (typeof value.doubleValue === "number" && Number.isFinite(value.doubleValue)) {
5236
5604
  return value.doubleValue;
5237
5605
  }
5238
- if (isRecord9(value.arrayValue) && Array.isArray(value.arrayValue.values)) {
5606
+ if (isRecord10(value.arrayValue) && Array.isArray(value.arrayValue.values)) {
5239
5607
  return value.arrayValue.values.map(
5240
5608
  (item, index) => parseOtlpAnyValue(item, `${field}.arrayValue.values[${index}]`, warnings, unsupportedFields)
5241
5609
  );
5242
5610
  }
5243
- if (isRecord9(value.kvlistValue) && Array.isArray(value.kvlistValue.values)) {
5611
+ if (isRecord10(value.kvlistValue) && Array.isArray(value.kvlistValue.values)) {
5244
5612
  const out = {};
5245
5613
  for (const [index, item] of value.kvlistValue.values.entries()) {
5246
- if (!isRecord9(item) || typeof item.key !== "string") {
5614
+ if (!isRecord10(item) || typeof item.key !== "string") {
5247
5615
  unsupportedFields.push(`${field}.kvlistValue.values[${index}]`);
5248
5616
  continue;
5249
5617
  }
@@ -5294,7 +5662,7 @@ function parseOtlpAttributes(value, pathPrefix) {
5294
5662
  }
5295
5663
  for (const [index, item] of value.entries()) {
5296
5664
  const field = `${pathPrefix}[${index}]`;
5297
- if (!isRecord9(item) || typeof item.key !== "string") {
5665
+ if (!isRecord10(item) || typeof item.key !== "string") {
5298
5666
  unsupportedFields.push(field);
5299
5667
  warnings.push({
5300
5668
  code: "otlp_attribute_invalid",
@@ -5317,16 +5685,16 @@ function parseOtlpAttributes(value, pathPrefix) {
5317
5685
  return { attributes, warnings, unsupportedFields };
5318
5686
  }
5319
5687
  function looksLikeOtlpSpan(value) {
5320
- return isRecord9(value) && readStringField(value, ["traceId"]) !== void 0 && readStringField(value, ["spanId"]) !== void 0 && readStringField(value, ["name"]) !== void 0;
5688
+ return isRecord10(value) && readStringField(value, ["traceId"]) !== void 0 && readStringField(value, ["spanId"]) !== void 0 && readStringField(value, ["name"]) !== void 0;
5321
5689
  }
5322
5690
  function extractOtlpDocument(root) {
5323
- if (!isRecord9(root) || !Array.isArray(root.resourceSpans)) return void 0;
5691
+ if (!isRecord10(root) || !Array.isArray(root.resourceSpans)) return void 0;
5324
5692
  const spans = [];
5325
5693
  const warnings = [];
5326
5694
  const unsupportedFields = [];
5327
5695
  for (const [resourceIndex, resourceSpan] of root.resourceSpans.entries()) {
5328
5696
  const resourcePath = `resourceSpans[${resourceIndex}]`;
5329
- if (!isRecord9(resourceSpan)) {
5697
+ if (!isRecord10(resourceSpan)) {
5330
5698
  unsupportedFields.push(resourcePath);
5331
5699
  continue;
5332
5700
  }
@@ -5349,7 +5717,7 @@ function extractOtlpDocument(root) {
5349
5717
  }
5350
5718
  for (const [scopeIndex, scopeSpan] of resourceSpan.scopeSpans.entries()) {
5351
5719
  const scopePath = `${resourcePath}.scopeSpans[${scopeIndex}]`;
5352
- if (!isRecord9(scopeSpan)) {
5720
+ if (!isRecord10(scopeSpan)) {
5353
5721
  unsupportedFields.push(scopePath);
5354
5722
  continue;
5355
5723
  }
@@ -5416,7 +5784,7 @@ function extractOtlpDocument(root) {
5416
5784
  };
5417
5785
  }
5418
5786
  function mapOtlpStatus(status) {
5419
- if (!isRecord9(status)) return void 0;
5787
+ if (!isRecord10(status)) return void 0;
5420
5788
  const rawCode = status.code;
5421
5789
  if (typeof rawCode !== "string") return void 0;
5422
5790
  switch (rawCode.toUpperCase()) {
@@ -5516,7 +5884,7 @@ function mapOtlpEvents(value, pathPrefix) {
5516
5884
  const events = [];
5517
5885
  for (const [index, event] of value.entries()) {
5518
5886
  const eventPath = `${pathPrefix}[${index}]`;
5519
- if (!isRecord9(event)) {
5887
+ if (!isRecord10(event)) {
5520
5888
  unsupportedFields.push(eventPath);
5521
5889
  continue;
5522
5890
  }
@@ -5654,7 +6022,7 @@ function mapOtlpSpan(context) {
5654
6022
  warnings.push(...kindWarnings);
5655
6023
  const status = mapOtlpStatus(span.status);
5656
6024
  const tokenUsage = readOtlpTokenUsage(parsedSpanAttributes.attributes);
5657
- const errorMessage = isRecord9(span.status) && typeof span.status.message === "string" ? span.status.message : void 0;
6025
+ const errorMessage = isRecord10(span.status) && typeof span.status.message === "string" ? span.status.message : void 0;
5658
6026
  const event = {
5659
6027
  schemaVersion: "0.2",
5660
6028
  eventId: typeof parsedSpanAttributes.attributes["agent_inspect.event_id"] === "string" ? parsedSpanAttributes.attributes["agent_inspect.event_id"] : spanId,
@@ -6005,7 +6373,7 @@ function openTrace(input, options = {}) {
6005
6373
  var EXPORT_PAYLOAD_VERSION = "0.1.2";
6006
6374
 
6007
6375
  // packages/core/src/exporters/redact-export.ts
6008
- function isRecord10(value) {
6376
+ function isRecord11(value) {
6009
6377
  return typeof value === "object" && value !== null && !Array.isArray(value);
6010
6378
  }
6011
6379
  function deepClone(value) {
@@ -6079,7 +6447,7 @@ function redactEventAttributes(attrs, redactor, maxMetadataValueLength, maxPrevi
6079
6447
  0
6080
6448
  );
6081
6449
  const err = bounded.error;
6082
- if (isRecord10(err) && typeof err.message === "string") {
6450
+ if (isRecord11(err) && typeof err.message === "string") {
6083
6451
  bounded.error = {
6084
6452
  ...err,
6085
6453
  message: truncateStringForProfile(
@@ -6804,7 +7172,7 @@ var STRICT_PROFILE_EXTRA_KEYS2 = [
6804
7172
  "retrieval",
6805
7173
  "query"
6806
7174
  ];
6807
- function isRecord11(value) {
7175
+ function isRecord12(value) {
6808
7176
  return typeof value === "object" && value !== null && !Array.isArray(value);
6809
7177
  }
6810
7178
  function toKey2(key) {
@@ -7184,7 +7552,7 @@ var Redactor2 = class {
7184
7552
  });
7185
7553
  return out;
7186
7554
  }
7187
- if (isRecord11(value)) {
7555
+ if (isRecord12(value)) {
7188
7556
  if (state.seen.has(value)) return state.seen.get(value);
7189
7557
  const out = {};
7190
7558
  state.seen.set(value, out);
@@ -7603,7 +7971,18 @@ async function callReadOnlyTool(context, name, args = {}) {
7603
7971
  toolNames: [...facts.toolsByName.keys()].sort((a, b) => a.localeCompare(b)),
7604
7972
  llmCount: facts.llmEvents.length,
7605
7973
  outcomeCount: facts.outcomeEvents.length,
7606
- note: "Bounded TraceFacts summary only; raw events and prompts are not included."
7974
+ failureRoleCounts: facts.summary.failureRoleCounts ?? {
7975
+ transient: 0,
7976
+ recovered: 0,
7977
+ terminal: 0,
7978
+ unknown: 0
7979
+ },
7980
+ failureFactIds: facts.failureFacts.map((fact) => ({
7981
+ eventId: fact.eventId,
7982
+ role: fact.role,
7983
+ confidence: fact.confidence
7984
+ })),
7985
+ note: "Bounded TraceFacts summary only; raw events, prompts, and error bodies are not included. Failure roles are derived classifications over recorded evidence."
7607
7986
  },
7608
7987
  context
7609
7988
  );
@@ -8053,5 +8432,5 @@ async function runReadOnlyMcpServer(options = {}) {
8053
8432
  }
8054
8433
 
8055
8434
  export { MCP_MAX_REQUEST_BYTES, MCP_PROTOCOL_VERSION, MCP_SERVER_INSTRUCTIONS, READ_ONLY_TOOLS, TRACE_DATA_UNTRUSTED_WARNING, callReadOnlyTool, createMcpServerContext, handleMcpProtocolLine, runReadOnlyMcpServer };
8056
- //# sourceMappingURL=chunk-FTUMVNQN.mjs.map
8057
- //# sourceMappingURL=chunk-FTUMVNQN.mjs.map
8435
+ //# sourceMappingURL=chunk-TVTJGGYV.mjs.map
8436
+ //# sourceMappingURL=chunk-TVTJGGYV.mjs.map