@agent-inspect/viewer 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
@@ -1,5 +1,5 @@
1
1
  import { createServer } from 'http';
2
- import path6 from 'path';
2
+ import path7 from 'path';
3
3
  import { AsyncLocalStorage } from 'async_hooks';
4
4
  import 'crypto';
5
5
  import { readdir, stat, readFile } from 'fs/promises';
@@ -71,6 +71,9 @@ function isTraceEvent(value) {
71
71
  case "step_completed": {
72
72
  return typeof value.runId === "string" && typeof value.stepId === "string" && (value.status === "success" || value.status === "error") && typeof value.endTime === "number" && typeof value.durationMs === "number";
73
73
  }
74
+ case "outcome_observed": {
75
+ 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";
76
+ }
74
77
  default:
75
78
  return false;
76
79
  }
@@ -88,7 +91,8 @@ var INSPECT_KINDS = [
88
91
  "RESULT",
89
92
  "ERROR",
90
93
  "LOGIC",
91
- "LOG"
94
+ "LOG",
95
+ "OUTCOME"
92
96
  ];
93
97
  var ATTRIBUTION_CONFIDENCES = [
94
98
  "explicit",
@@ -380,6 +384,32 @@ function fromLegacyStepCompleted(event) {
380
384
  if (error) out.error = error;
381
385
  return out;
382
386
  }
387
+ function fromLegacyOutcomeObserved(event) {
388
+ const attrs = event.attributes ?? {};
389
+ const observedAtRaw = attrs.observedAt;
390
+ const observedAt = typeof observedAtRaw === "string" ? Date.parse(observedAtRaw) : typeof observedAtRaw === "number" && Number.isFinite(observedAtRaw) ? observedAtRaw : resolveTimes(event).timestamp;
391
+ const status = attrs.outcomeStatus;
392
+ const out = {
393
+ schemaVersion: "0.1",
394
+ event: "outcome_observed",
395
+ timestamp: observedAt,
396
+ runId: event.runId,
397
+ outcomeId: typeof attrs.outcomeId === "string" ? attrs.outcomeId : event.eventId,
398
+ name: event.name,
399
+ expectation: typeof attrs.expectation === "string" ? attrs.expectation : event.name,
400
+ status: status === "passed" || status === "failed" || status === "unknown" || status === "skipped" ? status : "unknown",
401
+ observedAt
402
+ };
403
+ if (event.parentId !== void 0) out.parentId = event.parentId;
404
+ if (typeof attrs.method === "string") out.method = attrs.method;
405
+ if (attrs.actual !== void 0) out.actual = attrs.actual;
406
+ if (event.outputSummary !== void 0) out.actual = event.outputSummary;
407
+ if (attrs.evidence !== void 0) out.evidence = attrs.evidence;
408
+ return out;
409
+ }
410
+ function fromNativeOutcome(event) {
411
+ return [fromLegacyOutcomeObserved(event)];
412
+ }
383
413
  function fromNativeRun(event) {
384
414
  const { timestamp, startTime, endTime } = resolveTimes(event);
385
415
  const runStatus = mapPersistedStatusToRunStatus(event.status);
@@ -467,9 +497,13 @@ function persistedInspectEventToTraceEvents(event) {
467
497
  if (legacyEvent === "run_completed") return [fromLegacyRunCompleted(event)];
468
498
  if (legacyEvent === "step_started") return [fromLegacyStepStarted(event)];
469
499
  if (legacyEvent === "step_completed") return [fromLegacyStepCompleted(event)];
500
+ if (legacyEvent === "outcome_observed") return [fromLegacyOutcomeObserved(event)];
470
501
  if (event.kind === "RUN") {
471
502
  return fromNativeRun(event);
472
503
  }
504
+ if (event.kind === "OUTCOME") {
505
+ return fromNativeOutcome(event);
506
+ }
473
507
  return fromNativeStep(event);
474
508
  }
475
509
  function persistedInspectEventsToTraceEvents(events, options) {
@@ -483,7 +517,7 @@ function persistedInspectEventsToTraceEvents(events, options) {
483
517
  }
484
518
  var DEFAULT_TRACE_DIR_NAME = ".agent-inspect";
485
519
  var RUNS_DIR_NAME = "runs";
486
- var FALLBACK_TRACE_DIR = path6.join(
520
+ var FALLBACK_TRACE_DIR = path7.join(
487
521
  os.tmpdir(),
488
522
  "agent-inspect",
489
523
  RUNS_DIR_NAME
@@ -498,7 +532,7 @@ function getDefaultTraceDir() {
498
532
  if (typeof home !== "string" || home.trim() === "") {
499
533
  return FALLBACK_TRACE_DIR;
500
534
  }
501
- return path6.join(home, DEFAULT_TRACE_DIR_NAME, RUNS_DIR_NAME);
535
+ return path7.join(home, DEFAULT_TRACE_DIR_NAME, RUNS_DIR_NAME);
502
536
  } catch {
503
537
  return FALLBACK_TRACE_DIR;
504
538
  }
@@ -669,6 +703,9 @@ function validateEvent(event) {
669
703
  case "step_completed": {
670
704
  return nonEmptyString(event.runId) && nonEmptyString(event.stepId) && (event.status === "success" || event.status === "error") && finiteNumber(event.endTime) && finiteNumber(event.durationMs) && optionalErrorInfo(event.error);
671
705
  }
706
+ case "outcome_observed": {
707
+ 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);
708
+ }
672
709
  default:
673
710
  return false;
674
711
  }
@@ -704,7 +741,7 @@ var TraceDirectory = class {
704
741
  this.#dir = resolveTraceDir(options);
705
742
  }
706
743
  getPath(filename) {
707
- return filename ? path6.join(this.#dir, filename) : this.#dir;
744
+ return filename ? path7.join(this.#dir, filename) : this.#dir;
708
745
  }
709
746
  async list() {
710
747
  try {
@@ -731,7 +768,7 @@ function parseIsoToMs2(value) {
731
768
  }
732
769
  async function extractMetadata(filePath, _quickScan) {
733
770
  const stats = await stat(filePath);
734
- let runIdFromFile = path6.basename(filePath);
771
+ let runIdFromFile = path7.basename(filePath);
735
772
  if (runIdFromFile.endsWith(".jsonl")) {
736
773
  runIdFromFile = runIdFromFile.slice(0, -".jsonl".length);
737
774
  }
@@ -1341,12 +1378,12 @@ function buildCriticalPath(runs, handoffs) {
1341
1378
  handoffs.filter((edge) => edge.confidence === "explicit").map((edge) => edge.from)
1342
1379
  );
1343
1380
  const ordered = [...runs].sort(compareRuns);
1344
- const path7 = [];
1381
+ const path8 = [];
1345
1382
  const visited = /* @__PURE__ */ new Set();
1346
1383
  const pushRun = (run, confidence, source) => {
1347
1384
  if (visited.has(run.runId)) return;
1348
1385
  visited.add(run.runId);
1349
- path7.push({
1386
+ path8.push({
1350
1387
  runId: run.runId,
1351
1388
  name: run.name,
1352
1389
  startedAt: run.startedAt,
@@ -1371,7 +1408,7 @@ function buildCriticalPath(runs, handoffs) {
1371
1408
  const confidence = explicitTargets.has(run.runId) || explicitSources.has(run.runId) ? "explicit" : "correlated";
1372
1409
  pushRun(run, confidence, confidence === "explicit" ? "manual" : "inferred");
1373
1410
  }
1374
- return path7;
1411
+ return path8;
1375
1412
  }
1376
1413
  function metaRunIdMatches(run, token, runById) {
1377
1414
  const meta = extractSessionWorkflowMetadata(run.metadata);
@@ -1644,7 +1681,7 @@ function summarize(findings, diagnostics) {
1644
1681
  errors: diagnostics.filter((item) => item.severity === "error").length
1645
1682
  };
1646
1683
  }
1647
- function eventEvidence(event, path7) {
1684
+ function eventEvidence(event, path8) {
1648
1685
  return {
1649
1686
  runId: event.runId,
1650
1687
  eventId: event.eventId,
@@ -1793,6 +1830,8 @@ function nodeIdForEvent(event) {
1793
1830
  case "step_started":
1794
1831
  case "step_completed":
1795
1832
  return event.stepId;
1833
+ case "outcome_observed":
1834
+ return event.outcomeId;
1796
1835
  default:
1797
1836
  return "unknown";
1798
1837
  }
@@ -1976,6 +2015,39 @@ function traceEventToPersistedInspectEvent(event, options) {
1976
2015
  error
1977
2016
  };
1978
2017
  }
2018
+ case "outcome_observed": {
2019
+ const tsObserved = toIsoTimestamp(event.observedAt);
2020
+ const attributes = compactAttributes({
2021
+ legacyEvent: "outcome_observed",
2022
+ outcomeId: event.outcomeId,
2023
+ outcomeStatus: event.status,
2024
+ expectation: event.expectation,
2025
+ method: event.method,
2026
+ actual: event.actual,
2027
+ evidence: event.evidence,
2028
+ observedAt: tsObserved.iso,
2029
+ invalidTimestamp: tsMain.invalidTimestamp || tsObserved.invalidTimestamp ? true : void 0
2030
+ });
2031
+ const out = {
2032
+ schemaVersion: "0.2",
2033
+ eventId,
2034
+ runId: event.runId,
2035
+ kind: "OUTCOME",
2036
+ name: event.name,
2037
+ status: event.status === "failed" ? "error" : "ok",
2038
+ timestamp: tsMain.iso,
2039
+ confidence: "explicit",
2040
+ source,
2041
+ attributes
2042
+ };
2043
+ if (event.parentId !== void 0) {
2044
+ out.parentId = event.parentId;
2045
+ }
2046
+ if (event.actual !== void 0) {
2047
+ out.outputSummary = event.actual;
2048
+ }
2049
+ return out;
2050
+ }
1979
2051
  default: {
1980
2052
  const _exhaustive = event;
1981
2053
  throw new Error(`Unsupported trace event: ${_exhaustive.event}`);
@@ -2335,7 +2407,7 @@ function findReaderByFormat(format, readers) {
2335
2407
  }
2336
2408
  async function jsonlFilesInDirectory(dirPath) {
2337
2409
  const entries = await readdir(dirPath, { withFileTypes: true });
2338
- return entries.filter((entry) => entry.isFile() && entry.name.endsWith(".jsonl")).map((entry) => path6.join(dirPath, entry.name)).sort((a, b) => a.localeCompare(b));
2410
+ return entries.filter((entry) => entry.isFile() && entry.name.endsWith(".jsonl")).map((entry) => path7.join(dirPath, entry.name)).sort((a, b) => a.localeCompare(b));
2339
2411
  }
2340
2412
  async function resolveInput(input) {
2341
2413
  const cached = resolvedInputCache.get(input);
@@ -2705,7 +2777,7 @@ function sanitizeOpenInferenceAttributes(attributes, pathPrefix) {
2705
2777
  function mapOpenInferenceKind(span, attributes, pathPrefix) {
2706
2778
  const warnings = [];
2707
2779
  const agentInspectKind = attributes["agent_inspect.kind"];
2708
- if (agentInspectKind === "RUN" || agentInspectKind === "AGENT" || agentInspectKind === "LLM" || agentInspectKind === "TOOL" || agentInspectKind === "CHAIN" || agentInspectKind === "RETRIEVER" || agentInspectKind === "DECISION" || agentInspectKind === "RESULT" || agentInspectKind === "ERROR" || agentInspectKind === "LOGIC" || agentInspectKind === "LOG") {
2780
+ 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") {
2709
2781
  return { kind: agentInspectKind, warnings };
2710
2782
  }
2711
2783
  const rawKind = readStringField(span, ["kind", "span_kind", "spanKind"]) ?? (typeof attributes["openinference.span.kind"] === "string" ? attributes["openinference.span.kind"] : void 0);
@@ -3226,7 +3298,7 @@ function mapOtlpStatus(status) {
3226
3298
  function readOtlpKind(attributes, pathPrefix) {
3227
3299
  const warnings = [];
3228
3300
  const agentInspectKind = attributes["agent_inspect.kind"];
3229
- if (agentInspectKind === "RUN" || agentInspectKind === "AGENT" || agentInspectKind === "LLM" || agentInspectKind === "TOOL" || agentInspectKind === "CHAIN" || agentInspectKind === "RETRIEVER" || agentInspectKind === "DECISION" || agentInspectKind === "RESULT" || agentInspectKind === "ERROR" || agentInspectKind === "LOGIC" || agentInspectKind === "LOG") {
3301
+ 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") {
3230
3302
  return { kind: agentInspectKind, warnings };
3231
3303
  }
3232
3304
  const operation = attributes["gen_ai.operation.name"];
@@ -3872,7 +3944,7 @@ function createViewerServer(options = {}) {
3872
3944
  return sendJson(res, 200, {
3873
3945
  ok: true,
3874
3946
  readOnly: true,
3875
- traceDir: path6.resolve(traceDir)
3947
+ traceDir: path7.resolve(traceDir)
3876
3948
  });
3877
3949
  }
3878
3950
  const td = new TraceDirectory({ dir: traceDir });
@@ -3890,7 +3962,7 @@ function createViewerServer(options = {}) {
3890
3962
  runId: meta.runId,
3891
3963
  name: meta.name,
3892
3964
  status: meta.status,
3893
- file: path6.basename(meta.filePath),
3965
+ file: path7.basename(meta.filePath),
3894
3966
  startedAt: meta.startedAt,
3895
3967
  durationMs: meta.durationMs
3896
3968
  }))
@@ -4005,7 +4077,7 @@ function startViewerServer(options = {}) {
4005
4077
  resolve({
4006
4078
  host,
4007
4079
  port: resolvedPort,
4008
- traceDir: path6.resolve(traceDir),
4080
+ traceDir: path7.resolve(traceDir),
4009
4081
  url: `http://${host}:${resolvedPort}`
4010
4082
  });
4011
4083
  });