@agentmark-ai/shared-utils 0.5.0 → 0.6.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.d.mts CHANGED
@@ -1,3 +1,5 @@
1
+ export { TraceIO, TraceIOSpan, deriveTraceIO } from './trace-io.mjs';
2
+
1
3
  declare const generateUnique8CharString: () => string;
2
4
 
3
5
  declare function createSignature(secret: string | undefined, payload: string): Promise<string>;
@@ -555,6 +557,7 @@ declare class OtelGenAiTransformer implements ScopeTransformer {
555
557
  static readonly SCOPE_NAME = "pydantic-ai";
556
558
  }
557
559
 
560
+ declare function normalizeOtlpStatusCode(raw: string | number | undefined | null): string;
558
561
  declare function normalizeSpan(resource: OtelResource, scope: OtelScope, span: OtelSpan): NormalizedSpan;
559
562
  /**
560
563
  * Normalize spans from raw OTLP resourceSpans structure
@@ -562,4 +565,4 @@ declare function normalizeSpan(resource: OtelResource, scope: OtelScope, span: O
562
565
  */
563
566
  declare function normalizeOtlpSpans(resourceSpans: OtlpResourceSpans[]): NormalizedSpan[];
564
567
 
565
- export { AGENTMARK_SCOPE_NAME, AgentMarkTransformer, type AgentmarkConfig, type AgentmarkModelConfig, type AgentmarkModelSchema, type AgentmarkModelSettingsConfig, type AgentmarkModelSettingsSchema, AiSdkTransformer, type AiSdkVersion, type AttributeExtractor, AgentMarkTransformer as ClaudeAgentTransformer, type GenerateTypesLanguage, MastraTransformer, type McpServerConfig, type McpServers, type McpStdioServerConfig, type McpUrlServerConfig, type Message, type ModelSettingsTypeAspectRatio, type ModelSettingsTypeImageSize, type ModelSettingsTypeSelect, type ModelSettingsTypeSlider, type NormalizedSpan, type OtelEvent, OtelGenAiTransformer, type OtelLink, type OtelResource, type OtelScope, type OtelSpan, type OtlpAttribute, type OtlpAttributeValue, type OtlpEvent, type OtlpLink, type OtlpResource, type OtlpResourceSpans, type OtlpScope, type OtlpScopeSpans, type OtlpSpan, SEMANTIC_KINDS, type ScopeTransformer, type SemanticKind, SpanType, type StandardMessageContent, type StandardTextContent, type StandardToolCallContent, type StandardToolResultContent, type ToolCall, TransformerRegistry, TypeClassifier, convertOtlpAttributes, createSignature, detectVersion, extractCustomMetadata, extractReasoningFromProviderMetadata, extractResourceScopeSpan, fetchPromptsFrontmatter, findPromptFiles, generateTypeDefinitions, generateUnique8CharString, normalizeOtlpSpans, normalizeSpan, parseAgentMarkAttributes, parseMetadata, parseTokens, registry, resolveSemanticKind, toFrontMatter, typeClassifier, verifySignature };
568
+ export { AGENTMARK_SCOPE_NAME, AgentMarkTransformer, type AgentmarkConfig, type AgentmarkModelConfig, type AgentmarkModelSchema, type AgentmarkModelSettingsConfig, type AgentmarkModelSettingsSchema, AiSdkTransformer, type AiSdkVersion, type AttributeExtractor, AgentMarkTransformer as ClaudeAgentTransformer, type GenerateTypesLanguage, MastraTransformer, type McpServerConfig, type McpServers, type McpStdioServerConfig, type McpUrlServerConfig, type Message, type ModelSettingsTypeAspectRatio, type ModelSettingsTypeImageSize, type ModelSettingsTypeSelect, type ModelSettingsTypeSlider, type NormalizedSpan, type OtelEvent, OtelGenAiTransformer, type OtelLink, type OtelResource, type OtelScope, type OtelSpan, type OtlpAttribute, type OtlpAttributeValue, type OtlpEvent, type OtlpLink, type OtlpResource, type OtlpResourceSpans, type OtlpScope, type OtlpScopeSpans, type OtlpSpan, SEMANTIC_KINDS, type ScopeTransformer, type SemanticKind, SpanType, type StandardMessageContent, type StandardTextContent, type StandardToolCallContent, type StandardToolResultContent, type ToolCall, TransformerRegistry, TypeClassifier, convertOtlpAttributes, createSignature, detectVersion, extractCustomMetadata, extractReasoningFromProviderMetadata, extractResourceScopeSpan, fetchPromptsFrontmatter, findPromptFiles, generateTypeDefinitions, generateUnique8CharString, normalizeOtlpSpans, normalizeOtlpStatusCode, normalizeSpan, parseAgentMarkAttributes, parseMetadata, parseTokens, registry, resolveSemanticKind, toFrontMatter, typeClassifier, verifySignature };
package/dist/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ export { TraceIO, TraceIOSpan, deriveTraceIO } from './trace-io.js';
2
+
1
3
  declare const generateUnique8CharString: () => string;
2
4
 
3
5
  declare function createSignature(secret: string | undefined, payload: string): Promise<string>;
@@ -555,6 +557,7 @@ declare class OtelGenAiTransformer implements ScopeTransformer {
555
557
  static readonly SCOPE_NAME = "pydantic-ai";
556
558
  }
557
559
 
560
+ declare function normalizeOtlpStatusCode(raw: string | number | undefined | null): string;
558
561
  declare function normalizeSpan(resource: OtelResource, scope: OtelScope, span: OtelSpan): NormalizedSpan;
559
562
  /**
560
563
  * Normalize spans from raw OTLP resourceSpans structure
@@ -562,4 +565,4 @@ declare function normalizeSpan(resource: OtelResource, scope: OtelScope, span: O
562
565
  */
563
566
  declare function normalizeOtlpSpans(resourceSpans: OtlpResourceSpans[]): NormalizedSpan[];
564
567
 
565
- export { AGENTMARK_SCOPE_NAME, AgentMarkTransformer, type AgentmarkConfig, type AgentmarkModelConfig, type AgentmarkModelSchema, type AgentmarkModelSettingsConfig, type AgentmarkModelSettingsSchema, AiSdkTransformer, type AiSdkVersion, type AttributeExtractor, AgentMarkTransformer as ClaudeAgentTransformer, type GenerateTypesLanguage, MastraTransformer, type McpServerConfig, type McpServers, type McpStdioServerConfig, type McpUrlServerConfig, type Message, type ModelSettingsTypeAspectRatio, type ModelSettingsTypeImageSize, type ModelSettingsTypeSelect, type ModelSettingsTypeSlider, type NormalizedSpan, type OtelEvent, OtelGenAiTransformer, type OtelLink, type OtelResource, type OtelScope, type OtelSpan, type OtlpAttribute, type OtlpAttributeValue, type OtlpEvent, type OtlpLink, type OtlpResource, type OtlpResourceSpans, type OtlpScope, type OtlpScopeSpans, type OtlpSpan, SEMANTIC_KINDS, type ScopeTransformer, type SemanticKind, SpanType, type StandardMessageContent, type StandardTextContent, type StandardToolCallContent, type StandardToolResultContent, type ToolCall, TransformerRegistry, TypeClassifier, convertOtlpAttributes, createSignature, detectVersion, extractCustomMetadata, extractReasoningFromProviderMetadata, extractResourceScopeSpan, fetchPromptsFrontmatter, findPromptFiles, generateTypeDefinitions, generateUnique8CharString, normalizeOtlpSpans, normalizeSpan, parseAgentMarkAttributes, parseMetadata, parseTokens, registry, resolveSemanticKind, toFrontMatter, typeClassifier, verifySignature };
568
+ export { AGENTMARK_SCOPE_NAME, AgentMarkTransformer, type AgentmarkConfig, type AgentmarkModelConfig, type AgentmarkModelSchema, type AgentmarkModelSettingsConfig, type AgentmarkModelSettingsSchema, AiSdkTransformer, type AiSdkVersion, type AttributeExtractor, AgentMarkTransformer as ClaudeAgentTransformer, type GenerateTypesLanguage, MastraTransformer, type McpServerConfig, type McpServers, type McpStdioServerConfig, type McpUrlServerConfig, type Message, type ModelSettingsTypeAspectRatio, type ModelSettingsTypeImageSize, type ModelSettingsTypeSelect, type ModelSettingsTypeSlider, type NormalizedSpan, type OtelEvent, OtelGenAiTransformer, type OtelLink, type OtelResource, type OtelScope, type OtelSpan, type OtlpAttribute, type OtlpAttributeValue, type OtlpEvent, type OtlpLink, type OtlpResource, type OtlpResourceSpans, type OtlpScope, type OtlpScopeSpans, type OtlpSpan, SEMANTIC_KINDS, type ScopeTransformer, type SemanticKind, SpanType, type StandardMessageContent, type StandardTextContent, type StandardToolCallContent, type StandardToolResultContent, type ToolCall, TransformerRegistry, TypeClassifier, convertOtlpAttributes, createSignature, detectVersion, extractCustomMetadata, extractReasoningFromProviderMetadata, extractResourceScopeSpan, fetchPromptsFrontmatter, findPromptFiles, generateTypeDefinitions, generateUnique8CharString, normalizeOtlpSpans, normalizeOtlpStatusCode, normalizeSpan, parseAgentMarkAttributes, parseMetadata, parseTokens, registry, resolveSemanticKind, toFrontMatter, typeClassifier, verifySignature };
package/dist/index.js CHANGED
@@ -42,6 +42,7 @@ __export(index_exports, {
42
42
  TypeClassifier: () => TypeClassifier,
43
43
  convertOtlpAttributes: () => convertOtlpAttributes,
44
44
  createSignature: () => createSignature,
45
+ deriveTraceIO: () => deriveTraceIO,
45
46
  detectVersion: () => detectVersion,
46
47
  extractCustomMetadata: () => extractCustomMetadata,
47
48
  extractReasoningFromProviderMetadata: () => extractReasoningFromProviderMetadata,
@@ -51,6 +52,7 @@ __export(index_exports, {
51
52
  generateTypeDefinitions: () => generateTypeDefinitions,
52
53
  generateUnique8CharString: () => generateUnique8CharString,
53
54
  normalizeOtlpSpans: () => normalizeOtlpSpans,
55
+ normalizeOtlpStatusCode: () => normalizeOtlpStatusCode,
54
56
  normalizeSpan: () => normalizeSpan,
55
57
  parseAgentMarkAttributes: () => parseAgentMarkAttributes,
56
58
  parseMetadata: () => parseMetadata,
@@ -136,53 +138,24 @@ function hexToBytes(hex) {
136
138
  }
137
139
 
138
140
  // src/serialize.ts
141
+ var import_js_yaml = __toESM(require("js-yaml"));
139
142
  function toFrontMatter(content) {
140
- function jsonToFrontMatter(json, indent = 0) {
141
- let frontMatter = "";
142
- const indentation = " ".repeat(indent);
143
- for (const key in json) {
144
- if (Object.prototype.hasOwnProperty.call(json, key)) {
145
- const value = json[key];
146
- if (typeof value === "object" && !Array.isArray(value)) {
147
- frontMatter += `${indentation}${key}:
148
- `;
149
- frontMatter += jsonToFrontMatter(value, indent + 1);
150
- } else if (Array.isArray(value)) {
151
- frontMatter += `${indentation}${key}:
152
- `;
153
- value.forEach((item) => {
154
- if (typeof item === "object") {
155
- frontMatter += `${indentation}-
156
- `;
157
- frontMatter += jsonToFrontMatter(item, indent + 2);
158
- } else {
159
- frontMatter += `${indentation}- ${item}
160
- `;
161
- }
162
- });
163
- } else {
164
- frontMatter += `${indentation}${key}: ${value}
165
- `;
166
- }
167
- }
168
- }
169
- return frontMatter;
170
- }
143
+ const body = Object.keys(content).length === 0 ? "" : import_js_yaml.default.dump(content, { lineWidth: -1, noRefs: true, skipInvalid: true });
171
144
  return `---
172
- ${jsonToFrontMatter(content)}---
145
+ ${body}---
173
146
  `;
174
147
  }
175
148
 
176
149
  // src/generate-types.ts
177
150
  var fs = __toESM(require("fs-extra"));
178
151
  var import_path = __toESM(require("path"));
179
- var import_js_yaml = __toESM(require("js-yaml"));
152
+ var import_js_yaml2 = __toESM(require("js-yaml"));
180
153
  function extractFrontmatter(content) {
181
154
  const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
182
155
  if (!match) {
183
156
  return { attributes: {} };
184
157
  }
185
- const attributes = import_js_yaml.default.load(match[1]);
158
+ const attributes = import_js_yaml2.default.load(match[1]);
186
159
  return { attributes: attributes || {} };
187
160
  }
188
161
  var _compile = null;
@@ -1703,8 +1676,77 @@ var GenAIAttributes = {
1703
1676
  TOOL_NAME: "gen_ai.tool.name",
1704
1677
  TOOL_CALL_ID: "gen_ai.tool.call.id",
1705
1678
  TOOL_INPUT: "gen_ai.tool.input",
1706
- TOOL_OUTPUT: "gen_ai.tool.output"
1679
+ TOOL_OUTPUT: "gen_ai.tool.output",
1680
+ // Spec replacement for the deprecated gen_ai.system attribute.
1681
+ PROVIDER_NAME: "gen_ai.provider.name",
1682
+ // Vendor-namespaced IO keys (dual-emitted by observe()/setInput()/
1683
+ // setOutput() alongside the deprecated gen_ai.request.input /
1684
+ // gen_ai.response.output during the OTel GenAI spec migration).
1685
+ AM_REQUEST_INPUT: "agentmark.request.input",
1686
+ AM_RESPONSE_OUTPUT: "agentmark.response.output",
1687
+ // Standard OTel GenAI semconv content keys (spec status: Development).
1688
+ // Accepted as fallbacks so spec-conformant instrumentation routed to
1689
+ // this transformer doesn't silently lose IO data on ingest.
1690
+ // https://opentelemetry.io/docs/specs/semconv/gen-ai/gen-ai-spans/
1691
+ INPUT_MESSAGES: "gen_ai.input.messages",
1692
+ OUTPUT_MESSAGES: "gen_ai.output.messages",
1693
+ SYSTEM_INSTRUCTIONS: "gen_ai.system_instructions",
1694
+ // Legacy (pre-1.27) OTel GenAI content keys.
1695
+ LEGACY_PROMPT: "gen_ai.prompt",
1696
+ LEGACY_COMPLETION: "gen_ai.completion",
1697
+ // Legacy OTel GenAI usage keys (pre input_tokens/output_tokens rename).
1698
+ USAGE_PROMPT_TOKENS: "gen_ai.usage.prompt_tokens",
1699
+ USAGE_COMPLETION_TOKENS: "gen_ai.usage.completion_tokens"
1707
1700
  };
1701
+ function parseLooseInput(raw) {
1702
+ try {
1703
+ const parsed = JSON.parse(raw);
1704
+ if (Array.isArray(parsed) && parsed.length > 0) {
1705
+ const isMessagesArray = parsed.every(
1706
+ (item) => item && typeof item === "object" && "role" in item && "content" in item
1707
+ );
1708
+ if (isMessagesArray) {
1709
+ return parsed;
1710
+ }
1711
+ }
1712
+ } catch {
1713
+ }
1714
+ return [{ role: "user", content: raw }];
1715
+ }
1716
+ function specPartsToText(parts) {
1717
+ return parts.filter((p) => p && p.type === "text" && typeof p.content === "string").map((p) => p.content).join("\n");
1718
+ }
1719
+ function parseSpecMessages(raw) {
1720
+ try {
1721
+ const parsed = JSON.parse(raw);
1722
+ if (!Array.isArray(parsed) || parsed.length === 0) return null;
1723
+ const messages = [];
1724
+ for (const msg of parsed) {
1725
+ if (!msg || !msg.role) continue;
1726
+ if (typeof msg.content === "string") {
1727
+ messages.push({ role: msg.role, content: msg.content });
1728
+ } else if (Array.isArray(msg.parts)) {
1729
+ const text = specPartsToText(msg.parts);
1730
+ if (text) messages.push({ role: msg.role, content: text });
1731
+ }
1732
+ }
1733
+ return messages.length > 0 ? messages : null;
1734
+ } catch {
1735
+ return null;
1736
+ }
1737
+ }
1738
+ function parseSystemInstructions(raw) {
1739
+ try {
1740
+ const parsed = JSON.parse(raw);
1741
+ if (Array.isArray(parsed)) {
1742
+ const text = specPartsToText(parsed);
1743
+ return text || null;
1744
+ }
1745
+ if (typeof parsed === "string") return parsed || null;
1746
+ } catch {
1747
+ }
1748
+ return raw || null;
1749
+ }
1708
1750
  var SpanNames = {
1709
1751
  // OTEL GenAI standard operation names (these can be followed by model/tool/agent name)
1710
1752
  CHAT: "chat",
@@ -1767,7 +1809,7 @@ var AgentMarkTransformer = class {
1767
1809
  if (span.name === SpanNames.CONVERSATION || span.name === SpanNames.SUBAGENT) {
1768
1810
  return "SPAN" /* SPAN */;
1769
1811
  }
1770
- if (attributes[GenAIAttributes.SYSTEM] === "anthropic") {
1812
+ if (attributes[GenAIAttributes.SYSTEM] === "anthropic" || attributes[GenAIAttributes.PROVIDER_NAME] === "anthropic") {
1771
1813
  if (attributes[GenAIAttributes.USAGE_INPUT_TOKENS] !== void 0 && attributes[GenAIAttributes.RESPONSE_OUTPUT] !== void 0) {
1772
1814
  return "GENERATION" /* GENERATION */;
1773
1815
  }
@@ -1778,7 +1820,7 @@ var AgentMarkTransformer = class {
1778
1820
  * Transform the span and extract normalized fields from GenAI attributes.
1779
1821
  */
1780
1822
  transform(_span, attributes) {
1781
- var _a;
1823
+ var _a, _b, _c, _d, _e, _f, _g, _h;
1782
1824
  const result = {};
1783
1825
  const responseModel = attributes[GenAIAttributes.RESPONSE_MODEL];
1784
1826
  const requestModel = attributes[GenAIAttributes.REQUEST_MODEL];
@@ -1787,8 +1829,8 @@ var AgentMarkTransformer = class {
1787
1829
  } else if (requestModel) {
1788
1830
  result.model = String(requestModel);
1789
1831
  }
1790
- const inputTokens = attributes[GenAIAttributes.USAGE_INPUT_TOKENS];
1791
- const outputTokens = attributes[GenAIAttributes.USAGE_OUTPUT_TOKENS];
1832
+ const inputTokens = (_a = attributes[GenAIAttributes.USAGE_INPUT_TOKENS]) != null ? _a : attributes[GenAIAttributes.USAGE_PROMPT_TOKENS];
1833
+ const outputTokens = (_b = attributes[GenAIAttributes.USAGE_OUTPUT_TOKENS]) != null ? _b : attributes[GenAIAttributes.USAGE_COMPLETION_TOKENS];
1792
1834
  if (typeof inputTokens === "number") {
1793
1835
  result.inputTokens = inputTokens;
1794
1836
  }
@@ -1824,37 +1866,72 @@ var AgentMarkTransformer = class {
1824
1866
  result.settings.temperature = temperature;
1825
1867
  }
1826
1868
  }
1827
- const requestInput = attributes[GenAIAttributes.REQUEST_INPUT];
1869
+ const requestInput = (_c = attributes[GenAIAttributes.REQUEST_INPUT]) != null ? _c : attributes[GenAIAttributes.AM_REQUEST_INPUT];
1870
+ const hasAgentmarkInput = Boolean(
1871
+ (_d = attributes["agentmark.input"]) != null ? _d : attributes["agentmark.props"]
1872
+ );
1828
1873
  if (requestInput && typeof requestInput === "string") {
1829
- try {
1830
- const parsed = JSON.parse(requestInput);
1831
- if (Array.isArray(parsed) && parsed.length > 0) {
1832
- const isMessagesArray = parsed.every(
1833
- (item) => item && typeof item === "object" && "role" in item && "content" in item
1834
- );
1835
- if (isMessagesArray) {
1836
- result.input = parsed;
1837
- } else {
1838
- result.input = [{ role: "user", content: requestInput }];
1839
- }
1840
- } else {
1841
- result.input = [{ role: "user", content: requestInput }];
1874
+ result.input = parseLooseInput(requestInput);
1875
+ } else if (!hasAgentmarkInput) {
1876
+ const inputMessages = attributes[GenAIAttributes.INPUT_MESSAGES];
1877
+ if (inputMessages && typeof inputMessages === "string") {
1878
+ const messages = parseSpecMessages(inputMessages);
1879
+ if (messages) result.input = messages;
1880
+ }
1881
+ if (!result.input) {
1882
+ const legacyPrompt = attributes[GenAIAttributes.LEGACY_PROMPT];
1883
+ if (legacyPrompt && typeof legacyPrompt === "string") {
1884
+ result.input = parseLooseInput(legacyPrompt);
1842
1885
  }
1843
- } catch {
1844
- result.input = [{ role: "user", content: requestInput }];
1845
1886
  }
1846
1887
  }
1847
- const responseOutput = attributes[GenAIAttributes.RESPONSE_OUTPUT];
1888
+ const systemInstructions = attributes[GenAIAttributes.SYSTEM_INSTRUCTIONS];
1889
+ if (systemInstructions && typeof systemInstructions === "string" && !hasAgentmarkInput) {
1890
+ const text = parseSystemInstructions(systemInstructions);
1891
+ if (text && (!result.input || ((_e = result.input[0]) == null ? void 0 : _e.role) !== "system")) {
1892
+ result.input = [{ role: "system", content: text }, ...(_f = result.input) != null ? _f : []];
1893
+ }
1894
+ }
1895
+ const responseOutput = (_g = attributes[GenAIAttributes.RESPONSE_OUTPUT]) != null ? _g : attributes[GenAIAttributes.AM_RESPONSE_OUTPUT];
1896
+ const hasAgentmarkOutput = Boolean(attributes["agentmark.output"]);
1848
1897
  if (responseOutput && typeof responseOutput === "string") {
1849
1898
  result.output = responseOutput;
1850
1899
  try {
1851
1900
  result.outputObject = JSON.parse(responseOutput);
1852
1901
  } catch {
1853
1902
  }
1903
+ } else if (!hasAgentmarkOutput) {
1904
+ const outputMessages = attributes[GenAIAttributes.OUTPUT_MESSAGES];
1905
+ if (outputMessages && typeof outputMessages === "string") {
1906
+ const messages = parseSpecMessages(outputMessages);
1907
+ if (messages) {
1908
+ result.output = messages.map((m) => m.content).join("\n");
1909
+ }
1910
+ }
1911
+ if (result.output === void 0) {
1912
+ const legacyCompletion = attributes[GenAIAttributes.LEGACY_COMPLETION];
1913
+ if (legacyCompletion && typeof legacyCompletion === "string") {
1914
+ result.output = legacyCompletion;
1915
+ try {
1916
+ result.outputObject = JSON.parse(legacyCompletion);
1917
+ } catch {
1918
+ }
1919
+ }
1920
+ }
1854
1921
  }
1855
- const amInput = (_a = attributes["agentmark.input"]) != null ? _a : attributes["agentmark.props"];
1922
+ const amInput = (_h = attributes["agentmark.input"]) != null ? _h : attributes["agentmark.props"];
1856
1923
  if (amInput && typeof amInput === "string" && !result.input) {
1857
- result.input = [{ role: "user", content: amInput }];
1924
+ let parsedMessages = null;
1925
+ try {
1926
+ const parsed = JSON.parse(amInput);
1927
+ if (Array.isArray(parsed) && parsed.length > 0 && parsed.every(
1928
+ (item) => item && typeof item === "object" && "role" in item && "content" in item
1929
+ )) {
1930
+ parsedMessages = parsed;
1931
+ }
1932
+ } catch {
1933
+ }
1934
+ result.input = parsedMessages != null ? parsedMessages : [{ role: "user", content: amInput }];
1858
1935
  }
1859
1936
  const amOutput = attributes["agentmark.output"];
1860
1937
  if (amOutput && typeof amOutput === "string" && !result.output) {
@@ -1930,6 +2007,13 @@ var Attrs = {
1930
2007
  RESPONSE_OUTPUT_FALLBACK: "gen_ai.response.output",
1931
2008
  SYSTEM_INSTRUCTIONS: "gen_ai.system_instructions",
1932
2009
  TOOL_DEFINITIONS: "gen_ai.tool.definitions",
2010
+ // Legacy (pre-1.27) OTel GenAI content keys, accepted as last-resort
2011
+ // fallbacks below the canonical and AgentMark-scoped keys.
2012
+ LEGACY_PROMPT: "gen_ai.prompt",
2013
+ LEGACY_COMPLETION: "gen_ai.completion",
2014
+ // Legacy OTel GenAI usage keys (pre input_tokens/output_tokens rename).
2015
+ USAGE_PROMPT_TOKENS: "gen_ai.usage.prompt_tokens",
2016
+ USAGE_COMPLETION_TOKENS: "gen_ai.usage.completion_tokens",
1933
2017
  // Tool call attributes (v1.37.0+)
1934
2018
  TOOL_NAME: "gen_ai.tool.name",
1935
2019
  TOOL_CALL_ID: "gen_ai.tool.call.id",
@@ -1992,14 +2076,14 @@ var OtelGenAiTransformer = class {
1992
2076
  return "SPAN" /* SPAN */;
1993
2077
  }
1994
2078
  transform(span, attributes) {
1995
- var _a, _b;
2079
+ var _a, _b, _c, _d, _e, _f, _g, _h;
1996
2080
  const result = {};
1997
2081
  const model = attributes[Attrs.RESPONSE_MODEL] || attributes[Attrs.REQUEST_MODEL];
1998
2082
  if (model && typeof model === "string") {
1999
2083
  result.model = model;
2000
2084
  }
2001
- const inputTokens = attributes[Attrs.USAGE_INPUT_TOKENS];
2002
- const outputTokens = attributes[Attrs.USAGE_OUTPUT_TOKENS];
2085
+ const inputTokens = (_a = attributes[Attrs.USAGE_INPUT_TOKENS]) != null ? _a : attributes[Attrs.USAGE_PROMPT_TOKENS];
2086
+ const outputTokens = (_b = attributes[Attrs.USAGE_OUTPUT_TOKENS]) != null ? _b : attributes[Attrs.USAGE_COMPLETION_TOKENS];
2003
2087
  if (typeof inputTokens === "number") result.inputTokens = inputTokens;
2004
2088
  if (typeof outputTokens === "number") result.outputTokens = outputTokens;
2005
2089
  if (result.inputTokens !== void 0 && result.outputTokens !== void 0) {
@@ -2013,12 +2097,29 @@ var OtelGenAiTransformer = class {
2013
2097
  if (typeof temperature === "number") {
2014
2098
  result.settings = { ...result.settings, temperature };
2015
2099
  }
2016
- const inputMessages = (_a = attributes[Attrs.INPUT_MESSAGES]) != null ? _a : attributes[Attrs.REQUEST_INPUT_FALLBACK];
2100
+ const inputMessages = (_d = (_c = attributes[Attrs.INPUT_MESSAGES]) != null ? _c : attributes[Attrs.REQUEST_INPUT_FALLBACK]) != null ? _d : attributes[Attrs.LEGACY_PROMPT];
2017
2101
  if (inputMessages && typeof inputMessages === "string") {
2018
2102
  const messages = normalizeMessages(inputMessages);
2019
2103
  if (messages) result.input = messages;
2020
2104
  }
2021
- const outputMessages = (_b = attributes[Attrs.OUTPUT_MESSAGES]) != null ? _b : attributes[Attrs.RESPONSE_OUTPUT_FALLBACK];
2105
+ const systemInstructions = attributes[Attrs.SYSTEM_INSTRUCTIONS];
2106
+ if (systemInstructions && typeof systemInstructions === "string") {
2107
+ let text = null;
2108
+ try {
2109
+ const parsed = JSON.parse(systemInstructions);
2110
+ if (Array.isArray(parsed)) {
2111
+ text = partsToText(parsed) || null;
2112
+ } else if (typeof parsed === "string") {
2113
+ text = parsed || null;
2114
+ }
2115
+ } catch {
2116
+ text = systemInstructions;
2117
+ }
2118
+ if (text && (!result.input || ((_e = result.input[0]) == null ? void 0 : _e.role) !== "system")) {
2119
+ result.input = [{ role: "system", content: text }, ...(_f = result.input) != null ? _f : []];
2120
+ }
2121
+ }
2122
+ const outputMessages = (_h = (_g = attributes[Attrs.OUTPUT_MESSAGES]) != null ? _g : attributes[Attrs.RESPONSE_OUTPUT_FALLBACK]) != null ? _h : attributes[Attrs.LEGACY_COMPLETION];
2022
2123
  if (outputMessages && typeof outputMessages === "string") {
2023
2124
  const extracted = extractStructuredOutput(outputMessages);
2024
2125
  if (extracted) {
@@ -2026,6 +2127,8 @@ var OtelGenAiTransformer = class {
2026
2127
  if (extracted.outputObject) {
2027
2128
  result.outputObject = extracted.outputObject;
2028
2129
  }
2130
+ } else {
2131
+ result.output = outputMessages;
2029
2132
  }
2030
2133
  }
2031
2134
  const allMessages = attributes["pydantic_ai.all_messages"];
@@ -2270,7 +2373,7 @@ function resolveSemanticKind(normalized, allAttributes) {
2270
2373
  // src/normalizer/type-classifier.ts
2271
2374
  var TypeClassifier = class {
2272
2375
  classify(span, attributes) {
2273
- if (attributes["gen_ai.system"] || attributes["gen_ai.request.model"] || attributes["gen_ai.operation.name"]) {
2376
+ if (attributes["gen_ai.system"] || attributes["gen_ai.provider.name"] || attributes["gen_ai.request.model"] || attributes["gen_ai.operation.name"]) {
2274
2377
  return "GENERATION" /* GENERATION */;
2275
2378
  }
2276
2379
  if (attributes["ai.response.text"] || attributes["ai.result.text"] || attributes["ai.response.toolCalls"] || attributes["ai.result.toolCalls"]) {
@@ -2290,6 +2393,28 @@ registry.register("default-tracer", new MastraTransformer());
2290
2393
  registry.register("agentmark", new AgentMarkTransformer());
2291
2394
  registry.register("pydantic-ai", new OtelGenAiTransformer());
2292
2395
  registry.setDefault(new OtelGenAiTransformer());
2396
+ var OTLP_STATUS_CODE_MAP = {
2397
+ "0": "0",
2398
+ STATUS_CODE_UNSET: "0",
2399
+ UNSET: "0",
2400
+ Unset: "0",
2401
+ "1": "1",
2402
+ STATUS_CODE_OK: "1",
2403
+ OK: "1",
2404
+ Ok: "1",
2405
+ "2": "2",
2406
+ STATUS_CODE_ERROR: "2",
2407
+ ERROR: "2",
2408
+ Error: "2"
2409
+ };
2410
+ function normalizeOtlpStatusCode(raw) {
2411
+ var _a;
2412
+ if (raw === void 0 || raw === null || raw === "") {
2413
+ return "0";
2414
+ }
2415
+ const key = String(raw);
2416
+ return (_a = OTLP_STATUS_CODE_MAP[key]) != null ? _a : key;
2417
+ }
2293
2418
  function normalizeSpan(resource, scope, span) {
2294
2419
  var _a, _b, _c;
2295
2420
  const allAttributes = {
@@ -2322,7 +2447,7 @@ function normalizeSpan(resource, scope, span) {
2322
2447
  name: span.name,
2323
2448
  kind: span.kind.toString(),
2324
2449
  serviceName: (_a = resource.attributes) == null ? void 0 : _a["service.name"],
2325
- statusCode: ((_b = span.status) == null ? void 0 : _b.code.toString()) || "0",
2450
+ statusCode: normalizeOtlpStatusCode((_b = span.status) == null ? void 0 : _b.code),
2326
2451
  statusMessage: (_c = span.status) == null ? void 0 : _c.message,
2327
2452
  // Raw Data
2328
2453
  resourceAttributes: resource.attributes || {},
@@ -2345,6 +2470,9 @@ function normalizeSpan(resource, scope, span) {
2345
2470
  }
2346
2471
  const agentMarkAttributes = parseAgentMarkAttributes(allAttributes);
2347
2472
  Object.assign(normalized, agentMarkAttributes);
2473
+ if (!normalized.sessionId && allAttributes["gen_ai.conversation.id"]) {
2474
+ normalized.sessionId = String(allAttributes["gen_ai.conversation.id"]);
2475
+ }
2348
2476
  normalized.semanticKind = resolveSemanticKind(normalized, allAttributes);
2349
2477
  return normalized;
2350
2478
  }
@@ -2358,6 +2486,30 @@ function normalizeOtlpSpans(resourceSpans) {
2358
2486
  }
2359
2487
  return normalizedSpans;
2360
2488
  }
2489
+
2490
+ // src/trace-io.ts
2491
+ function present(v) {
2492
+ if (v === null || v === void 0) return false;
2493
+ if (typeof v === "string") return v.length > 0;
2494
+ return true;
2495
+ }
2496
+ function deriveTraceIO(spans) {
2497
+ var _a, _b;
2498
+ const rootSpan = (_a = spans.find((s) => !s.parentId)) != null ? _a : spans[0];
2499
+ const generationSpans = spans.filter((s) => s.type === "GENERATION").sort((a, b) => {
2500
+ var _a2, _b2;
2501
+ const ta = (_a2 = a.timestamp) != null ? _a2 : 0;
2502
+ const tb = (_b2 = b.timestamp) != null ? _b2 : 0;
2503
+ return ta < tb ? -1 : ta > tb ? 1 : 0;
2504
+ });
2505
+ const input = present(rootSpan == null ? void 0 : rootSpan.input) ? rootSpan == null ? void 0 : rootSpan.input : (_b = generationSpans.find((s) => present(s.input))) == null ? void 0 : _b.input;
2506
+ const lastGenWithOutput = [...generationSpans].reverse().find((s) => present(s.output));
2507
+ const output = present(rootSpan == null ? void 0 : rootSpan.output) ? rootSpan == null ? void 0 : rootSpan.output : lastGenWithOutput == null ? void 0 : lastGenWithOutput.output;
2508
+ return {
2509
+ ...present(input) ? { input } : {},
2510
+ ...present(output) ? { output } : {}
2511
+ };
2512
+ }
2361
2513
  // Annotate the CommonJS export names for ESM import in node:
2362
2514
  0 && (module.exports = {
2363
2515
  AGENTMARK_SCOPE_NAME,
@@ -2372,6 +2524,7 @@ function normalizeOtlpSpans(resourceSpans) {
2372
2524
  TypeClassifier,
2373
2525
  convertOtlpAttributes,
2374
2526
  createSignature,
2527
+ deriveTraceIO,
2375
2528
  detectVersion,
2376
2529
  extractCustomMetadata,
2377
2530
  extractReasoningFromProviderMetadata,
@@ -2381,6 +2534,7 @@ function normalizeOtlpSpans(resourceSpans) {
2381
2534
  generateTypeDefinitions,
2382
2535
  generateUnique8CharString,
2383
2536
  normalizeOtlpSpans,
2537
+ normalizeOtlpStatusCode,
2384
2538
  normalizeSpan,
2385
2539
  parseAgentMarkAttributes,
2386
2540
  parseMetadata,