@agent-inspect/mcp-server 4.3.0 → 4.4.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.mjs CHANGED
@@ -70,6 +70,9 @@ function isTraceEvent(value) {
70
70
  case "step_completed": {
71
71
  return typeof value.runId === "string" && typeof value.stepId === "string" && (value.status === "success" || value.status === "error") && typeof value.endTime === "number" && typeof value.durationMs === "number";
72
72
  }
73
+ case "outcome_observed": {
74
+ return typeof value.runId === "string" && typeof value.outcomeId === "string" && typeof value.name === "string" && typeof value.expectation === "string" && (value.status === "passed" || value.status === "failed" || value.status === "unknown" || value.status === "skipped") && typeof value.observedAt === "number";
75
+ }
73
76
  default:
74
77
  return false;
75
78
  }
@@ -87,7 +90,8 @@ var INSPECT_KINDS = [
87
90
  "RESULT",
88
91
  "ERROR",
89
92
  "LOGIC",
90
- "LOG"
93
+ "LOG",
94
+ "OUTCOME"
91
95
  ];
92
96
  var ATTRIBUTION_CONFIDENCES = [
93
97
  "explicit",
@@ -379,6 +383,32 @@ function fromLegacyStepCompleted(event) {
379
383
  if (error) out.error = error;
380
384
  return out;
381
385
  }
386
+ function fromLegacyOutcomeObserved(event) {
387
+ const attrs = event.attributes ?? {};
388
+ const observedAtRaw = attrs.observedAt;
389
+ const observedAt = typeof observedAtRaw === "string" ? Date.parse(observedAtRaw) : typeof observedAtRaw === "number" && Number.isFinite(observedAtRaw) ? observedAtRaw : resolveTimes(event).timestamp;
390
+ const status = attrs.outcomeStatus;
391
+ const out = {
392
+ schemaVersion: "0.1",
393
+ event: "outcome_observed",
394
+ timestamp: observedAt,
395
+ runId: event.runId,
396
+ outcomeId: typeof attrs.outcomeId === "string" ? attrs.outcomeId : event.eventId,
397
+ name: event.name,
398
+ expectation: typeof attrs.expectation === "string" ? attrs.expectation : event.name,
399
+ status: status === "passed" || status === "failed" || status === "unknown" || status === "skipped" ? status : "unknown",
400
+ observedAt
401
+ };
402
+ if (event.parentId !== void 0) out.parentId = event.parentId;
403
+ if (typeof attrs.method === "string") out.method = attrs.method;
404
+ if (attrs.actual !== void 0) out.actual = attrs.actual;
405
+ if (event.outputSummary !== void 0) out.actual = event.outputSummary;
406
+ if (attrs.evidence !== void 0) out.evidence = attrs.evidence;
407
+ return out;
408
+ }
409
+ function fromNativeOutcome(event) {
410
+ return [fromLegacyOutcomeObserved(event)];
411
+ }
382
412
  function fromNativeRun(event) {
383
413
  const { timestamp, startTime, endTime } = resolveTimes(event);
384
414
  const runStatus = mapPersistedStatusToRunStatus(event.status);
@@ -466,9 +496,13 @@ function persistedInspectEventToTraceEvents(event) {
466
496
  if (legacyEvent === "run_completed") return [fromLegacyRunCompleted(event)];
467
497
  if (legacyEvent === "step_started") return [fromLegacyStepStarted(event)];
468
498
  if (legacyEvent === "step_completed") return [fromLegacyStepCompleted(event)];
499
+ if (legacyEvent === "outcome_observed") return [fromLegacyOutcomeObserved(event)];
469
500
  if (event.kind === "RUN") {
470
501
  return fromNativeRun(event);
471
502
  }
503
+ if (event.kind === "OUTCOME") {
504
+ return fromNativeOutcome(event);
505
+ }
472
506
  return fromNativeStep(event);
473
507
  }
474
508
  function persistedInspectEventsToTraceEvents(events, options) {
@@ -703,6 +737,9 @@ function validateEvent(event) {
703
737
  case "step_completed": {
704
738
  return nonEmptyString(event.runId) && nonEmptyString(event.stepId) && (event.status === "success" || event.status === "error") && finiteNumber(event.endTime) && finiteNumber(event.durationMs) && optionalErrorInfo(event.error);
705
739
  }
740
+ case "outcome_observed": {
741
+ return nonEmptyString(event.runId) && nonEmptyString(event.outcomeId) && nonEmptyString(event.name) && nonEmptyString(event.expectation) && (event.status === "passed" || event.status === "failed" || event.status === "unknown" || event.status === "skipped") && finiteNumber(event.observedAt);
742
+ }
706
743
  default:
707
744
  return false;
708
745
  }
@@ -722,6 +759,55 @@ async function readTraceEventsFromFile(filePath) {
722
759
 
723
760
  // packages/core/src/context.ts
724
761
  new AsyncLocalStorage();
762
+
763
+ // packages/core/src/outcomes/types.ts
764
+ var OBSERVED_OUTCOME_STATUSES = [
765
+ "passed",
766
+ "failed",
767
+ "unknown",
768
+ "skipped"
769
+ ];
770
+ var OUTCOME_LEGACY_EVENT = "outcome_observed";
771
+
772
+ // packages/core/src/outcomes/validate.ts
773
+ function parseObservedOutcomeStatus(value) {
774
+ const trimmed = value.trim().toLowerCase();
775
+ if (OBSERVED_OUTCOME_STATUSES.includes(trimmed)) {
776
+ return trimmed;
777
+ }
778
+ throw new Error(
779
+ `Unsupported observation status "${value}". Use passed, failed, unknown, or skipped.`
780
+ );
781
+ }
782
+
783
+ // packages/core/src/outcomes/extract.ts
784
+ function fromOutcomeObservedEvent(event) {
785
+ return {
786
+ outcomeId: event.outcomeId,
787
+ runId: event.runId,
788
+ ...event.parentId !== void 0 ? { parentId: event.parentId } : {},
789
+ name: event.name,
790
+ expectation: event.expectation,
791
+ status: event.status,
792
+ ...event.method !== void 0 ? { method: event.method } : {},
793
+ ...event.actual !== void 0 ? { actual: event.actual } : {},
794
+ ...event.evidence !== void 0 ? { evidence: event.evidence } : {},
795
+ observedAt: event.observedAt
796
+ };
797
+ }
798
+ function extractOutcomesFromTraceEvents(events) {
799
+ const out = [];
800
+ for (const event of events) {
801
+ if (event.event === OUTCOME_LEGACY_EVENT) {
802
+ out.push(fromOutcomeObservedEvent(event));
803
+ }
804
+ }
805
+ return out.sort((a, b) => a.observedAt - b.observedAt || a.name.localeCompare(b.name));
806
+ }
807
+ function parseObservationFilter(value) {
808
+ if (value === void 0 || value.trim() === "") return void 0;
809
+ return parseObservedOutcomeStatus(value);
810
+ }
725
811
  function resolveTraceDir(options = {}) {
726
812
  if (typeof options.dir === "string" && options.dir.trim() !== "") {
727
813
  return options.dir.trim();
@@ -1069,8 +1155,9 @@ async function searchTraces(metas, options) {
1069
1155
  }
1070
1156
  const limit = options.limit;
1071
1157
  const sessionId = options.session?.trim();
1158
+ const observationStatus = parseObservationFilter(options.observation);
1072
1159
  const hasContentFilter = Boolean(
1073
- options.status || stepTypeFilter || nameQuery || toolQuery || durationFilter
1160
+ options.status || stepTypeFilter || nameQuery || toolQuery || durationFilter || observationStatus
1074
1161
  );
1075
1162
  const results = [];
1076
1163
  const sessionLabel = sessionId && sessionId !== "" ? sessionId : void 0;
@@ -1115,6 +1202,22 @@ async function searchTraces(metas, options) {
1115
1202
  statusFilter: options.status
1116
1203
  });
1117
1204
  results.push(...stepMatches);
1205
+ if (observationStatus) {
1206
+ const outcomes = extractOutcomesFromTraceEvents(events);
1207
+ const matched = outcomes.filter((outcome) => outcome.status === observationStatus);
1208
+ for (const outcome of matched) {
1209
+ results.push({
1210
+ runId: m.runId,
1211
+ runName: m.name,
1212
+ runStatus: m.status,
1213
+ stepName: outcome.name,
1214
+ timestamp: outcome.observedAt,
1215
+ matchReason: `observation status=${outcome.status}`,
1216
+ matchedFields: ["outcome.status", "outcome.name"],
1217
+ filePath: m.filePath
1218
+ });
1219
+ }
1220
+ }
1118
1221
  }
1119
1222
  results.sort((a, b) => {
1120
1223
  const ta = a.timestamp ?? 0;
@@ -2137,6 +2240,8 @@ function nodeIdForEvent(event) {
2137
2240
  case "step_started":
2138
2241
  case "step_completed":
2139
2242
  return event.stepId;
2243
+ case "outcome_observed":
2244
+ return event.outcomeId;
2140
2245
  default:
2141
2246
  return "unknown";
2142
2247
  }
@@ -2320,6 +2425,39 @@ function traceEventToPersistedInspectEvent(event, options) {
2320
2425
  error
2321
2426
  };
2322
2427
  }
2428
+ case "outcome_observed": {
2429
+ const tsObserved = toIsoTimestamp(event.observedAt);
2430
+ const attributes = compactAttributes2({
2431
+ legacyEvent: "outcome_observed",
2432
+ outcomeId: event.outcomeId,
2433
+ outcomeStatus: event.status,
2434
+ expectation: event.expectation,
2435
+ method: event.method,
2436
+ actual: event.actual,
2437
+ evidence: event.evidence,
2438
+ observedAt: tsObserved.iso,
2439
+ invalidTimestamp: tsMain.invalidTimestamp || tsObserved.invalidTimestamp ? true : void 0
2440
+ });
2441
+ const out = {
2442
+ schemaVersion: "0.2",
2443
+ eventId,
2444
+ runId: event.runId,
2445
+ kind: "OUTCOME",
2446
+ name: event.name,
2447
+ status: event.status === "failed" ? "error" : "ok",
2448
+ timestamp: tsMain.iso,
2449
+ confidence: "explicit",
2450
+ source,
2451
+ attributes
2452
+ };
2453
+ if (event.parentId !== void 0) {
2454
+ out.parentId = event.parentId;
2455
+ }
2456
+ if (event.actual !== void 0) {
2457
+ out.outputSummary = event.actual;
2458
+ }
2459
+ return out;
2460
+ }
2323
2461
  default: {
2324
2462
  const _exhaustive = event;
2325
2463
  throw new Error(`Unsupported trace event: ${_exhaustive.event}`);
@@ -3049,7 +3187,7 @@ function sanitizeOpenInferenceAttributes(attributes, pathPrefix) {
3049
3187
  function mapOpenInferenceKind(span, attributes, pathPrefix) {
3050
3188
  const warnings = [];
3051
3189
  const agentInspectKind = attributes["agent_inspect.kind"];
3052
- if (agentInspectKind === "RUN" || agentInspectKind === "AGENT" || agentInspectKind === "LLM" || agentInspectKind === "TOOL" || agentInspectKind === "CHAIN" || agentInspectKind === "RETRIEVER" || agentInspectKind === "DECISION" || agentInspectKind === "RESULT" || agentInspectKind === "ERROR" || agentInspectKind === "LOGIC" || agentInspectKind === "LOG") {
3190
+ if (agentInspectKind === "RUN" || agentInspectKind === "AGENT" || agentInspectKind === "LLM" || agentInspectKind === "TOOL" || agentInspectKind === "CHAIN" || agentInspectKind === "RETRIEVER" || agentInspectKind === "DECISION" || agentInspectKind === "RESULT" || agentInspectKind === "ERROR" || agentInspectKind === "LOGIC" || agentInspectKind === "LOG" || agentInspectKind === "OUTCOME") {
3053
3191
  return { kind: agentInspectKind, warnings };
3054
3192
  }
3055
3193
  const rawKind = readStringField(span, ["kind", "span_kind", "spanKind"]) ?? (typeof attributes["openinference.span.kind"] === "string" ? attributes["openinference.span.kind"] : void 0);
@@ -3570,7 +3708,7 @@ function mapOtlpStatus(status) {
3570
3708
  function readOtlpKind(attributes, pathPrefix) {
3571
3709
  const warnings = [];
3572
3710
  const agentInspectKind = attributes["agent_inspect.kind"];
3573
- if (agentInspectKind === "RUN" || agentInspectKind === "AGENT" || agentInspectKind === "LLM" || agentInspectKind === "TOOL" || agentInspectKind === "CHAIN" || agentInspectKind === "RETRIEVER" || agentInspectKind === "DECISION" || agentInspectKind === "RESULT" || agentInspectKind === "ERROR" || agentInspectKind === "LOGIC" || agentInspectKind === "LOG") {
3711
+ if (agentInspectKind === "RUN" || agentInspectKind === "AGENT" || agentInspectKind === "LLM" || agentInspectKind === "TOOL" || agentInspectKind === "CHAIN" || agentInspectKind === "RETRIEVER" || agentInspectKind === "DECISION" || agentInspectKind === "RESULT" || agentInspectKind === "ERROR" || agentInspectKind === "LOGIC" || agentInspectKind === "LOG" || agentInspectKind === "OUTCOME") {
3574
3712
  return { kind: agentInspectKind, warnings };
3575
3713
  }
3576
3714
  const operation = attributes["gen_ai.operation.name"];