agent-inspect 6.31.6 → 6.31.7

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.
Files changed (35) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +1 -1
  3. package/docs/AI-SDK-ADOPTION.md +62 -34
  4. package/package.json +1 -1
  5. package/packages/cli/dist/{chunk-YXDNWHNJ.mjs → chunk-QV73NM25.mjs} +97 -25
  6. package/packages/cli/dist/chunk-QV73NM25.mjs.map +1 -0
  7. package/packages/cli/dist/index.cjs +414 -81
  8. package/packages/cli/dist/index.cjs.map +1 -1
  9. package/packages/cli/dist/index.mjs +322 -62
  10. package/packages/cli/dist/index.mjs.map +1 -1
  11. package/packages/cli/dist/{src-H22KNWAZ.mjs → src-KFOBXFPN.mjs} +3 -3
  12. package/packages/cli/dist/{src-H22KNWAZ.mjs.map → src-KFOBXFPN.mjs.map} +1 -1
  13. package/packages/core/dist/advanced.cjs +94 -22
  14. package/packages/core/dist/advanced.cjs.map +1 -1
  15. package/packages/core/dist/advanced.mjs +4 -4
  16. package/packages/core/dist/{chunk-OSGNGRHF.mjs → chunk-3RV3JILQ.mjs} +34 -16
  17. package/packages/core/dist/chunk-3RV3JILQ.mjs.map +1 -0
  18. package/packages/core/dist/{chunk-EXGQLMVB.mjs → chunk-7YYS742B.mjs} +49 -12
  19. package/packages/core/dist/chunk-7YYS742B.mjs.map +1 -0
  20. package/packages/core/dist/{chunk-Q5SLKV2Y.mjs → chunk-QLYUWKK7.mjs} +19 -2
  21. package/packages/core/dist/chunk-QLYUWKK7.mjs.map +1 -0
  22. package/packages/core/dist/exporters.cjs +224 -47
  23. package/packages/core/dist/exporters.cjs.map +1 -1
  24. package/packages/core/dist/exporters.mjs +178 -38
  25. package/packages/core/dist/exporters.mjs.map +1 -1
  26. package/packages/core/dist/persisted.cjs +17 -0
  27. package/packages/core/dist/persisted.cjs.map +1 -1
  28. package/packages/core/dist/persisted.mjs +2 -2
  29. package/packages/core/dist/readers.cjs +48 -13
  30. package/packages/core/dist/readers.cjs.map +1 -1
  31. package/packages/core/dist/readers.mjs +2 -2
  32. package/packages/cli/dist/chunk-YXDNWHNJ.mjs.map +0 -1
  33. package/packages/core/dist/chunk-EXGQLMVB.mjs.map +0 -1
  34. package/packages/core/dist/chunk-OSGNGRHF.mjs.map +0 -1
  35. package/packages/core/dist/chunk-Q5SLKV2Y.mjs.map +0 -1
@@ -1,4 +1,4 @@
1
- import { buildRunWhatSummary, renderRunWhat, renderTimeline, buildRunTimeline } from './chunk-EXGQLMVB.mjs';
1
+ import { buildRunWhatSummary, renderRunWhat, renderTimeline, buildRunTimeline } from './chunk-7YYS742B.mjs';
2
2
  import { summarizeObservedOutcomes, extractOutcomesFromTraceEvents, renderObservedOutcomesMarkdown, renderObservedOutcomesHtml } from './chunk-N5PZAI6Q.mjs';
3
3
  import { escapeHtml, flattenTree, safeString, compactAttributes, stableJson, escapeMarkdown, zeroKinds } from './chunk-CAWPF22J.mjs';
4
4
  export { compactAttributes, escapeHtml, escapeMarkdown, flattenTree, safeString, stableJson, summarizeTree } from './chunk-CAWPF22J.mjs';
@@ -808,6 +808,10 @@ function exportOpenInference(tree, options) {
808
808
  warnings
809
809
  };
810
810
  }
811
+ var OTLP_STATUS_CODE_UNSET = 0;
812
+ var OTLP_STATUS_CODE_OK = 1;
813
+ var OTLP_STATUS_CODE_ERROR = 2;
814
+ var OTLP_SPAN_KIND_INTERNAL = 1;
811
815
  function hexFrom2(seed, byteLen) {
812
816
  return crypto.createHash("sha256").update(seed, "utf8").digest("hex").slice(0, byteLen * 2);
813
817
  }
@@ -820,7 +824,19 @@ function stringAttr(key, value) {
820
824
  return { key, value: { stringValue: value } };
821
825
  }
822
826
  function intAttr(key, value) {
823
- return { key, value: { intValue: String(value) } };
827
+ return { key, value: { intValue: String(Math.trunc(value)) } };
828
+ }
829
+ function doubleAttr(key, value) {
830
+ return { key, value: { doubleValue: value } };
831
+ }
832
+ function boolAttr(key, value) {
833
+ return { key, value: { boolValue: value } };
834
+ }
835
+ function numberAttr(key, value) {
836
+ if (Number.isFinite(value) && !Number.isInteger(value)) {
837
+ return doubleAttr(key, value);
838
+ }
839
+ return intAttr(key, value);
824
840
  }
825
841
  function genAiOperationName(kind) {
826
842
  switch (kind) {
@@ -834,10 +850,27 @@ function genAiOperationName(kind) {
834
850
  return void 0;
835
851
  }
836
852
  }
853
+ function resolveSpanTimes(ev) {
854
+ const startedAtMs = typeof ev.attributes?.startedAtMs === "number" && Number.isFinite(ev.attributes.startedAtMs) ? ev.attributes.startedAtMs : void 0;
855
+ const endedAtMs = typeof ev.attributes?.endedAtMs === "number" && Number.isFinite(ev.attributes.endedAtMs) ? ev.attributes.endedAtMs : void 0;
856
+ const startMs = startedAtMs ?? ev.timestamp;
857
+ const startNs = String(unixNano2(startMs));
858
+ if (endedAtMs !== void 0) {
859
+ return { startNs, endNs: String(unixNano2(endedAtMs)) };
860
+ }
861
+ if (ev.durationMs !== void 0 && Number.isFinite(ev.durationMs)) {
862
+ return {
863
+ startNs,
864
+ endNs: String(unixNano2(startMs) + unixNano2(ev.durationMs))
865
+ };
866
+ }
867
+ return { startNs };
868
+ }
837
869
  function exportOtlpJson(tree, options) {
838
870
  const warnings = [
839
871
  "OTLP JSON export uses OTel GenAI-aligned attributes where applicable; experimental until verified against specific collectors.",
840
- "Not OTLP gRPC/protobuf \u2014 JSON mapping only. Generated locally; no network upload."
872
+ "Not OTLP gRPC/protobuf \u2014 JSON mapping only. Generated locally; no network upload.",
873
+ "Status and span kind use OTLP numeric enums (StatusCode 0/1/2, SpanKind INTERNAL=1)."
841
874
  ];
842
875
  const traceId = hexFrom2(`trace:${tree.runId}`, 16);
843
876
  const includeAttributes = options?.includeAttributes ?? false;
@@ -849,11 +882,7 @@ function exportOtlpJson(tree, options) {
849
882
  const ev = n.event;
850
883
  const spanId = hexFrom2(`${tree.runId}:${ev.eventId}`, 8);
851
884
  const parentSpanId = ev.parentId ? hexFrom2(`${tree.runId}:${ev.parentId}`, 8) : void 0;
852
- const startNs = String(unixNano2(ev.timestamp));
853
- let endNs;
854
- if (ev.durationMs !== void 0 && Number.isFinite(ev.durationMs)) {
855
- endNs = String(unixNano2(ev.timestamp) + unixNano2(ev.durationMs));
856
- }
885
+ const { startNs, endNs } = resolveSpanTimes(ev);
857
886
  const attrs = [
858
887
  stringAttr("agent_inspect.kind", ev.kind),
859
888
  stringAttr("agent_inspect.confidence", ev.confidence),
@@ -883,29 +912,28 @@ function exportOtlpJson(tree, options) {
883
912
  if (includeAttributes && meta && typeof meta === "object") {
884
913
  for (const [k, v] of Object.entries(meta)) {
885
914
  if (k === "tokens" || k === "model") continue;
886
- if (typeof v === "string" || typeof v === "number" || typeof v === "boolean") {
887
- attrs.push(
888
- stringAttr(
889
- `agent_inspect.preview.${k}`,
890
- typeof v === "string" ? v.slice(0, maxLen) : String(v)
891
- )
892
- );
915
+ if (typeof v === "string") {
916
+ attrs.push(stringAttr(`agent_inspect.preview.${k}`, v.slice(0, maxLen)));
917
+ } else if (typeof v === "number" && Number.isFinite(v)) {
918
+ attrs.push(numberAttr(`agent_inspect.preview.${k}`, v));
919
+ } else if (typeof v === "boolean") {
920
+ attrs.push(boolAttr(`agent_inspect.preview.${k}`, v));
893
921
  }
894
922
  }
895
923
  }
896
- let statusCode = "STATUS_CODE_UNSET";
924
+ let statusCode = OTLP_STATUS_CODE_UNSET;
897
925
  let statusMessage;
898
926
  if (ev.status === "error") {
899
- statusCode = "STATUS_CODE_ERROR";
927
+ statusCode = OTLP_STATUS_CODE_ERROR;
900
928
  statusMessage = meta && typeof meta.error === "object" && meta.error !== null ? String(meta.error.message ?? "error").slice(0, maxLen) : "error";
901
929
  } else if (ev.status === "ok") {
902
- statusCode = "STATUS_CODE_OK";
930
+ statusCode = OTLP_STATUS_CODE_OK;
903
931
  }
904
932
  const spanJson = {
905
933
  traceId,
906
934
  spanId,
907
935
  name: ev.name,
908
- kind: "SPAN_KIND_INTERNAL",
936
+ kind: OTLP_SPAN_KIND_INTERNAL,
909
937
  startTimeUnixNano: startNs,
910
938
  attributes: attrs,
911
939
  status: {
@@ -947,6 +975,136 @@ function exportOtlpJson(tree, options) {
947
975
 
948
976
  // packages/core/src/exporters/validation.ts
949
977
  var EXPERIMENTAL = "Experimental compatibility export \u2014 verify against your target tooling before relying on it.";
978
+ function pushPath(errors, path, message) {
979
+ errors.push(`${path}: ${message}`);
980
+ }
981
+ function isRecord2(value) {
982
+ return value !== null && typeof value === "object" && !Array.isArray(value);
983
+ }
984
+ function validateOtlpJson(content) {
985
+ const errors = [];
986
+ const warnings = [
987
+ EXPERIMENTAL,
988
+ "OTLP JSON mapping uses OTel GenAI-aligned attributes where applicable; collectors may require transformation.",
989
+ "protocol-valid \u2260 profile-complete \u2260 fixture-complete \u2014 nested path diagnostics report protocol shape only."
990
+ ];
991
+ let parsed;
992
+ try {
993
+ parsed = JSON.parse(content);
994
+ } catch {
995
+ pushPath(errors, "$", "OTLP JSON export is not valid JSON");
996
+ return { ok: false, format: "otlp-json", errors, warnings };
997
+ }
998
+ if (!isRecord2(parsed)) {
999
+ pushPath(errors, "$", "OTLP JSON export must be an object");
1000
+ return { ok: false, format: "otlp-json", errors, warnings };
1001
+ }
1002
+ if (!Array.isArray(parsed.resourceSpans)) {
1003
+ pushPath(errors, "$.resourceSpans", "must be an array");
1004
+ return { ok: false, format: "otlp-json", errors, warnings };
1005
+ }
1006
+ parsed.resourceSpans.forEach((resourceSpan, rsi) => {
1007
+ const rsPath = `$.resourceSpans[${rsi}]`;
1008
+ if (!isRecord2(resourceSpan)) {
1009
+ pushPath(errors, rsPath, "must be an object");
1010
+ return;
1011
+ }
1012
+ if (!Array.isArray(resourceSpan.scopeSpans)) {
1013
+ pushPath(errors, `${rsPath}.scopeSpans`, "must be an array");
1014
+ return;
1015
+ }
1016
+ resourceSpan.scopeSpans.forEach((scopeSpan, ssi) => {
1017
+ const ssPath = `${rsPath}.scopeSpans[${ssi}]`;
1018
+ if (!isRecord2(scopeSpan)) {
1019
+ pushPath(errors, ssPath, "must be an object");
1020
+ return;
1021
+ }
1022
+ if (!Array.isArray(scopeSpan.spans)) {
1023
+ pushPath(errors, `${ssPath}.spans`, "must be an array");
1024
+ return;
1025
+ }
1026
+ scopeSpan.spans.forEach((span, spi) => {
1027
+ const spanPath = `${ssPath}.spans[${spi}]`;
1028
+ if (!isRecord2(span)) {
1029
+ pushPath(errors, spanPath, "must be an object");
1030
+ return;
1031
+ }
1032
+ if (typeof span.traceId !== "string" || span.traceId.length === 0) {
1033
+ pushPath(errors, `${spanPath}.traceId`, "must be a non-empty string");
1034
+ }
1035
+ if (typeof span.spanId !== "string" || span.spanId.length === 0) {
1036
+ pushPath(errors, `${spanPath}.spanId`, "must be a non-empty string");
1037
+ }
1038
+ if (typeof span.name !== "string") {
1039
+ pushPath(errors, `${spanPath}.name`, "must be a string");
1040
+ }
1041
+ if (typeof span.startTimeUnixNano !== "string" || !/^\d+$/.test(span.startTimeUnixNano)) {
1042
+ pushPath(
1043
+ errors,
1044
+ `${spanPath}.startTimeUnixNano`,
1045
+ "must be a decimal-string 64-bit integer"
1046
+ );
1047
+ }
1048
+ if (span.endTimeUnixNano !== void 0 && (typeof span.endTimeUnixNano !== "string" || !/^\d+$/.test(span.endTimeUnixNano))) {
1049
+ pushPath(
1050
+ errors,
1051
+ `${spanPath}.endTimeUnixNano`,
1052
+ "must be a decimal-string 64-bit integer when present"
1053
+ );
1054
+ }
1055
+ if (typeof span.kind === "number") {
1056
+ if (!Number.isInteger(span.kind)) {
1057
+ pushPath(errors, `${spanPath}.kind`, "must be an integer SpanKind enum");
1058
+ }
1059
+ } else if (typeof span.kind === "string") {
1060
+ warnings.push(
1061
+ `${spanPath}.kind: string SpanKind enum is legacy; prefer numeric (INTERNAL=1)`
1062
+ );
1063
+ } else if (span.kind !== void 0) {
1064
+ pushPath(
1065
+ errors,
1066
+ `${spanPath}.kind`,
1067
+ "must be numeric SpanKind or historical string enum"
1068
+ );
1069
+ }
1070
+ if (!isRecord2(span.status)) {
1071
+ pushPath(errors, `${spanPath}.status`, "must be an object");
1072
+ } else {
1073
+ const code = span.status.code;
1074
+ if (typeof code === "number") {
1075
+ if (![0, 1, 2].includes(code)) {
1076
+ pushPath(
1077
+ errors,
1078
+ `${spanPath}.status.code`,
1079
+ "must be numeric StatusCode 0 (UNSET), 1 (OK), or 2 (ERROR)"
1080
+ );
1081
+ }
1082
+ } else if (typeof code === "string") {
1083
+ const upper = code.toUpperCase();
1084
+ if (upper !== "STATUS_CODE_UNSET" && upper !== "STATUS_CODE_OK" && upper !== "STATUS_CODE_ERROR" && upper !== "UNSET" && upper !== "OK" && upper !== "ERROR" && !/^[012]$/.test(code.trim())) {
1085
+ pushPath(
1086
+ errors,
1087
+ `${spanPath}.status.code`,
1088
+ "unrecognized StatusCode string"
1089
+ );
1090
+ } else {
1091
+ warnings.push(
1092
+ `${spanPath}.status.code: string StatusCode is legacy; prefer numeric 0/1/2`
1093
+ );
1094
+ }
1095
+ } else {
1096
+ pushPath(
1097
+ errors,
1098
+ `${spanPath}.status.code`,
1099
+ "must be numeric StatusCode 0/1/2 or historical string enum"
1100
+ );
1101
+ }
1102
+ }
1103
+ });
1104
+ });
1105
+ });
1106
+ return { ok: errors.length === 0, format: "otlp-json", errors, warnings };
1107
+ }
950
1108
  function validateExportContent(format, content) {
951
1109
  const errors = [];
952
1110
  const warnings = [EXPERIMENTAL];
@@ -992,25 +1150,7 @@ function validateExportContent(format, content) {
992
1150
  return { ok: errors.length === 0, format, errors, warnings };
993
1151
  }
994
1152
  if (format === "otlp-json") {
995
- let parsed;
996
- try {
997
- parsed = JSON.parse(content);
998
- } catch {
999
- errors.push("OTLP JSON export is not valid JSON");
1000
- return { ok: false, format, errors, warnings };
1001
- }
1002
- if (!parsed || typeof parsed !== "object") {
1003
- errors.push("OTLP JSON export must be an object");
1004
- return { ok: false, format, errors, warnings };
1005
- }
1006
- const o = parsed;
1007
- if (!Array.isArray(o.resourceSpans)) {
1008
- errors.push("OTLP JSON export must include resourceSpans array");
1009
- }
1010
- warnings.push(
1011
- "OTLP JSON mapping uses OTel GenAI-aligned attributes where applicable; collectors may require transformation."
1012
- );
1013
- return { ok: errors.length === 0, format, errors, warnings };
1153
+ return validateOtlpJson(content);
1014
1154
  }
1015
1155
  errors.push(`Unsupported export format`);
1016
1156
  return { ok: false, format, errors, warnings };