@agentmark-ai/shared-utils 0.3.1 → 0.3.3

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
@@ -219,6 +219,7 @@ interface NormalizedSpan {
219
219
  duration: number;
220
220
  name: string;
221
221
  kind: string;
222
+ semanticKind?: string;
222
223
  serviceName?: string;
223
224
  statusCode: string;
224
225
  statusMessage?: string;
@@ -443,6 +444,27 @@ declare function extractCustomMetadata(attributes: Record<string, any>, prefix?:
443
444
  */
444
445
  declare function parseAgentMarkAttributes(attributes: Record<string, any>, prefix?: string): Partial<NormalizedSpan>;
445
446
 
447
+ /** Valid semantic kind values. */
448
+ declare const SEMANTIC_KINDS: readonly ["function", "llm", "tool", "agent", "retrieval", "embedding", "guardrail"];
449
+ type SemanticKind = typeof SEMANTIC_KINDS[number];
450
+ /**
451
+ * Resolve the semantic kind of a span using an 8-level priority chain.
452
+ *
453
+ * Priority:
454
+ * 1. normalized.semanticKind (from agentmark.span.kind attribute) — if valid
455
+ * 2. openinference.span.kind attribute
456
+ * 3. Framework-specific attributes (Vercel AI SDK, Traceloop, LangChain, Genkit)
457
+ * 4. gen_ai.operation.name → llm/embedding
458
+ * 5. Type = GENERATION → llm
459
+ * 6. Has non-empty ToolCalls → tool
460
+ * 7. Name-based heuristics
461
+ * 8. Default → function
462
+ */
463
+ declare function resolveSemanticKind(normalized: Partial<NormalizedSpan> & {
464
+ type: SpanType;
465
+ name: string;
466
+ }, allAttributes: Record<string, any>): SemanticKind;
467
+
446
468
  declare class AiSdkTransformer implements ScopeTransformer {
447
469
  private strategies;
448
470
  constructor();
@@ -536,4 +558,4 @@ declare function normalizeSpan(resource: OtelResource, scope: OtelScope, span: O
536
558
  */
537
559
  declare function normalizeOtlpSpans(resourceSpans: OtlpResourceSpans[]): NormalizedSpan[];
538
560
 
539
- 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, type ScopeTransformer, 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, toFrontMatter, typeClassifier, verifySignature };
561
+ 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 };
package/dist/index.d.ts CHANGED
@@ -219,6 +219,7 @@ interface NormalizedSpan {
219
219
  duration: number;
220
220
  name: string;
221
221
  kind: string;
222
+ semanticKind?: string;
222
223
  serviceName?: string;
223
224
  statusCode: string;
224
225
  statusMessage?: string;
@@ -443,6 +444,27 @@ declare function extractCustomMetadata(attributes: Record<string, any>, prefix?:
443
444
  */
444
445
  declare function parseAgentMarkAttributes(attributes: Record<string, any>, prefix?: string): Partial<NormalizedSpan>;
445
446
 
447
+ /** Valid semantic kind values. */
448
+ declare const SEMANTIC_KINDS: readonly ["function", "llm", "tool", "agent", "retrieval", "embedding", "guardrail"];
449
+ type SemanticKind = typeof SEMANTIC_KINDS[number];
450
+ /**
451
+ * Resolve the semantic kind of a span using an 8-level priority chain.
452
+ *
453
+ * Priority:
454
+ * 1. normalized.semanticKind (from agentmark.span.kind attribute) — if valid
455
+ * 2. openinference.span.kind attribute
456
+ * 3. Framework-specific attributes (Vercel AI SDK, Traceloop, LangChain, Genkit)
457
+ * 4. gen_ai.operation.name → llm/embedding
458
+ * 5. Type = GENERATION → llm
459
+ * 6. Has non-empty ToolCalls → tool
460
+ * 7. Name-based heuristics
461
+ * 8. Default → function
462
+ */
463
+ declare function resolveSemanticKind(normalized: Partial<NormalizedSpan> & {
464
+ type: SpanType;
465
+ name: string;
466
+ }, allAttributes: Record<string, any>): SemanticKind;
467
+
446
468
  declare class AiSdkTransformer implements ScopeTransformer {
447
469
  private strategies;
448
470
  constructor();
@@ -536,4 +558,4 @@ declare function normalizeSpan(resource: OtelResource, scope: OtelScope, span: O
536
558
  */
537
559
  declare function normalizeOtlpSpans(resourceSpans: OtlpResourceSpans[]): NormalizedSpan[];
538
560
 
539
- 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, type ScopeTransformer, 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, toFrontMatter, typeClassifier, verifySignature };
561
+ 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 };
package/dist/index.js CHANGED
@@ -36,6 +36,7 @@ __export(index_exports, {
36
36
  ClaudeAgentTransformer: () => AgentMarkTransformer,
37
37
  MastraTransformer: () => MastraTransformer,
38
38
  OtelGenAiTransformer: () => OtelGenAiTransformer,
39
+ SEMANTIC_KINDS: () => SEMANTIC_KINDS,
39
40
  SpanType: () => SpanType,
40
41
  TransformerRegistry: () => TransformerRegistry,
41
42
  TypeClassifier: () => TypeClassifier,
@@ -55,6 +56,7 @@ __export(index_exports, {
55
56
  parseMetadata: () => parseMetadata,
56
57
  parseTokens: () => parseTokens,
57
58
  registry: () => registry,
59
+ resolveSemanticKind: () => resolveSemanticKind,
58
60
  toFrontMatter: () => toFrontMatter,
59
61
  typeClassifier: () => typeClassifier,
60
62
  verifySignature: () => verifySignature
@@ -226,27 +228,26 @@ async function generateTypeDefinitionsV1_0(prompts) {
226
228
  for (const prompt of prompts) {
227
229
  const { path: promptPath, input_schema } = prompt;
228
230
  const name = getInterfaceName(promptPath);
229
- let tools = {};
230
231
  try {
231
232
  let kind = "text";
232
233
  let output_schema = null;
234
+ let hasTools = false;
233
235
  if ("text_config" in prompt) {
234
236
  kind = "text";
235
- tools = prompt.text_config.tools || {};
237
+ hasTools = Array.isArray(prompt.text_config.tools) ? prompt.text_config.tools.length > 0 : !!prompt.text_config.tools;
236
238
  } else if ("object_config" in prompt) {
237
239
  kind = "object";
238
- tools = prompt.object_config.tools || {};
240
+ hasTools = Array.isArray(prompt.object_config.tools) ? prompt.object_config.tools.length > 0 : !!prompt.object_config.tools;
239
241
  output_schema = prompt.object_config.schema;
240
242
  } else if ("image_config" in prompt) {
241
243
  kind = "image";
242
- tools = prompt.image_config.tools || {};
244
+ hasTools = Array.isArray(prompt.image_config.tools) ? prompt.image_config.tools.length > 0 : !!prompt.image_config.tools;
243
245
  }
244
246
  const compile = await getCompile();
245
247
  const inputInterface = input_schema ? await compile(input_schema, `${name}In`, {
246
248
  bannerComment: "",
247
249
  additionalProperties: false
248
250
  }) : `interface ${name}In { [key: string]: any }`;
249
- const toolTypes = await generateToolTypes(tools);
250
251
  const outputInterface = output_schema ? await compile(output_schema, `${name}Out`, {
251
252
  bannerComment: "",
252
253
  additionalProperties: false
@@ -255,12 +256,11 @@ async function generateTypeDefinitionsV1_0(prompts) {
255
256
  inputInterface.replace("export interface", "interface"),
256
257
  outputInterface.replace("export type", "type").replace("export interface", "interface")
257
258
  );
258
- output += toolTypes || "";
259
259
  output += `type ${name} = {
260
260
  kind: '${kind}';
261
261
  input: ${name}In;
262
- output: ${name}Out;${toolTypes ? `
263
- tools?: Array<keyof Tools>;` : ""}
262
+ output: ${name}Out;${hasTools ? `
263
+ tools?: string[];` : ""}
264
264
  };
265
265
 
266
266
  `;
@@ -687,6 +687,7 @@ async function generateTypeDefinitions(prompts, language = "typescript") {
687
687
  return generateTypeDefinitionsV0(prompts);
688
688
  }
689
689
  async function fetchPromptsFrontmatter(options) {
690
+ var _a, _b, _c;
690
691
  if (options.local) {
691
692
  const baseUrl = `http://localhost:${options.local}`;
692
693
  try {
@@ -696,7 +697,8 @@ async function fetchPromptsFrontmatter(options) {
696
697
  `Failed to fetch prompt paths: ${pathsResponse.statusText}`
697
698
  );
698
699
  }
699
- const { paths } = await pathsResponse.json();
700
+ const body = await pathsResponse.json();
701
+ const paths = (_c = (_b = (_a = body == null ? void 0 : body.data) == null ? void 0 : _a.paths) != null ? _b : body == null ? void 0 : body.paths) != null ? _c : [];
700
702
  return Promise.all(
701
703
  paths.map(async (promptPath) => {
702
704
  const templateResponse = await fetch(
@@ -762,34 +764,6 @@ async function fetchPromptsFrontmatter(options) {
762
764
  }
763
765
  throw new Error("Either --local or --root-dir must be specified");
764
766
  }
765
- async function generateToolTypes(tools) {
766
- const toolArgTypes = [];
767
- for (const [toolName, schema] of Object.entries(tools)) {
768
- const typeName = `${getToolInterfaceName(toolName)}Args`;
769
- try {
770
- const compile = await getCompile();
771
- const argInterface = schema.parameters ? await compile(schema.parameters, typeName, {
772
- bannerComment: "",
773
- additionalProperties: false
774
- }) : `type ${typeName} = { ${Object.entries(schema.parameters || {}).map(([key]) => `${key}: any`).join("; ")} };`;
775
- toolArgTypes.push(
776
- argInterface.replace("export type", "type").replace("export interface", "interface")
777
- );
778
- } catch (error) {
779
- console.error(`Error processing tool ${toolName}:`, error);
780
- toolArgTypes.push(`type ${typeName} = { [key: string]: any };`);
781
- }
782
- }
783
- if (Object.keys(tools).length > 0) {
784
- const toolsInterface = `export interface Tools {
785
- ${Object.keys(tools).map(
786
- (toolName) => ` ${toolName}: { args: ${getToolInterfaceName(toolName)}Args };`
787
- ).join("\n")}
788
- }`;
789
- return toolArgTypes.join("\n\n") + "\n\n" + toolsInterface + "\n\n";
790
- }
791
- return null;
792
- }
793
767
 
794
768
  // src/normalizer/types.ts
795
769
  var SpanType = /* @__PURE__ */ ((SpanType2) => {
@@ -889,8 +863,7 @@ var KNOWN_METADATA_FIELDS = /* @__PURE__ */ new Set([
889
863
  "dataset_expected_output",
890
864
  "dataset_input",
891
865
  "prompt_name",
892
- "props",
893
- "commit_sha"
866
+ "props"
894
867
  ]);
895
868
  function parseMetadata(attributes, prefix = "agentmark.metadata.") {
896
869
  const result = {};
@@ -1675,7 +1648,7 @@ function parseAgentMarkAttributes(attributes, prefix = "agentmark.") {
1675
1648
  if (get("trace_name")) result.traceName = String(get("trace_name"));
1676
1649
  if (get("prompt_name")) result.promptName = String(get("prompt_name"));
1677
1650
  if (get("props")) result.props = String(get("props"));
1678
- if (get("span.kind")) result.kind = String(get("span.kind"));
1651
+ if (get("span.kind")) result.semanticKind = String(get("span.kind"));
1679
1652
  if (get("dataset_run_id")) result.datasetRunId = String(get("dataset_run_id"));
1680
1653
  if (get("dataset_run_name")) result.datasetRunName = String(get("dataset_run_name"));
1681
1654
  if (get("dataset_item_name")) result.datasetItemName = String(get("dataset_item_name"));
@@ -1745,6 +1718,9 @@ var AgentMarkTransformer = class {
1745
1718
  if (operationName === OperationNames.CHAT || operationName === OperationNames.TEXT_COMPLETION) {
1746
1719
  return "GENERATION" /* GENERATION */;
1747
1720
  }
1721
+ if (operationName === OperationNames.EMBEDDINGS) {
1722
+ return "GENERATION" /* GENERATION */;
1723
+ }
1748
1724
  if (span.name === SpanNames.CHAT || span.name.startsWith(SpanNames.CHAT + " ")) {
1749
1725
  return "GENERATION" /* GENERATION */;
1750
1726
  }
@@ -1774,6 +1750,7 @@ var AgentMarkTransformer = class {
1774
1750
  * Transform the span and extract normalized fields from GenAI attributes.
1775
1751
  */
1776
1752
  transform(_span, attributes) {
1753
+ var _a;
1777
1754
  const result = {};
1778
1755
  const responseModel = attributes[GenAIAttributes.RESPONSE_MODEL];
1779
1756
  const requestModel = attributes[GenAIAttributes.REQUEST_MODEL];
@@ -1847,7 +1824,7 @@ var AgentMarkTransformer = class {
1847
1824
  } catch {
1848
1825
  }
1849
1826
  }
1850
- const amInput = attributes["agentmark.input"];
1827
+ const amInput = (_a = attributes["agentmark.input"]) != null ? _a : attributes["agentmark.props"];
1851
1828
  if (amInput && typeof amInput === "string" && !result.input) {
1852
1829
  result.input = [{ role: "user", content: amInput }];
1853
1830
  }
@@ -1913,9 +1890,16 @@ var Attrs = {
1913
1890
  RESPONSE_FINISH_REASONS: "gen_ai.response.finish_reasons",
1914
1891
  USAGE_INPUT_TOKENS: "gen_ai.usage.input_tokens",
1915
1892
  USAGE_OUTPUT_TOKENS: "gen_ai.usage.output_tokens",
1916
- // v1.37.0+ content attributes
1893
+ // v1.37.0+ content attributes (canonical OTel GenAI semantic conventions).
1894
+ // SDKs that emit the AgentMark-scoped equivalents (`gen_ai.request.input`
1895
+ // / `gen_ai.response.output` — used by `claude-agent-sdk-v0-adapter`) are
1896
+ // also accepted here as fallbacks so an SDK picking either key set
1897
+ // doesn't silently lose IO data on ingest. The canonical pair always wins
1898
+ // when both are present.
1917
1899
  INPUT_MESSAGES: "gen_ai.input.messages",
1918
1900
  OUTPUT_MESSAGES: "gen_ai.output.messages",
1901
+ REQUEST_INPUT_FALLBACK: "gen_ai.request.input",
1902
+ RESPONSE_OUTPUT_FALLBACK: "gen_ai.response.output",
1919
1903
  SYSTEM_INSTRUCTIONS: "gen_ai.system_instructions",
1920
1904
  TOOL_DEFINITIONS: "gen_ai.tool.definitions",
1921
1905
  // Tool call attributes (v1.37.0+)
@@ -1980,6 +1964,7 @@ var OtelGenAiTransformer = class {
1980
1964
  return "SPAN" /* SPAN */;
1981
1965
  }
1982
1966
  transform(span, attributes) {
1967
+ var _a, _b;
1983
1968
  const result = {};
1984
1969
  const model = attributes[Attrs.RESPONSE_MODEL] || attributes[Attrs.REQUEST_MODEL];
1985
1970
  if (model && typeof model === "string") {
@@ -2000,12 +1985,12 @@ var OtelGenAiTransformer = class {
2000
1985
  if (typeof temperature === "number") {
2001
1986
  result.settings = { ...result.settings, temperature };
2002
1987
  }
2003
- const inputMessages = attributes[Attrs.INPUT_MESSAGES];
1988
+ const inputMessages = (_a = attributes[Attrs.INPUT_MESSAGES]) != null ? _a : attributes[Attrs.REQUEST_INPUT_FALLBACK];
2004
1989
  if (inputMessages && typeof inputMessages === "string") {
2005
1990
  const messages = normalizeMessages(inputMessages);
2006
1991
  if (messages) result.input = messages;
2007
1992
  }
2008
- const outputMessages = attributes[Attrs.OUTPUT_MESSAGES];
1993
+ const outputMessages = (_b = attributes[Attrs.OUTPUT_MESSAGES]) != null ? _b : attributes[Attrs.RESPONSE_OUTPUT_FALLBACK];
2009
1994
  if (outputMessages && typeof outputMessages === "string") {
2010
1995
  const extracted = extractStructuredOutput(outputMessages);
2011
1996
  if (extracted) {
@@ -2167,6 +2152,83 @@ function extractResourceScopeSpan(resourceSpans) {
2167
2152
  return result;
2168
2153
  }
2169
2154
 
2155
+ // src/normalizer/resolvers/semantic-kind-resolver.ts
2156
+ var SEMANTIC_KINDS = ["function", "llm", "tool", "agent", "retrieval", "embedding", "guardrail"];
2157
+ var VALID_KINDS = new Set(SEMANTIC_KINDS);
2158
+ var OPENINFERENCE_MAP = {
2159
+ "CHAIN": "function",
2160
+ "LLM": "llm",
2161
+ "TOOL": "tool",
2162
+ "AGENT": "agent",
2163
+ "RETRIEVER": "retrieval",
2164
+ "EMBEDDING": "embedding",
2165
+ "GUARDRAIL": "guardrail",
2166
+ "RERANKER": "retrieval"
2167
+ };
2168
+ var FRAMEWORK_MAPPINGS = [
2169
+ {
2170
+ key: "ai.operationId",
2171
+ // Vercel AI SDK
2172
+ map: {
2173
+ "embed": "embedding",
2174
+ "ai.embed": "embedding",
2175
+ "generateText": "llm",
2176
+ "streamText": "llm",
2177
+ "generateObject": "llm",
2178
+ "streamObject": "llm"
2179
+ }
2180
+ },
2181
+ {
2182
+ key: "traceloop.span.kind",
2183
+ // Traceloop / OpenLLMetry
2184
+ map: { "LLM": "llm", "TOOL": "tool", "AGENT": "agent", "WORKFLOW": "function", "TASK": "function" }
2185
+ },
2186
+ {
2187
+ key: "langchain.run_type",
2188
+ // LangChain via OTLP
2189
+ map: { "llm": "llm", "chat_model": "llm", "retriever": "retrieval", "tool": "tool", "chain": "function", "embedding": "embedding" }
2190
+ },
2191
+ {
2192
+ key: "genkit:type",
2193
+ // Firebase Genkit
2194
+ map: { "model": "llm", "tool": "tool", "flow": "function", "retriever": "retrieval", "embedder": "embedding" }
2195
+ }
2196
+ ];
2197
+ function resolveSemanticKind(normalized, allAttributes) {
2198
+ if (normalized.semanticKind && VALID_KINDS.has(normalized.semanticKind)) {
2199
+ return normalized.semanticKind;
2200
+ }
2201
+ const oiKind = allAttributes["openinference.span.kind"];
2202
+ if (oiKind) {
2203
+ const mapped = OPENINFERENCE_MAP[String(oiKind).toUpperCase()];
2204
+ if (mapped) return mapped;
2205
+ }
2206
+ for (const { key, map } of FRAMEWORK_MAPPINGS) {
2207
+ const val = allAttributes[key];
2208
+ if (val) {
2209
+ const mapped = map[String(val)];
2210
+ if (mapped) return mapped;
2211
+ }
2212
+ }
2213
+ const opName = allAttributes["gen_ai.operation.name"];
2214
+ if (opName) {
2215
+ const op = String(opName).toLowerCase();
2216
+ if (op === "chat" || op === "text_completion" || op === "generate_content") return "llm";
2217
+ if (op === "embeddings") return "embedding";
2218
+ }
2219
+ if (normalized.type === "GENERATION" /* GENERATION */) {
2220
+ return "llm";
2221
+ }
2222
+ if (normalized.toolCalls && normalized.toolCalls.length > 0) {
2223
+ return "tool";
2224
+ }
2225
+ const name = (normalized.name || "").toLowerCase();
2226
+ if (/retriev|search|rag/i.test(name)) return "retrieval";
2227
+ if (/embed/i.test(name)) return "embedding";
2228
+ if (/guard|safety/i.test(name)) return "guardrail";
2229
+ return "function";
2230
+ }
2231
+
2170
2232
  // src/normalizer/type-classifier.ts
2171
2233
  var TypeClassifier = class {
2172
2234
  classify(span, attributes) {
@@ -2245,6 +2307,7 @@ function normalizeSpan(resource, scope, span) {
2245
2307
  }
2246
2308
  const agentMarkAttributes = parseAgentMarkAttributes(allAttributes);
2247
2309
  Object.assign(normalized, agentMarkAttributes);
2310
+ normalized.semanticKind = resolveSemanticKind(normalized, allAttributes);
2248
2311
  return normalized;
2249
2312
  }
2250
2313
  function normalizeOtlpSpans(resourceSpans) {
@@ -2265,6 +2328,7 @@ function normalizeOtlpSpans(resourceSpans) {
2265
2328
  ClaudeAgentTransformer,
2266
2329
  MastraTransformer,
2267
2330
  OtelGenAiTransformer,
2331
+ SEMANTIC_KINDS,
2268
2332
  SpanType,
2269
2333
  TransformerRegistry,
2270
2334
  TypeClassifier,
@@ -2284,6 +2348,7 @@ function normalizeOtlpSpans(resourceSpans) {
2284
2348
  parseMetadata,
2285
2349
  parseTokens,
2286
2350
  registry,
2351
+ resolveSemanticKind,
2287
2352
  toFrontMatter,
2288
2353
  typeClassifier,
2289
2354
  verifySignature