@agent-inspect/mcp-server 4.2.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;
@@ -1421,7 +1524,7 @@ function summarize(findings, diagnostics) {
1421
1524
  errors: diagnostics.filter((item) => item.severity === "error").length
1422
1525
  };
1423
1526
  }
1424
- function eventEvidence(event, path7) {
1527
+ function eventEvidence(event, path8) {
1425
1528
  return {
1426
1529
  runId: event.runId,
1427
1530
  eventId: event.eventId,
@@ -1759,13 +1862,13 @@ function pairSteps(left, right) {
1759
1862
  return pairs;
1760
1863
  }
1761
1864
  function compareLeafSteps(L, R, segments, opts, out) {
1762
- const path7 = buildPath(segments);
1865
+ const path8 = buildPath(segments);
1763
1866
  if (L.name !== R.name) {
1764
1867
  out.push({
1765
1868
  kind: "structure",
1766
1869
  severity: "warning",
1767
1870
  message: "Step name differs",
1768
- path: path7,
1871
+ path: path8,
1769
1872
  left: L.name,
1770
1873
  right: R.name
1771
1874
  });
@@ -1775,7 +1878,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
1775
1878
  kind: "step-type",
1776
1879
  severity: "warning",
1777
1880
  message: "Step type differs",
1778
- path: path7,
1881
+ path: path8,
1779
1882
  left: L.type,
1780
1883
  right: R.type
1781
1884
  });
@@ -1785,7 +1888,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
1785
1888
  kind: "step-status",
1786
1889
  severity: "warning",
1787
1890
  message: "Step status differs",
1788
- path: path7,
1891
+ path: path8,
1789
1892
  left: L.status,
1790
1893
  right: R.status
1791
1894
  });
@@ -1797,7 +1900,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
1797
1900
  kind: "error",
1798
1901
  severity: "error",
1799
1902
  message: "Step error message differs",
1800
- path: path7,
1903
+ path: path8,
1801
1904
  left: le || void 0,
1802
1905
  right: re || void 0
1803
1906
  });
@@ -1815,7 +1918,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
1815
1918
  kind: "duration",
1816
1919
  severity: "info",
1817
1920
  message: "Step duration differs",
1818
- path: path7,
1921
+ path: path8,
1819
1922
  left: ld,
1820
1923
  right: rd
1821
1924
  });
@@ -1828,7 +1931,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
1828
1931
  kind: "metadata",
1829
1932
  severity: "info",
1830
1933
  message: "Step metadata differs",
1831
- path: path7,
1934
+ path: path8,
1832
1935
  left: L.metadata,
1833
1936
  right: R.metadata
1834
1937
  });
@@ -1840,7 +1943,7 @@ function compareLeafSteps(L, R, segments, opts, out) {
1840
1943
  kind: "output",
1841
1944
  severity: "info",
1842
1945
  message: "Output preview differs",
1843
- path: path7,
1946
+ path: path8,
1844
1947
  left: L.outputPreview,
1845
1948
  right: R.outputPreview
1846
1949
  });
@@ -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"];